opennebula-cli 5.10.4 → 5.12.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/bin/oneacct +2 -1
  3. data/bin/oneacl +2 -1
  4. data/bin/onecluster +2 -1
  5. data/bin/onedatastore +2 -1
  6. data/bin/oneflow +149 -551
  7. data/bin/oneflow-template +171 -292
  8. data/bin/onegroup +2 -1
  9. data/bin/onehook +2 -1
  10. data/bin/onehost +76 -9
  11. data/bin/oneimage +2 -1
  12. data/bin/onemarket +2 -1
  13. data/bin/onemarketapp +15 -3
  14. data/bin/onesecgroup +2 -1
  15. data/bin/oneshowback +2 -1
  16. data/bin/onetemplate +2 -1
  17. data/bin/oneuser +2 -1
  18. data/bin/onevcenter +2 -1
  19. data/bin/onevdc +2 -1
  20. data/bin/onevm +88 -16
  21. data/bin/onevmgroup +2 -1
  22. data/bin/onevnet +11 -3
  23. data/bin/onevntemplate +2 -1
  24. data/bin/onevrouter +2 -1
  25. data/bin/onezone +5 -1
  26. data/lib/cli_helper.rb +54 -30
  27. data/lib/command_parser.rb +33 -14
  28. data/lib/one_helper.rb +258 -6
  29. data/lib/one_helper/oneacct_helper.rb +1 -1
  30. data/lib/one_helper/oneacl_helper.rb +1 -1
  31. data/lib/one_helper/onecluster_helper.rb +4 -4
  32. data/lib/one_helper/onedatastore_helper.rb +1 -1
  33. data/lib/one_helper/oneflow_helper.rb +419 -0
  34. data/lib/one_helper/oneflowtemplate_helper.rb +312 -0
  35. data/lib/one_helper/onegroup_helper.rb +1 -1
  36. data/lib/one_helper/onehook_helper.rb +1 -1
  37. data/lib/one_helper/onehost_helper.rb +148 -68
  38. data/lib/one_helper/oneimage_helper.rb +2 -2
  39. data/lib/one_helper/onemarket_helper.rb +1 -1
  40. data/lib/one_helper/onemarketapp_helper.rb +1 -1
  41. data/lib/one_helper/oneprovision_helper.rb +104 -60
  42. data/lib/one_helper/onequota_helper.rb +1 -1
  43. data/lib/one_helper/onesecgroup_helper.rb +1 -1
  44. data/lib/one_helper/onetemplate_helper.rb +9 -180
  45. data/lib/one_helper/oneuser_helper.rb +1 -1
  46. data/lib/one_helper/onevcenter_helper.rb +2 -1
  47. data/lib/one_helper/onevdc_helper.rb +1 -1
  48. data/lib/one_helper/onevm_helper.rb +11 -6
  49. data/lib/one_helper/onevmgroup_helper.rb +1 -1
  50. data/lib/one_helper/onevnet_helper.rb +1 -1
  51. data/lib/one_helper/onevntemplate_helper.rb +1 -1
  52. data/lib/one_helper/onevrouter_helper.rb +1 -1
  53. data/lib/one_helper/onezone_helper.rb +3 -1
  54. metadata +8 -6
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  # -------------------------------------------------------------------------- #
4
- # Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
4
+ # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
5
5
  # #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
7
7
  # not use this file except in compliance with the License. You may obtain #
@@ -20,139 +20,61 @@ ONE_LOCATION = ENV['ONE_LOCATION']
20
20
 
21
21
  if !ONE_LOCATION
22
22
  RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
23
+ ONEFLOW_LOCATION = '/usr/lib/one/oneflow/lib'
23
24
  GEMS_LOCATION = '/usr/share/one/gems'
24
25
  else
25
26
  RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
27
+ ONEFLOW_LOCATION = ONE_LOCATION + '/lib/oneflow/lib'
26
28
  GEMS_LOCATION = ONE_LOCATION + '/share/gems'
