morpheus-cli 3.3.2.7 → 3.4.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/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
|