morpheus-cli 3.3.2.7 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/morpheus/api/account_groups_interface.rb +54 -0
- data/lib/morpheus/api/api_client.rb +4 -0
- data/lib/morpheus/api/virtual_images_interface.rb +14 -9
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/cli/account_groups_command.rb +555 -0
- data/lib/morpheus/cli/accounts.rb +8 -0
- data/lib/morpheus/cli/groups.rb +1 -1
- data/lib/morpheus/cli/policies_command.rb +3 -2
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +236 -123
- metadata +4 -2
@@ -14,6 +14,9 @@ class Morpheus::Cli::Accounts
|
|
14
14
|
alias_subcommand :details, :get
|
15
15
|
set_default_subcommand :list
|
16
16
|
|
17
|
+
# account-groups is under this namespace for now
|
18
|
+
register_subcommands :'groups' => :account_groups
|
19
|
+
|
17
20
|
def initialize()
|
18
21
|
@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
19
22
|
end
|
@@ -29,6 +32,10 @@ class Morpheus::Cli::Accounts
|
|
29
32
|
handle_subcommand(args)
|
30
33
|
end
|
31
34
|
|
35
|
+
def account_groups(args)
|
36
|
+
Morpheus::Cli::AccountGroupsCommand.new.handle(args)
|
37
|
+
end
|
38
|
+
|
32
39
|
def list(args)
|
33
40
|
options = {}
|
34
41
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
@@ -131,6 +138,7 @@ class Morpheus::Cli::Accounts
|
|
131
138
|
puts "ID: #{account['id']}"
|
132
139
|
puts "Name: #{account['name']}"
|
133
140
|
puts "Description: #{account['description']}"
|
141
|
+
puts "Subdomain: #{account['subdomain']}" if !account['subdomain'].to_s.empty?
|
134
142
|
puts "Currency: #{account['currency']}"
|
135
143
|
# puts "# Users: #{account['usersCount']}"
|
136
144
|
# puts "# Instances: #{account['instancesCount']}"
|
data/lib/morpheus/cli/groups.rb
CHANGED
@@ -54,7 +54,7 @@ class Morpheus::Cli::Groups
|
|
54
54
|
groups = json_response['groups']
|
55
55
|
print_h1 "Morpheus Groups"
|
56
56
|
if groups.empty?
|
57
|
-
|
57
|
+
print yellow,"No groups currently configured.",reset,"\n"
|
58
58
|
else
|
59
59
|
print_groups_table(groups)
|
60
60
|
print_results_pagination(json_response)
|
@@ -826,8 +826,9 @@ class Morpheus::Cli::PoliciesCommand
|
|
826
826
|
|
827
827
|
def format_tenants(accounts)
|
828
828
|
if accounts && accounts.size > 0
|
829
|
-
|
830
|
-
|
829
|
+
accounts = accounts.sort {|it| it['name'] }.uniq {|it| it['id'] }
|
830
|
+
account_ids = accounts.collect {|it| it['id'] }
|
831
|
+
account_names = accounts.collect {|it| it['name'] }
|
831
832
|
"(#{account_ids.join(',')}) #{account_names.join(',')}"
|
832
833
|
else
|
833
834
|
""
|
data/lib/morpheus/cli/version.rb
CHANGED
@@ -29,7 +29,7 @@ class Morpheus::Cli::VirtualImages
|
|
29
29
|
|
30
30
|
def list(args)
|
31
31
|
options = {}
|
32
|
-
optparse = OptionParser.new do|opts|
|
32
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
33
33
|
opts.banner = subcommand_usage()
|
34
34
|
opts.on( '-t', '--type IMAGE_TYPE', "Image Type" ) do |val|
|
35
35
|
options[:imageType] = val.downcase
|
@@ -43,15 +43,14 @@ class Morpheus::Cli::VirtualImages
|
|
43
43
|
opts.on('--system', "System Images" ) do
|
44
44
|
options[:filterType] = 'System'
|
45
45
|
end
|
46
|
-
build_common_options(opts, options, [:list, :json, :dry_run, :remote])
|
46
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
47
|
+
opts.footer = "List virtual images."
|
47
48
|
end
|
48
49
|
optparse.parse!(args)
|
49
50
|
connect(options)
|
50
51
|
begin
|
51
52
|
params = {}
|
52
|
-
|
53
|
-
params[k] = options[k] unless options[k].nil?
|
54
|
-
end
|
53
|
+
params.merge!(parse_list_options(options))
|
55
54
|
if options[:imageType]
|
56
55
|
params[:imageType] = options[:imageType]
|
57
56
|
end
|
@@ -63,38 +62,50 @@ class Morpheus::Cli::VirtualImages
|
|
63
62
|
return
|
64
63
|
end
|
65
64
|
json_response = @virtual_images_interface.get(params)
|
65
|
+
|
66
66
|
if options[:json]
|
67
|
-
|
67
|
+
puts as_json(json_response, options, "virtualImages")
|
68
|
+
return 0
|
69
|
+
elsif options[:yaml]
|
70
|
+
puts as_yaml(json_response, options, "virtualImages")
|
71
|
+
return 0
|
72
|
+
elsif options[:csv]
|
73
|
+
puts records_as_csv(json_response["virtualImages"], options)
|
74
|
+
return 0
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
images = json_response['virtualImages']
|
79
|
+
title = "Morpheus Virtual Images"
|
80
|
+
subtitles = []
|
81
|
+
if options[:imageType]
|
82
|
+
subtitles << "Image Type: #{options[:imageType]}".strip
|
83
|
+
end
|
84
|
+
if options[:filterType]
|
85
|
+
subtitles << "Image Type: #{options[:filterType]}".strip
|
86
|
+
end
|
87
|
+
if params[:phrase]
|
88
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
89
|
+
end
|
90
|
+
print_h1 title, subtitles
|
91
|
+
if images.empty?
|
92
|
+
print yellow,"No virtual images found.",reset,"\n"
|
68
93
|
else
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
subtitles << "Image Type: #{options[:imageType]}".strip
|
94
|
+
rows = images.collect do |image|
|
95
|
+
image_type = virtual_image_type_for_name_or_code(image['imageType'])
|
96
|
+
image_type_display = image_type ? "#{image_type['name']}" : image['imageType']
|
97
|
+
{name: image['name'], id: image['id'], type: image_type_display, source: image['userUploaded'] ? "#{green}UPLOADED#{cyan}" : (image['systemImage'] ? 'SYSTEM' : "#{white}SYNCED#{cyan}"), storage: !image['storageProvider'].nil? ? image['storageProvider']['name'] : 'Default', size: image['rawSize'].nil? ? 'Unknown' : "#{Filesize.from("#{image['rawSize']} B").pretty}"}
|
74
98
|
end
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
81
|
-
print_h1 title, subtitles
|
82
|
-
if images.empty?
|
83
|
-
print yellow,"No virtual images found.",reset,"\n"
|
84
|
-
else
|
85
|
-
rows = images.collect do |image|
|
86
|
-
image_type = virtual_image_type_for_name_or_code(image['imageType'])
|
87
|
-
image_type_display = image_type ? "#{image_type['name']}" : image['imageType']
|
88
|
-
{name: image['name'], id: image['id'], type: image_type_display, source: image['userUploaded'] ? "#{green}UPLOADED#{cyan}" : (image['systemImage'] ? 'SYSTEM' : "#{white}SYNCED#{cyan}"), storage: !image['storageProvider'].nil? ? image['storageProvider']['name'] : 'Default', size: image['rawSize'].nil? ? 'Unknown' : "#{Filesize.from("#{image['rawSize']} B").pretty}"}
|
89
|
-
end
|
90
|
-
columns = [:id, :name, :type, :storage, :size, :source]
|
91
|
-
print cyan
|
92
|
-
print as_pretty_table(rows, columns, options)
|
93
|
-
print_results_pagination(json_response)
|
94
|
-
end
|
95
|
-
print reset,"\n"
|
99
|
+
columns = [:id, :name, :type, :storage, :size, :source]
|
100
|
+
columns = options[:include_fields] if options[:include_fields]
|
101
|
+
print cyan
|
102
|
+
print as_pretty_table(rows, columns, options)
|
103
|
+
print_results_pagination(json_response)
|
96
104
|
end
|
97
|
-
|
105
|
+
print reset,"\n"
|
106
|
+
|
107
|
+
return 0
|
108
|
+
rescue RestClient::Exception => e
|
98
109
|
print_rest_exception(e, options)
|
99
110
|
exit 1
|
100
111
|
end
|
@@ -102,9 +113,15 @@ class Morpheus::Cli::VirtualImages
|
|
102
113
|
|
103
114
|
def get(args)
|
104
115
|
options = {}
|
105
|
-
|
116
|
+
show_details = false
|
117
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
106
118
|
opts.banner = subcommand_usage("[name]")
|
107
|
-
|
119
|
+
opts.on('--details', "Show more details." ) do
|
120
|
+
show_details = true
|
121
|
+
end
|
122
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
123
|
+
opts.footer = "Get details about a virtual image." + "\n" +
|
124
|
+
"[name] is required. This is the name or id of a virtual image."
|
108
125
|
end
|
109
126
|
optparse.parse!(args)
|
110
127
|
if args.count < 1
|
@@ -126,48 +143,94 @@ class Morpheus::Cli::VirtualImages
|
|
126
143
|
return 1 if image.nil?
|
127
144
|
# refetch
|
128
145
|
json_response = @virtual_images_interface.get(image['id'])
|
146
|
+
if options[:json]
|
147
|
+
puts as_json(json_response, options, "virtualImage")
|
148
|
+
return 0
|
149
|
+
elsif options[:yaml]
|
150
|
+
puts as_yaml(json_response, options, "virtualImage")
|
151
|
+
return 0
|
152
|
+
elsif options[:csv]
|
153
|
+
puts records_as_csv([json_response["virtualImage"]], options)
|
154
|
+
return 0
|
155
|
+
end
|
156
|
+
|
129
157
|
image = json_response['virtualImage']
|
130
158
|
image_files = json_response['cloudFiles'] || json_response['files']
|
131
159
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
}
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
160
|
+
|
161
|
+
image_type = virtual_image_type_for_name_or_code(image['imageType'])
|
162
|
+
image_type_display = image_type ? "#{image_type['name']}" : image['imageType']
|
163
|
+
print_h1 "Virtual Image Details"
|
164
|
+
print cyan
|
165
|
+
description_cols = {
|
166
|
+
"ID" => 'id',
|
167
|
+
"Name" => 'name',
|
168
|
+
"Type" => lambda {|it| image_type_display },
|
169
|
+
"Storage" => lambda {|it| !image['storageProvider'].nil? ? image['storageProvider']['name'] : 'Default' },
|
170
|
+
"Size" => lambda {|it| image['rawSize'].nil? ? 'Unknown' : "#{Filesize.from("#{image['rawSize']} B").pretty}" },
|
171
|
+
"Source" => lambda {|it| image['userUploaded'] ? "#{green}UPLOADED#{cyan}" : (image['systemImage'] ? 'SYSTEM' : "#{white}SYNCED#{cyan}") },
|
172
|
+
# "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
173
|
+
# "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
174
|
+
}
|
175
|
+
advanced_description_cols = {
|
176
|
+
"OS Type" => lambda {|it| it['osType'] ? it['osType']['name'] : "" },
|
177
|
+
"Min Memory" => lambda {|it| it['minRam'].to_i != 0 ? Filesize.from("#{it['minRam']} B").pretty : "" },
|
178
|
+
"Cloud Init?" => lambda {|it| format_boolean it['osType'] },
|
179
|
+
"Install Agent?" => lambda {|it| format_boolean it['osType'] },
|
180
|
+
"SSH Username" => lambda {|it| it['sshUsername'] },
|
181
|
+
"SSH Password" => lambda {|it| it['sshPassword'] },
|
182
|
+
"User Data" => lambda {|it| it['userData'] },
|
183
|
+
"Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
|
184
|
+
"Tenants" => lambda {|it| format_tenants(it['accounts']) },
|
185
|
+
"Auto Join Domain?" => lambda {|it| format_boolean it['isAutoJoinDomain'] },
|
186
|
+
"VirtIO Drivers Loaded?" => lambda {|it| format_boolean it['virtioSupported'] },
|
187
|
+
"VM Tools Installed?" => lambda {|it| format_boolean it['vmToolsInstalled'] },
|
188
|
+
"Force Guest Customization?" => lambda {|it| format_boolean it['isForceCustomization'] },
|
189
|
+
"Trial Version" => lambda {|it| format_boolean it['trialVersion'] },
|
190
|
+
"Sysprep Enabled?" => lambda {|it| format_boolean it['isSysprep'] },
|
191
|
+
}
|
192
|
+
if show_details
|
193
|
+
description_cols.merge!(advanced_description_cols)
|
194
|
+
end
|
195
|
+
print_description_list(description_cols, image)
|
196
|
+
|
197
|
+
if image_files
|
198
|
+
print_h2 "Files (#{image_files.size})"
|
199
|
+
# image_files.each {|image_file|
|
200
|
+
# pretty_filesize = Filesize.from("#{image_file['size']} B").pretty
|
201
|
+
# print cyan," = #{image_file['name']} [#{pretty_filesize}]", "\n"
|
202
|
+
# }
|
203
|
+
image_file_rows = image_files.collect do |image_file|
|
204
|
+
|
205
|
+
{filename: image_file['name'], size: Filesize.from("#{image_file['size']} B").pretty}
|
154
206
|
end
|
155
|
-
print
|
207
|
+
print cyan
|
208
|
+
print as_pretty_table(image_file_rows, [:filename, :size])
|
209
|
+
# print reset,"\n"
|
156
210
|
end
|
211
|
+
print reset,"\n"
|
157
212
|
rescue RestClient::Exception => e
|
158
213
|
print_rest_exception(e, options)
|
159
214
|
exit 1
|
160
215
|
end
|
161
216
|
end
|
162
217
|
|
163
|
-
# JD: I don't think this has ever worked
|
164
218
|
def update(args)
|
165
219
|
image_name = args[0]
|
166
220
|
options = {}
|
167
|
-
|
168
|
-
optparse = OptionParser.new do|opts|
|
221
|
+
tenants_list = nil
|
222
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
169
223
|
opts.banner = subcommand_usage("[name] [options]")
|
170
|
-
|
224
|
+
opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
|
225
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
226
|
+
tenants_list = []
|
227
|
+
else
|
228
|
+
tenants_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
229
|
+
end
|
230
|
+
end
|
231
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
232
|
+
opts.footer = "Update a virtual image." + "\n" +
|
233
|
+
"[name] is required. This is the name or id of a virtual image."
|
171
234
|
end
|
172
235
|
optparse.parse!(args)
|
173
236
|
if args.count < 1
|
@@ -176,24 +239,31 @@ class Morpheus::Cli::VirtualImages
|
|
176
239
|
end
|
177
240
|
|
178
241
|
connect(options)
|
179
|
-
|
180
|
-
|
242
|
+
begin
|
181
243
|
image = find_virtual_image_by_name_or_id(image_name)
|
182
244
|
return 1 if image.nil?
|
183
245
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
246
|
+
payload = nil
|
247
|
+
if options[:payload]
|
248
|
+
payload = options[:payload]
|
249
|
+
# support -O OPTION switch on top of --payload
|
250
|
+
if options[:options]
|
251
|
+
payload['virtualImage'] ||= {}
|
252
|
+
payload['virtualImage'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
|
253
|
+
end
|
254
|
+
else
|
255
|
+
params = options[:options] || {}
|
256
|
+
if params.empty? && tenants_list.nil?
|
257
|
+
puts optparse
|
258
|
+
option_lines = update_virtual_image_option_types().collect {|it| "\t-O #{it['fieldContext'] ? (it['fieldContext'] + '.') : ''}#{it['fieldName']}=\"value\"" }.join("\n")
|
259
|
+
puts "\nAvailable Options:\n#{option_lines}\n\n"
|
260
|
+
exit 1
|
261
|
+
end
|
262
|
+
if tenants_list
|
263
|
+
params['accounts'] = tenants_list
|
264
|
+
end
|
265
|
+
payload = {'virtualImage' => params}
|
191
266
|
end
|
192
|
-
|
193
|
-
image_payload = {id: image['id']}
|
194
|
-
image_payload.merge(params)
|
195
|
-
# JD: what can be updated?
|
196
|
-
payload = {virtualImage: image_payload}
|
197
267
|
if options[:dry_run]
|
198
268
|
print_dry_run @virtual_images_interface.dry.update(image['id'], payload)
|
199
269
|
return
|
@@ -205,7 +275,7 @@ class Morpheus::Cli::VirtualImages
|
|
205
275
|
exit 1
|
206
276
|
end
|
207
277
|
else
|
208
|
-
print "\n", cyan, "
|
278
|
+
print "\n", cyan, "Virtual Image #{image['name']} updated", reset, "\n\n"
|
209
279
|
end
|
210
280
|
rescue RestClient::Exception => e
|
211
281
|
print_rest_exception(e, options)
|
@@ -215,7 +285,7 @@ class Morpheus::Cli::VirtualImages
|
|
215
285
|
|
216
286
|
def virtual_image_types(args)
|
217
287
|
options = {}
|
218
|
-
optparse = OptionParser.new do|opts|
|
288
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
219
289
|
opts.banner = subcommand_usage()
|
220
290
|
build_common_options(opts, options, [:json, :dry_run, :remote])
|
221
291
|
end
|
@@ -254,16 +324,29 @@ class Morpheus::Cli::VirtualImages
|
|
254
324
|
def add(args)
|
255
325
|
image_type_name = nil
|
256
326
|
file_url = nil
|
327
|
+
file_name = nil
|
328
|
+
tenants_list = nil
|
257
329
|
options = {}
|
258
|
-
optparse = OptionParser.new do|opts|
|
330
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
259
331
|
opts.banner = subcommand_usage("[name] -t TYPE")
|
260
332
|
opts.on( '-t', '--type TYPE', "Virtual Image Type" ) do |val|
|
261
333
|
image_type_name = val
|
262
334
|
end
|
335
|
+
opts.on( '--filename NAME', "Image File Name. Specify a name for the uploaded file." ) do |val|
|
336
|
+
file_name = val
|
337
|
+
end
|
263
338
|
opts.on( '-U', '--url URL', "Image File URL. This can be used instead of uploading local files." ) do |val|
|
264
339
|
file_url = val
|
265
340
|
end
|
341
|
+
opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
|
342
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
343
|
+
tenants_list = []
|
344
|
+
else
|
345
|
+
tenants_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
346
|
+
end
|
347
|
+
end
|
266
348
|
build_common_options(opts, options, [:options, :json, :dry_run, :remote])
|
349
|
+
opts.footer = "Create a virtual image."
|
267
350
|
end
|
268
351
|
optparse.parse!(args)
|
269
352
|
# if args.count < 1
|
@@ -304,6 +387,7 @@ class Morpheus::Cli::VirtualImages
|
|
304
387
|
# end
|
305
388
|
# end
|
306
389
|
params = Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, options[:params])
|
390
|
+
params.deep_compact!
|
307
391
|
virtual_image_payload = {}.merge(params)
|
308
392
|
virtual_image_files = virtual_image_payload.delete('virtualImageFiles')
|
309
393
|
virtual_image_payload['imageType'] = image_type['code']
|
@@ -311,15 +395,18 @@ class Morpheus::Cli::VirtualImages
|
|
311
395
|
if !storage_provider_id.to_s.empty?
|
312
396
|
virtual_image_payload['storageProvider'] = {id: storage_provider_id}
|
313
397
|
end
|
398
|
+
if tenants_list
|
399
|
+
virtual_image_payload['accounts'] = tenants_list
|
400
|
+
end
|
314
401
|
payload = {virtualImage: virtual_image_payload}
|
315
402
|
|
316
403
|
if options[:dry_run]
|
317
404
|
print_dry_run @virtual_images_interface.dry.create(payload)
|
318
405
|
if file_url
|
319
|
-
print_dry_run @virtual_images_interface.dry.upload_by_url(":id", file_url)
|
406
|
+
print_dry_run @virtual_images_interface.dry.upload_by_url(":id", file_url, file_name)
|
320
407
|
elsif virtual_image_files && !virtual_image_files.empty?
|
321
|
-
virtual_image_files.each do |key,
|
322
|
-
print_dry_run @virtual_images_interface.dry.upload(":id", "(Contents of file #{
|
408
|
+
virtual_image_files.each do |key, filepath|
|
409
|
+
print_dry_run @virtual_images_interface.dry.upload(":id", "(Contents of file #{filepath})")
|
323
410
|
end
|
324
411
|
end
|
325
412
|
return
|
@@ -339,17 +426,17 @@ class Morpheus::Cli::VirtualImages
|
|
339
426
|
unless options[:quiet]
|
340
427
|
print cyan, "Uploading file by url #{file_url} ...", reset, "\n"
|
341
428
|
end
|
342
|
-
upload_json_response = @virtual_images_interface.upload_by_url(virtual_image['id'], file_url)
|
429
|
+
upload_json_response = @virtual_images_interface.upload_by_url(virtual_image['id'], file_url, file_name)
|
343
430
|
if options[:json]
|
344
431
|
print JSON.pretty_generate(upload_json_response)
|
345
432
|
end
|
346
433
|
elsif virtual_image_files && !virtual_image_files.empty?
|
347
|
-
virtual_image_files.each do |key,
|
434
|
+
virtual_image_files.each do |key, filepath|
|
348
435
|
unless options[:quiet]
|
349
|
-
print cyan, "Uploading file (#{key}) #{
|
436
|
+
print cyan, "Uploading file (#{key}) #{filepath} ...", reset, "\n"
|
350
437
|
end
|
351
|
-
image_file = File.new(
|
352
|
-
upload_json_response = @virtual_images_interface.upload(virtual_image['id'], image_file)
|
438
|
+
image_file = File.new(filepath, 'rb')
|
439
|
+
upload_json_response = @virtual_images_interface.upload(virtual_image['id'], image_file, file_name)
|
353
440
|
if options[:json]
|
354
441
|
print JSON.pretty_generate(upload_json_response)
|
355
442
|
end
|
@@ -369,19 +456,25 @@ class Morpheus::Cli::VirtualImages
|
|
369
456
|
end
|
370
457
|
|
371
458
|
def add_file(args)
|
372
|
-
image_type_name = nil
|
373
459
|
file_url = nil
|
460
|
+
file_name = nil
|
374
461
|
options = {}
|
375
|
-
optparse = OptionParser.new do|opts|
|
462
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
376
463
|
opts.banner = subcommand_usage("[name] [filepath]")
|
464
|
+
opts.on('--filename FILENAME', String, "Filename for uploaded file. Derived from [filepath] by default." ) do |val|
|
465
|
+
file_name = val
|
466
|
+
end
|
377
467
|
opts.on( '-U', '--url URL', "Image File URL. This can be used instead of [filepath]" ) do |val|
|
378
468
|
file_url = val
|
379
469
|
end
|
380
470
|
build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
|
471
|
+
opts.footer = "Upload a virtual image file." + "\n" +
|
472
|
+
"[name] is required. This is the name or id of a virtual image." + "\n" +
|
473
|
+
"[filepath] or --url is required. This is location of the virtual image file."
|
381
474
|
end
|
382
475
|
optparse.parse!(args)
|
383
476
|
image_name = args[0]
|
384
|
-
|
477
|
+
filepath = nil
|
385
478
|
if file_url
|
386
479
|
if args.count < 1
|
387
480
|
puts optparse
|
@@ -392,7 +485,7 @@ class Morpheus::Cli::VirtualImages
|
|
392
485
|
puts optparse
|
393
486
|
exit 1
|
394
487
|
end
|
395
|
-
|
488
|
+
filepath = args[1]
|
396
489
|
end
|
397
490
|
|
398
491
|
connect(options)
|
@@ -402,13 +495,13 @@ class Morpheus::Cli::VirtualImages
|
|
402
495
|
return 1 if image.nil?
|
403
496
|
if file_url
|
404
497
|
if options[:dry_run]
|
405
|
-
print_dry_run @virtual_images_interface.dry.upload_by_url(image['id'], file_url)
|
498
|
+
print_dry_run @virtual_images_interface.dry.upload_by_url(image['id'], file_url, file_name)
|
406
499
|
return
|
407
500
|
end
|
408
501
|
unless options[:quiet]
|
409
502
|
print cyan, "Uploading file by url #{file_url} ...", reset, "\n"
|
410
503
|
end
|
411
|
-
json_response = @virtual_images_interface.upload_by_url(image['id'], file_url)
|
504
|
+
json_response = @virtual_images_interface.upload_by_url(image['id'], file_url, file_name)
|
412
505
|
if options[:json]
|
413
506
|
print JSON.pretty_generate(json_response)
|
414
507
|
elsif !options[:quiet]
|
@@ -416,15 +509,15 @@ class Morpheus::Cli::VirtualImages
|
|
416
509
|
get([image['id']])
|
417
510
|
end
|
418
511
|
else
|
419
|
-
image_file = File.new(
|
512
|
+
image_file = File.new(filepath, 'rb')
|
420
513
|
if options[:dry_run]
|
421
|
-
print_dry_run @virtual_images_interface.dry.upload(image['id'], image_file)
|
514
|
+
print_dry_run @virtual_images_interface.dry.upload(image['id'], image_file, file_name)
|
422
515
|
return
|
423
516
|
end
|
424
517
|
unless options[:quiet]
|
425
|
-
print cyan, "Uploading file #{
|
518
|
+
print cyan, "Uploading file #{filepath} ...", reset, "\n"
|
426
519
|
end
|
427
|
-
json_response = @virtual_images_interface.upload(image['id'], image_file)
|
520
|
+
json_response = @virtual_images_interface.upload(image['id'], image_file, file_name)
|
428
521
|
if options[:json]
|
429
522
|
print JSON.pretty_generate(json_response)
|
430
523
|
elsif !options[:quiet]
|
@@ -441,7 +534,7 @@ class Morpheus::Cli::VirtualImages
|
|
441
534
|
|
442
535
|
def remove_file(args)
|
443
536
|
options = {}
|
444
|
-
optparse = OptionParser.new do|opts|
|
537
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
445
538
|
opts.banner = subcommand_usage("[name] [filename]")
|
446
539
|
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
447
540
|
end
|
@@ -477,7 +570,7 @@ class Morpheus::Cli::VirtualImages
|
|
477
570
|
|
478
571
|
def remove(args)
|
479
572
|
options = {}
|
480
|
-
optparse = OptionParser.new do|opts|
|
573
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
481
574
|
opts.banner = subcommand_usage("[name]")
|
482
575
|
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
483
576
|
end
|
@@ -555,13 +648,14 @@ class Morpheus::Cli::VirtualImages
|
|
555
648
|
return get_available_virtual_image_types().find { |z| z['name'].downcase == name.downcase || z['code'].downcase == name.downcase}
|
556
649
|
end
|
557
650
|
|
558
|
-
def add_virtual_image_option_types(image_type, include_file_selection=true)
|
559
|
-
|
651
|
+
def add_virtual_image_option_types(image_type = nil, include_file_selection=true)
|
652
|
+
|
560
653
|
# todo: make api provide virtualImageType and its optionTypes.
|
561
654
|
tmp_option_types = [
|
562
655
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
563
656
|
#{'fieldName' => 'imageType', 'fieldLabel' => 'Image Type', 'type' => 'select', 'optionSource' => 'virtualImageTypes', 'required' => true, 'description' => 'Select Virtual Image Type.', 'displayOrder' => 2},
|
564
657
|
{'fieldName' => 'osType', 'fieldLabel' => 'OS Type', 'type' => 'select', 'optionSource' => 'osTypes', 'required' => false, 'description' => 'Select OS Type.', 'displayOrder' => 3},
|
658
|
+
{'fieldName' => 'minRam', 'fieldLabel' => 'Minimum Memory (MB)', 'type' => 'number', 'required' => false, 'description' => 'Minimum Memory (MB)', 'displayOrder' => 4},
|
565
659
|
{'fieldName' => 'isCloudInit', 'fieldLabel' => 'Cloud Init Enabled?', 'type' => 'checkbox', 'required' => false, 'description' => 'Cloud Init Enabled?', 'displayOrder' => 4},
|
566
660
|
{'fieldName' => 'installAgent', 'fieldLabel' => 'Install Agent?', 'type' => 'checkbox', 'required' => false, 'description' => 'Cloud Init Enabled?', 'displayOrder' => 4},
|
567
661
|
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text', 'required' => false, 'description' => 'Enter an SSH Username', 'displayOrder' => 5},
|
@@ -569,36 +663,55 @@ class Morpheus::Cli::VirtualImages
|
|
569
663
|
{'fieldName' => 'storageProviderId', 'type' => 'select', 'fieldLabel' => 'Storage Provider', 'optionSource' => 'storageProviders', 'required' => false, 'description' => 'Select Storage Provider.', 'displayOrder' => 7},
|
570
664
|
{'fieldName' => 'userData', 'fieldLabel' => 'Cloud-Init User Data', 'type' => 'textarea', 'required' => false, 'displayOrder' => 10},
|
571
665
|
{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'},{'name' => 'Public', 'value' => 'public'}], 'required' => false, 'description' => 'Visibility', 'category' => 'permissions', 'defaultValue' => 'private', 'displayOrder' => 40},
|
572
|
-
{'fieldName' => 'isAutoJoinDomain', 'fieldLabel' => 'Auto Join Domain?', 'type' => 'checkbox', 'required' => false, 'description' => '
|
573
|
-
{'fieldName' => 'virtioSupported', 'fieldLabel' => 'VirtIO Drivers Loaded?', 'type' => 'checkbox', 'defaultValue' => 'on', 'required' => false, 'description' => 'VirtIO Drivers Loaded?', 'category' => 'advanced', 'displayOrder' => 40}
|
666
|
+
{'fieldName' => 'isAutoJoinDomain', 'fieldLabel' => 'Auto Join Domain?', 'type' => 'checkbox', 'required' => false, 'description' => 'Auto Join Domain?', 'category' => 'advanced', 'displayOrder' => 40},
|
667
|
+
{'fieldName' => 'virtioSupported', 'fieldLabel' => 'VirtIO Drivers Loaded?', 'type' => 'checkbox', 'defaultValue' => 'on', 'required' => false, 'description' => 'VirtIO Drivers Loaded?', 'category' => 'advanced', 'displayOrder' => 40},
|
668
|
+
{'fieldName' => 'vmToolsInstalled', 'fieldLabel' => 'VM Tools Installed?', 'type' => 'checkbox', 'defaultValue' => 'on', 'required' => false, 'description' => 'VM Tools Installed?', 'category' => 'advanced', 'displayOrder' => 40},
|
669
|
+
{'fieldName' => 'isForceCustomization', 'fieldLabel' => 'Force Guest Customization?', 'type' => 'checkbox', 'defaultValue' => 'off', 'required' => false, 'description' => 'Force Guest Customization?', 'category' => 'advanced', 'displayOrder' => 40},
|
670
|
+
{'fieldName' => 'trialVersion', 'fieldLabel' => 'Trial Version', 'type' => 'checkbox', 'defaultValue' => 'off', 'required' => false, 'description' => 'Trial Version', 'category' => 'advanced', 'displayOrder' => 40},
|
671
|
+
{'fieldName' => 'isSysprep', 'fieldLabel' => 'Sysprep Enabled?', 'type' => 'checkbox', 'defaultValue' => 'off', 'required' => false, 'description' => 'Sysprep Enabled?', 'category' => 'advanced', 'displayOrder' => 40}
|
574
672
|
]
|
575
673
|
|
576
|
-
|
577
|
-
|
578
|
-
if
|
579
|
-
tmp_option_types << {'fieldName' => '
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
674
|
+
image_type_code = image_type ? image_type['code'] : nil
|
675
|
+
if image_type_code
|
676
|
+
if image_type_code == 'ami'
|
677
|
+
tmp_option_types << {'fieldName' => 'externalId', 'fieldLabel' => 'AMI id', 'type' => 'text', 'required' => false, 'displayOrder' => 10}
|
678
|
+
if include_file_selection
|
679
|
+
tmp_option_types << {'fieldName' => 'imageFile', 'fieldLabel' => 'Image File', 'type' => 'file', 'required' => false, 'displayOrder' => 10}
|
680
|
+
end
|
681
|
+
elsif image_type_code == 'vmware' || image_type_code == 'vmdk'
|
682
|
+
if include_file_selection
|
683
|
+
tmp_option_types << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageFile', 'fieldLabel' => 'OVF File', 'type' => 'file', 'required' => false, 'displayOrder' => 10}
|
684
|
+
tmp_option_types << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageDescriptorFile', 'fieldLabel' => 'VMDK File', 'type' => 'file', 'required' => false, 'displayOrder' => 10}
|
685
|
+
end
|
686
|
+
elsif image_type_code == 'pxe'
|
687
|
+
tmp_option_types << {'fieldName' => 'config.menu', 'fieldLabel' => 'Menu', 'type' => 'text', 'required' => false, 'displayOrder' => 10}
|
688
|
+
tmp_option_types << {'fieldName' => 'imagePath', 'fieldLabel' => 'Image Path', 'type' => 'text', 'required' => true, 'displayOrder' => 10}
|
689
|
+
tmp_option_types.reject! {|opt| ['isCloudInit', 'installAgent', 'sshUsername', 'sshPassword'].include?(opt['fieldName'])}
|
690
|
+
else
|
691
|
+
if include_file_selection
|
692
|
+
tmp_option_types << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageFile', 'fieldLabel' => 'Image File', 'type' => 'file', 'required' => false, 'description' => 'Choose an image file to upload', 'displayOrder' => 10}
|
693
|
+
end
|
593
694
|
end
|
594
695
|
end
|
595
696
|
|
596
697
|
return tmp_option_types
|
597
698
|
end
|
598
699
|
|
599
|
-
|
600
|
-
|
601
|
-
[]
|
700
|
+
def update_virtual_image_option_types(image_type = nil)
|
701
|
+
list = add_virtual_image_option_types(image_type)
|
702
|
+
list.each {|it| it['required'] = false }
|
703
|
+
list
|
704
|
+
end
|
705
|
+
|
706
|
+
def format_tenants(accounts)
|
707
|
+
if accounts && accounts.size > 0
|
708
|
+
accounts = accounts.sort {|a,b| a['name'] <=> b['name'] }.uniq {|it| it['id'] }
|
709
|
+
account_ids = accounts.collect {|it| it['id'] }
|
710
|
+
account_names = accounts.collect {|it| it['name'] }
|
711
|
+
"(#{account_ids.join(',')}) #{account_names.join(',')}"
|
712
|
+
else
|
713
|
+
""
|
714
|
+
end
|
602
715
|
end
|
603
716
|
|
604
717
|
end
|