27
29
  end
28
30
 
29
31
  if File.directory?(GEMS_LOCATION)
30
32
  Gem.use_paths(GEMS_LOCATION)
33
+ $LOAD_PATH.reject! {|l| l =~ /(vendor|site)_ruby/ }
31
34
  end
32
35
 
33
36
  $LOAD_PATH << RUBY_LIB_LOCATION
37
+ $LOAD_PATH << ONEFLOW_LOCATION
34
38
  $LOAD_PATH << RUBY_LIB_LOCATION + '/cli'
39
+ $LOAD_PATH << RUBY_LIB_LOCATION + '/oneflow/lib'
40
+
41
+ require 'json'
42
+ require 'English'
43
+ require 'tempfile'
35
44
 
36
45
  require 'command_parser'
37
46
  require 'opennebula/oneflow_client'
38
- require 'English'
47
+ require 'models'
39
48
  require 'cli_helper'
40
- require 'one_helper'
41
-
42
- require 'json'
49
+ require 'one_helper/oneflowtemplate_helper'
43
50
 
44
51
  USER_AGENT = 'CLI'
45
52
 
46
53
  # Base Path representing the resource to be used in the requests
47
54
  RESOURCE_PATH = '/service_template'
48
55
 
49
- #
50
- # Table
51
- #
52
-
53
- TABLE = CLIHelper::ShowTable.new(nil, self) do
54
- column :ID, 'ID', :size => 10 do |d|
55
- d['ID']
56
- end
57
-
58
- column :USER, 'Username', :left, :size => 15 do |d|
59
- d['UNAME']
60
- end
61
-
62
- column :GROUP, 'Group', :left, :size => 15 do |d|
63
- d['GNAME']
64
- end
65
-
66
- column :NAME, 'Name', :left, :size => 37 do |d|
67
- d['NAME']
68
- end
69
-
70
- default :ID, :USER, :GROUP, :NAME
71
- end
72
-
73
- # Show the service template information. This method is used in top and
74
- # show commands
75
- # @param [Service::Client] client
76
- # @param [Array] args
77
- # @param [Hash] options
78
- # @return [[Integer, String], Integer] Returns the exit_code and optionally
79
- # a String to be printed
80
- def show_service_template(client, args, options)
81
- response = client.get("#{RESOURCE_PATH}/#{args[0]}")
82
-
83
- if CloudClient.is_error?(response)
84
- [response.code.to_i, response.to_s]
85
- else
86
- # [0,response.body]
87
- if options[:json]
88
- [0, response.body]
89
- else
90
- str = '%-20s: %-20s'
91
- str_h1 = '%-80s'
92
-
93
- document_hash = JSON.parse(response.body)
94
- template = document_hash['DOCUMENT']['TEMPLATE']['BODY']
95
-
96
- CLIHelper.print_header(str_h1 %
97
- "SERVICE TEMPLATE #{document_hash['DOCUMENT']['ID']} "\
98
- 'INFORMATION')
99
-
100
- puts Kernel.format str, 'ID', document_hash['DOCUMENT']['ID']
101
- puts Kernel.format str, 'NAME', document_hash['DOCUMENT']['NAME']
102
- puts Kernel.format str, 'USER', document_hash['DOCUMENT']['UNAME']
103
- puts Kernel.format str, 'GROUP', document_hash['DOCUMENT']['GNAME']
104
-
105
- puts
106
-
107
- CLIHelper.print_header(str_h1 % 'PERMISSIONS', false)
108
-
109
- %w[OWNER GROUP OTHER].each do |e|
110
- mask = '---'
111
- permissions_hash = document_hash['DOCUMENT']['PERMISSIONS']
112
- mask[0] = 'u' if permissions_hash["#{e}_U"] == '1'
113
- mask[1] = 'm' if permissions_hash["#{e}_M"] == '1'
114
- mask[2] = 'a' if permissions_hash["#{e}_A"] == '1'
115
-
116
- puts Kernel.format str, e, mask
117
- end
118
-
119
- puts
120
-
121
- CLIHelper.print_header(str_h1 % 'TEMPLATE CONTENTS', false)
122
- puts JSON.pretty_generate(template)
123
-
124
- 0
125
- end
126
- end
127
- end
128
-
129
- # List the services. This method is used in top and list commands
130
- # @param [Service::Client] client
131
- # @param [Hash] options
132
- # @return [[Integer, String], Integer] Returns the exit_code and optionally
133
- # a String to be printed
134
- def list_service_templates(client, options)
135
- response = client.get(RESOURCE_PATH)
136
-
137
- if CloudClient.is_error?(response)
138
- [response.code.to_i, response.to_s]
139
- else
140
- # [0,response.body]
141
- if options[:json]
142
- [0, response.body]
143
- else
144
- array_list = JSON.parse(response.body)
145
- TABLE.show(array_list['DOCUMENT_POOL']['DOCUMENT'])
146
- 0
147
- end
148
- end
149
- end
150
-
151
- #
152
- # Commands
153
- #
154
-
155
56
  CommandParser::CmdParser.new(ARGV) do
57
+ MULTIPLE = {
58
+ :name => 'multiple',
59
+ :short => '-m x',
60
+ :large => '--multiple x',
61
+ :format => Integer,
62
+ :description => 'Instance multiple templates'
63
+ }
64
+
65
+ RECURSIVE = {
66
+ :name => 'recursive',
67
+ :short => '-r',
68
+ :large => '--recursive',
69
+ :description => 'Clone the template recursively (templates and images)'
70
+ }
71
+
72
+ RECURSIVE_TEMPLATES = {
73
+ :name => 'recursive_templates',
74
+ :large => '--recursive-templates',
75
+ :description => 'Clone the template recursively (just templates)'
76
+ }
77
+
156
78
  usage '`oneflow-template` <command> [<args>] [<options>]'
157
79
  version OpenNebulaHelper::ONE_VERSION
158
80
 
@@ -160,9 +82,12 @@ CommandParser::CmdParser.new(ARGV) do
160
82
  set :option, CommandParser::VERSION
161
83
  set :option, CommandParser::HELP
162
84
 
163
- #
85
+ # create helper object
86
+ helper = OneFlowTemplateHelper.new
87
+
88
+ ############################################################################
164
89
  # Formatters for arguments
165
- #
90
+ ############################################################################
166
91
  set :format, :groupid, OpenNebulaHelper.rname_to_id_desc('GROUP') do |arg|
167
92
  OpenNebulaHelper.rname_to_id(arg, 'GROUP')
168
93
  end
@@ -181,81 +106,52 @@ CommandParser::CmdParser.new(ARGV) do
181
106
  Service.list_to_id(arg, 'SERVICE TEMPLATE')
182
107
  end
183
108
 
184
- #
185
- # List
186
- #
109
+ ###
187
110
 
188
111
  list_desc = <<-EOT.unindent
189
112
  List the available Service Templates
190
113
  EOT
191
114
 
192
115
  command :list, list_desc, :options => Service::JSON_FORMAT do
193
- client = Service::Client.new(
194
- :username => options[:username],
195
- :password => options[:password],
196
- :url => options[:server],
197
- :user_agent => USER_AGENT
198
- )
199
-
200
- list_service_templates(client, options)
116
+ helper.list_service_template_pool(helper.client(options), options)
201
117
  end
202
118
 
203
- #
204
- # Top
205
- #
119
+ ###
206
120
 
207
121
  top_desc = <<-EOT.unindent
208
122
  List the available Service Templates continuously
209
123
  EOT
210
124
 
211
- command :top, top_desc,
125
+ command :top,
126
+ top_desc,
212
127
  :options => [Service::JSON_FORMAT,
213
128
  Service::TOP,
214
129
  CLIHelper::DELAY] do
215
- client = Service::Client.new(
216
- :username => options[:username],
217
- :password => options[:password],
218
- :url => options[:server],
219
- :user_agent => USER_AGENT
220
- )
130
+ Signal.trap('INT') { exit(-1) }
221
131
 
222
- options[:delay] ? delay = options[:delay] : delay = 3
132
+ helper.top_service_template_pool(helper.client(options), options)
223
133
 
224
- begin
225
- loop do
226
- CLIHelper.scr_cls
227
- CLIHelper.scr_move(0, 0)
134
+ 0
135
+ end
228
136
 
229
- rc, message = list_service_templates(client, options)
137
+ ###
230
138
 
231
- if rc != 0
232
- raise message
233
- end
139
+ show_desc = <<-EOT.unindent
140
+ Show detailed information of a given Service Template
141
+ EOT
234
142
 
235
- sleep delay
236
- end
237
- rescue StandardError => e
238
- puts e.message
239
- -1
240
- end
143
+ command :show, show_desc, :templateid, :options => Service::JSON_FORMAT do
144
+ helper.format_resource(helper.client(options), args[0], options)
241
145
  end
242
146
 
243
- #
244
- # Create
245
- #
147
+ ###
246
148
 
247
149
  create_desc = <<-EOT.unindent
248
150
  Create a new Service Template
249
151
  EOT
250
152
 
251
153
  command :create, create_desc, :file, :options => Service::JSON_FORMAT do
252
- client = Service::Client.new(
253
- :username => options[:username],
254
- :password => options[:password],
255
- :url => options[:server],
256
- :user_agent => USER_AGENT
257
- )
258
-
154
+ client = helper.client(options)
259
155
  response = client.post(RESOURCE_PATH, File.read(args[0]))
260
156
 
261
157
  if CloudClient.is_error?(response)
@@ -264,180 +160,178 @@ CommandParser::CmdParser.new(ARGV) do
264
160
  if options[:json]
265
161
  [0, response.body]
266
162
  else
267
- template = JSON.parse(response.body)
268
- puts "ID: #{template['DOCUMENT']['ID']}"
163
+ puts "ID: #{JSON.parse(response.body)['DOCUMENT']['ID']}"
164
+
269
165
  0
270
166
  end
271
167
  end
272
168
  end
273
169
 
274
- #
275
- # Show
276
- #
277
-
278
- show_desc = <<-EOT.unindent
279
- Show detailed information of a given Service Template
280
- EOT
281
-
282
- command :show, show_desc, :templateid, :options => Service::JSON_FORMAT do
283
- client = Service::Client.new(
284
- :username => options[:username],
285
- :password => options[:password],
286
- :url => options[:server],
287
- :user_agent => USER_AGENT
288
- )
289
-
290
- show_service_template(client, args, options)
291
- end
292
-
293
- #
294
- # Delete
295
- #
170
+ ###
296
171
 
297
172
  delete_desc = <<-EOT.unindent
298
173
  Delete a given Service Template
299
174
  EOT
300
175
 
301
176
  command :delete, delete_desc, [:range, :templateid_list] do
302
- client = Service::Client.new(
303
- :username => options[:username],
304
- :password => options[:password],
305
- :url => options[:server],
306
- :user_agent => USER_AGENT
307
- )
177
+ client = helper.client(options)
308
178
 
309
179
  Service.perform_actions(args[0]) do |template_id|
310
180
  client.delete("#{RESOURCE_PATH}/#{template_id}")
311
181
  end
312
182
  end
313
183
 
314
- #
315
- # Instantiate
316
- #
184
+ ###
317
185
 
318
186
  instantiate_desc = <<-EOT.unindent
319
187
  Instantiate a Service Template
320
188
  EOT
321
189
 
322
- command :instantiate, instantiate_desc, :templateid, [:file, nil],
323
- :options => [Service::JSON_FORMAT, Service::TOP] do
324
- client = Service::Client.new(
325
- :username => options[:username],
326
- :password => options[:password],
327
- :url => options[:server],
328
- :user_agent => USER_AGENT
329
- )
330
-
190
+ command :instantiate,
191
+ instantiate_desc,
192
+ :templateid,
193
+ [:file, nil],
194
+ :options => [MULTIPLE, Service::JSON_FORMAT, Service::TOP] do
195
+ number = options[:multiple] || 1
331
196
  params = {}
197
+ rc = 0
332
198
 
333
- if args[1]
334
- params['merge_template'] = JSON.parse(File.read(args[1]))
335
- end
199
+ number.times do
200
+ params['merge_template'] = nil
201
+ params['merge_template'] = JSON.parse(File.read(args[1])) if args[1]
336
202
 
337
- json_str = Service.build_json_action('instantiate', params)
203
+ unless params['merge_template']
204
+ service_template = OpenNebula::ServiceTemplate
205
+ .new_with_id(args[0],
206
+ OpenNebula::Client.new)
207
+ service_template.info
338
208
 
339
- response = client.post("#{RESOURCE_PATH}/#{args[0]}/action", json_str)
209
+ body = JSON.parse(service_template['/DOCUMENT/TEMPLATE/BODY'])
340
210
 
341
- if CloudClient.is_error?(response)
342
- [response.code.to_i, response.to_s]
343
- else
344
- if options[:json]
345
- [0, response.body]
211
+ params['merge_template'] = helper.custom_attrs(
212
+ body['custom_attrs']
213
+ )
214
+
215
+ params['merge_template'] = {} unless params['merge_template']
216
+
217
+ vnets = helper.networks(body['networks'])
218
+ params['merge_template'].merge!(vnets) unless vnets.nil?
219
+ end
220
+
221
+ json = Service.build_json_action('instantiate', params)
222
+ client = helper.client(options)
223
+ response = client.post("#{RESOURCE_PATH}/#{args[0]}/action", json)
224
+
225
+ if CloudClient.is_error?(response)
226
+ rc = [response.code.to_i, response.to_s]
227
+ break
346
228
  else
347
- template = JSON.parse(response.body)
348
- puts "ID: #{template['DOCUMENT']['ID']}"
349
- 0
229
+ if options[:json]
230
+ rc = [0, response.body]
231
+ break
232
+ else
233
+ rc = 0
234
+ puts "ID: #{JSON.parse(response.body)['DOCUMENT']['ID']}"
235
+ end
350
236
  end
351
237
  end
238
+
239
+ rc
352
240
  end
353
241
 
242
+ ###
243
+
354
244
  chgrp_desc = <<-EOT.unindent
355
245
  Changes the service template group
356
246
  EOT
357
247
 
358
248
  command :chgrp, chgrp_desc, [:range, :templateid_list], :groupid do
359
- client = Service::Client.new(
360
- :username => options[:username],
361
- :password => options[:password],
362
- :url => options[:server],
363
- :user_agent => USER_AGENT
364
- )
249
+ client = helper.client(options)
365
250
 
366
251
  Service.perform_actions(args[0]) do |service_id|
367
252
  params = {}
368
253
  params['group_id'] = args[1].to_i
369
254
 
370
- json_action = Service.build_json_action('chgrp', params)
255
+ json = Service.build_json_action('chgrp', params)
371
256
 
372
- client.post("#{RESOURCE_PATH}/#{service_id}/action", json_action)
257
+ client.post("#{RESOURCE_PATH}/#{service_id}/action", json)
373
258
  end
374
259
  end
375
260
 
261
+ ###
262
+
376
263
  chown_desc = <<-EOT.unindent
377
264
  Changes the service template owner and group
378
265
  EOT
379
266
 
380
- command :chown, chown_desc, [:range, :templateid_list],
381
- :userid, [:groupid, nil] do
382
- client = Service::Client.new(
383
- :username => options[:username],
384
- :password => options[:password],
385
- :url => options[:server],
386
- :user_agent => USER_AGENT
387
- )
267
+ command :chown,
268
+ chown_desc,
269
+ [:range, :templateid_list],
270
+ :userid,
271
+ [:groupid, nil] do
272
+ client = helper.client(options)
388
273
 
389
274
  Service.perform_actions(args[0]) do |service_id|
390
275
  params = {}
391
276
  params['owner_id'] = args[1]
392
277
  params['group_id'] = args[2] if args[2]
393
278
 
394
- json_action = Service.build_json_action('chown', params)
279
+ json = Service.build_json_action('chown', params)
395
280
 
396
- client.post("#{RESOURCE_PATH}/#{service_id}/action", json_action)
281
+ client.post("#{RESOURCE_PATH}/#{service_id}/action", json)
397
282
  end
398
283
  end
399
284
 
285
+ ###
286
+
400
287
  chmod_desc = <<-EOT.unindent
401
288
  Changes the service template permissions
402
289
  EOT
403
290
 
404
291
  command :chmod, chmod_desc, [:range, :templateid_list], :octet do
405
- client = Service::Client.new(
406
- :username => options[:username],
407
- :password => options[:password],
408
- :url => options[:server],
409
- :user_agent => USER_AGENT
410
- )
292
+ if !/\A\d+\z/.match(args[1])
293
+ STDERR.puts "Invalid '#{args[1]}' octed permissions"
294
+ exit(-1)
295
+ end
296
+
297
+ client = helper.client(options)
411
298
 
412
299
  Service.perform_actions(args[0]) do |service_id|
413
300
  params = {}
414
301
  params['octet'] = args[1]
415
302
 
416
- json_action = Service.build_json_action('chmod', params)
303
+ json = Service.build_json_action('chmod', params)
417
304
 
418
- client.post("#{RESOURCE_PATH}/#{service_id}/action", json_action)
305
+ client.post("#{RESOURCE_PATH}/#{service_id}/action", json)
419
306
  end
420
307
  end
421
308
 
309
+ ###
310
+
422
311
  clone_desc = <<-EOT.unindent
423
312
  Creates a new Service Template from an existing one
424
313
  EOT
425
314
 
426
- command :clone, clone_desc, :templateid, :name do
427
- client = Service::Client.new(
428
- :username => options[:username],
429
- :password => options[:password],
430
- :url => options[:server],
431
- :user_agent => USER_AGENT
432
- )
433
-
315
+ command :clone,
316
+ clone_desc,
317
+ :templateid,
318
+ :name,
319
+ :options => [RECURSIVE, RECURSIVE_TEMPLATES] do
434
320
  params = {}
435
321
  params['name'] = args[1]
436
322
 
437
- json_action = Service.build_json_action('clone', params)
323
+ if options.key?(:recursive)
324
+ params['recursive'] = 'all'
325
+ elsif options.key?(:recursive_templates)
326
+ params['recurisve'] = 'templates'
327
+ else
328
+ params['recursive'] = 'none'
329
+ end
330
+
331
+ json = Service.build_json_action('clone', params)
332
+ client = helper.client(options)
438
333
 
439
- response = client.post("#{RESOURCE_PATH}/#{args[0]}/action",
440
- json_action)
334
+ response = client.post("#{RESOURCE_PATH}/#{args[0]}/action", json)
441
335
 
442
336
  if CloudClient.is_error?(response)
443
337
  [response.code.to_i, response.to_s]
@@ -445,40 +339,33 @@ CommandParser::CmdParser.new(ARGV) do
445
339
  if options[:json]
446
340
  [0, response.body]
447
341
  else
448
- template = JSON.parse(response.body)
449
- puts "ID: #{template['DOCUMENT']['ID']}"
342
+ puts "ID: #{JSON.parse(response.body)['DOCUMENT']['ID']}"
343
+
450
344
  0
451
345
  end
452
346
  end
453
347
  end
454
348
 
349
+ ###
350
+
455
351
  rename_desc = <<-EOT.unindent
456
352
  Renames the Service Template
457
353
  EOT
458
354
 
459
355
  command :rename, rename_desc, :templateid, :name do
460
- client = Service::Client.new(
461
- :username => options[:username],
462
- :password => options[:password],
463
- :url => options[:server],
464
- :user_agent => USER_AGENT
465
- )
466
-
467
- params = {}
468
- params['name'] = args[1]
469
-
470
- json_action = Service.build_json_action('rename', params)
356
+ Service.perform_action(args[0]) do |template_id|
357
+ params = {}
358
+ params['name'] = args[1]
471
359
 
472
- response = client.post("#{RESOURCE_PATH}/#{args[0]}/action",
473
- json_action)
360
+ json = Service.build_json_action('rename', params)
361
+ client = helper.client(options)
474
362
 
475
- if CloudClient.is_error?(response)
476
- [response.code.to_i, response.to_s]
477
- else
478
- response.code.to_i
363
+ client.post("#{RESOURCE_PATH}/#{template_id}/action", json)
479
364
  end
480
365
  end
481
366
 
367
+ ###
368
+
482
369
  update_desc = <<-EOT.unindent
483
370
  Update the template contents. If a path is not provided the editor will
484
371
  be launched to modify the current content.
@@ -486,30 +373,23 @@ CommandParser::CmdParser.new(ARGV) do
486
373
 
487
374
  command :update, update_desc, :templateid, [:file, nil] do
488
375
  template_id = args[0]
489
- client = Service::Client.new(
490
- :username => options[:username],
491
- :password => options[:password],
492
- :url => options[:server],
493
- :user_agent => USER_AGENT
494
- )
376
+ client = helper.client(options)
495
377
 
496
378
  if args[1]
497
379
  path = args[1]
498
380
  else
499
- require 'tempfile'
500
-
501
- tmp = Tempfile.new(template_id.to_s)
502
- path = tmp.path
503
-
504
381
  response = client.get("#{RESOURCE_PATH}/#{template_id}")
505
382
 
506
383
  if CloudClient.is_error?(response)
507
384
  exit_with_code response.code.to_i, response.to_s
508
385
  else
509
- document_hash = JSON.parse(response.body)
510
- template = document_hash['DOCUMENT']['TEMPLATE']['BODY']
386
+ document = JSON.parse(response.body)['DOCUMENT']
387
+ template = document['TEMPLATE']['BODY']
511
388
 
512
- tmp << JSON.pretty_generate(template)
389
+ tmp = Tempfile.new(template_id.to_s)
390
+ path = tmp.path
391
+
392
+ tmp.write(JSON.pretty_generate(template))
513
393
  tmp.flush
514
394
 
515
395
  if ENV['EDITOR']
@@ -517,10 +397,11 @@ CommandParser::CmdParser.new(ARGV) do
517
397
  else
518
398
  editor_path = OpenNebulaHelper::EDITOR_PATH
519
399
  end
400
+
520
401
  system("#{editor_path} #{path}")
521
402
 
522
403
  unless $CHILD_STATUS.exitstatus.zero?
523
- puts 'Editor not defined'
404
+ STDERR.puts 'Editor not defined'
524
405
  exit(-1)
525
406
  end
526
407
 
@@ -528,15 +409,13 @@ CommandParser::CmdParser.new(ARGV) do
528
409
  end
529
410
  end
530
411
 
531
- exit_code = 0
412
+ response = client.put("#{RESOURCE_PATH}/#{template_id}",
413
+ File.read(path))
532
414
 
533
- t_str = File.read(path)
534
- response = client.put("#{RESOURCE_PATH}/#{template_id}", t_str)
535
415
  if CloudClient.is_error?(response)
536
- puts response.to_s
537
- exit_code = response.code.to_i
416
+ [response.code.to_i, response.to_s]
417
+ else
418
+ 0
538
419
  end
539
-
540
- exit_code
541
420
  end
542
421
  end