opennebula-cli 5.12.9 → 6.0.0.1

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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/bin/oneacct +9 -4
  3. data/bin/oneacl +8 -5
  4. data/bin/onecluster +10 -7
  5. data/bin/onedatastore +10 -7
  6. data/bin/oneflow +85 -13
  7. data/bin/oneflow-template +45 -8
  8. data/bin/onegroup +10 -7
  9. data/bin/onehook +10 -7
  10. data/bin/onehost +10 -7
  11. data/bin/oneimage +100 -9
  12. data/bin/onemarket +10 -7
  13. data/bin/onemarketapp +114 -11
  14. data/bin/onesecgroup +13 -7
  15. data/bin/oneshowback +18 -10
  16. data/bin/onetemplate +12 -8
  17. data/bin/oneuser +30 -7
  18. data/bin/onevcenter +8 -11
  19. data/bin/onevdc +10 -7
  20. data/bin/onevm +146 -11
  21. data/bin/onevmgroup +13 -7
  22. data/bin/onevnet +8 -5
  23. data/bin/onevntemplate +11 -7
  24. data/bin/onevrouter +10 -7
  25. data/bin/onezone +11 -8
  26. data/lib/cli_helper.rb +17 -8
  27. data/lib/command_parser.rb +17 -14
  28. data/lib/one_helper.rb +401 -39
  29. data/lib/one_helper/oneacct_helper.rb +6 -17
  30. data/lib/one_helper/oneacl_helper.rb +1 -1
  31. data/lib/one_helper/onecluster_helper.rb +1 -1
  32. data/lib/one_helper/onedatastore_helper.rb +11 -1
  33. data/lib/one_helper/oneflow_helper.rb +20 -5
  34. data/lib/one_helper/oneflowtemplate_helper.rb +28 -2
  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 +1 -5
  38. data/lib/one_helper/oneimage_helper.rb +13 -7
  39. data/lib/one_helper/onemarket_helper.rb +1 -1
  40. data/lib/one_helper/onemarketapp_helper.rb +500 -96
  41. data/lib/one_helper/onequota_helper.rb +1 -1
  42. data/lib/one_helper/onesecgroup_helper.rb +1 -1
  43. data/lib/one_helper/onetemplate_helper.rb +12 -1
  44. data/lib/one_helper/oneuser_helper.rb +11 -3
  45. data/lib/one_helper/onevcenter_helper.rb +176 -146
  46. data/lib/one_helper/onevdc_helper.rb +1 -1
  47. data/lib/one_helper/onevm_helper.rb +4 -3
  48. data/lib/one_helper/onevmgroup_helper.rb +1 -1
  49. data/lib/one_helper/onevnet_helper.rb +1 -1
  50. data/lib/one_helper/onevntemplate_helper.rb +1 -1
  51. data/lib/one_helper/onevrouter_helper.rb +1 -20
  52. data/lib/one_helper/onezone_helper.rb +24 -17
  53. data/share/schemas/xsd/acct.xsd +179 -0
  54. data/share/schemas/xsd/acl_pool.xsd +22 -0
  55. data/share/schemas/xsd/api_info.xsd +43 -0
  56. data/share/schemas/xsd/cluster.xsd +34 -0
  57. data/share/schemas/xsd/cluster_pool.xsd +12 -0
  58. data/share/schemas/xsd/datastore.xsd +67 -0
  59. data/share/schemas/xsd/datastore_pool.xsd +12 -0
  60. data/share/schemas/xsd/document.xsd +42 -0
  61. data/share/schemas/xsd/document_pool.xsd +12 -0
  62. data/share/schemas/xsd/group.xsd +179 -0
  63. data/share/schemas/xsd/group_pool.xsd +194 -0
  64. data/share/schemas/xsd/hook.xsd +59 -0
  65. data/share/schemas/xsd/hook_message_api.xsd +14 -0
  66. data/share/schemas/xsd/hook_message_retry.xsd +12 -0
  67. data/share/schemas/xsd/hook_message_state.xsd +25 -0
  68. data/share/schemas/xsd/hook_pool.xsd +12 -0
  69. data/share/schemas/xsd/host.xsd +164 -0
  70. data/share/schemas/xsd/host_pool.xsd +12 -0
  71. data/share/schemas/xsd/image.xsd +123 -0
  72. data/share/schemas/xsd/image_pool.xsd +12 -0
  73. data/share/schemas/xsd/index.xsd +50 -0
  74. data/share/schemas/xsd/marketplace.xsd +44 -0
  75. data/share/schemas/xsd/marketplace_pool.xsd +12 -0
  76. data/share/schemas/xsd/marketplaceapp.xsd +56 -0
  77. data/share/schemas/xsd/marketplaceapp_pool.xsd +12 -0
  78. data/share/schemas/xsd/monitoring_data.xsd +41 -0
  79. data/share/schemas/xsd/opennebula_configuration.xsd +412 -0
  80. data/share/schemas/xsd/raftstatus.xsd +18 -0
  81. data/share/schemas/xsd/security_group.xsd +74 -0
  82. data/share/schemas/xsd/security_group_pool.xsd +12 -0
  83. data/share/schemas/xsd/showback.xsd +29 -0
  84. data/share/schemas/xsd/user.xsd +186 -0
  85. data/share/schemas/xsd/user_pool.xsd +201 -0
  86. data/share/schemas/xsd/vdc.xsd +76 -0
  87. data/share/schemas/xsd/vdc_pool.xsd +12 -0
  88. data/share/schemas/xsd/vm.xsd +251 -0
  89. data/share/schemas/xsd/vm_group.xsd +59 -0
  90. data/share/schemas/xsd/vm_group_pool.xsd +12 -0
  91. data/share/schemas/xsd/vm_pool.xsd +114 -0
  92. data/share/schemas/xsd/vmtemplate.xsd +52 -0
  93. data/share/schemas/xsd/vmtemplate_pool.xsd +12 -0
  94. data/share/schemas/xsd/vnet.xsd +137 -0
  95. data/share/schemas/xsd/vnet_pool.xsd +85 -0
  96. data/share/schemas/xsd/vntemplate.xsd +50 -0
  97. data/share/schemas/xsd/vntemplate_pool.xsd +12 -0
  98. data/share/schemas/xsd/vrouter.xsd +49 -0
  99. data/share/schemas/xsd/vrouter_pool.xsd +12 -0
  100. data/share/schemas/xsd/zone.xsd +40 -0
  101. data/share/schemas/xsd/zone_pool.xsd +36 -0
  102. metadata +67 -5
  103. data/lib/one_helper/oneprovision_helper.rb +0 -362
data/bin/onevmgroup CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  # -------------------------------------------------------------------------- #
4
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
4
+ # Copyright 2002-2021, 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 #
@@ -27,9 +27,12 @@ else
27
27
  end
28
28
 
29
29
  if File.directory?(GEMS_LOCATION)
30
- $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
31
- require 'rubygems'
32
- Gem.use_paths(File.realpath(GEMS_LOCATION))
30
+ real_gems_path = File.realpath(GEMS_LOCATION)
31
+ if !defined?(Gem) || Gem.path != [real_gems_path]
32
+ $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
33
+ require 'rubygems'
34
+ Gem.use_paths(real_gems_path)
35
+ end
33
36
  end
34
37
 
35
38
  $LOAD_PATH << RUBY_LIB_LOCATION
@@ -77,8 +80,8 @@ CommandParser::CmdParser.new(ARGV) do
77
80
  ########################################################################
78
81
  set :option, CommandParser::OPTIONS + OpenNebulaHelper::CLIENT_OPTIONS
79
82
 
80
- list_options = CLIHelper::OPTIONS
81
- list_options << OpenNebulaHelper::XML
83
+ list_options = CLIHelper::OPTIONS
84
+ list_options += OpenNebulaHelper::FORMAT
82
85
  list_options << OpenNebulaHelper::NUMERIC
83
86
  list_options << OpenNebulaHelper::DESCRIBE
84
87
 
@@ -148,7 +151,10 @@ CommandParser::CmdParser.new(ARGV) do
148
151
  Shows information for the given VM Group
149
152
  EOT
150
153
 
151
- command :show, show_desc, :vmgroupid, :options => OpenNebulaHelper::XML do
154
+ command :show,
155
+ show_desc,
156
+ :vmgroupid,
157
+ :options => OpenNebulaHelper::FORMAT do
152
158
  helper.show_resource(args[0], options)
153
159
  end
154
160
 
data/bin/onevnet CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  # -------------------------------------------------------------------------- #
4
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
4
+ # Copyright 2002-2021, 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 #
@@ -27,9 +27,12 @@ else
27
27
  end
28
28
 
29
29
  if File.directory?(GEMS_LOCATION)
30
- $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
31
- require 'rubygems'
32
- Gem.use_paths(File.realpath(GEMS_LOCATION))
30
+ real_gems_path = File.realpath(GEMS_LOCATION)
31
+ if !defined?(Gem) || Gem.path != [real_gems_path]
32
+ $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
33
+ require 'rubygems'
34
+ Gem.use_paths(real_gems_path)
35
+ end
33
36
  end
34
37
 
35
38
  $LOAD_PATH << RUBY_LIB_LOCATION
@@ -320,7 +323,7 @@ CommandParser::CmdParser.new(ARGV) do
320
323
  EOT
321
324
 
322
325
  command :show, show_desc, :vnetid,
323
- :options => [OpenNebulaHelper::XML,
326
+ :options => [OpenNebulaHelper::FORMAT,
324
327
  OpenNebulaHelper::DECRYPT,
325
328
  OneVNetHelper::SHOW_AR] do
326
329
  helper.show_resource(args[0], options)
data/bin/onevntemplate CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  # -------------------------------------------------------------------------- #
4
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
4
+ # Copyright 2002-2021, 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 #
@@ -27,9 +27,12 @@ else
27
27
  end
28
28
 
29
29
  if File.directory?(GEMS_LOCATION)
30
- $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
31
- require 'rubygems'
32
- Gem.use_paths(File.realpath(GEMS_LOCATION))
30
+ real_gems_path = File.realpath(GEMS_LOCATION)
31
+ if !defined?(Gem) || Gem.path != [real_gems_path]
32
+ $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
33
+ require 'rubygems'
34
+ Gem.use_paths(real_gems_path)
35
+ end
33
36
  end
34
37
 
35
38
  $LOAD_PATH << RUBY_LIB_LOCATION
@@ -78,8 +81,8 @@ CommandParser::CmdParser.new(ARGV) do
78
81
  ########################################################################
79
82
  set :option, CommandParser::OPTIONS + OpenNebulaHelper::CLIENT_OPTIONS
80
83
 
81
- list_options = CLIHelper::OPTIONS
82
- list_options << OpenNebulaHelper::XML
84
+ list_options = CLIHelper::OPTIONS
85
+ list_options += OpenNebulaHelper::FORMAT
83
86
  list_options << OpenNebulaHelper::NUMERIC
84
87
  list_options << OpenNebulaHelper::DESCRIBE
85
88
 
@@ -313,7 +316,8 @@ CommandParser::CmdParser.new(ARGV) do
313
316
  EOT
314
317
 
315
318
  command :show, show_desc, :templateid,
316
- :options => [OpenNebulaHelper::XML, OneTemplateHelper::EXTENDED] do
319
+ :options => [OpenNebulaHelper::FORMAT,
320
+ OneTemplateHelper::EXTENDED] do
317
321
  helper.show_resource(args[0], options)
318
322
  end
319
323
 
data/bin/onevrouter CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  # -------------------------------------------------------------------------- #
4
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
4
+ # Copyright 2002-2021, 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 #
@@ -27,9 +27,12 @@ else
27
27
  end
28
28
 
29
29
  if File.directory?(GEMS_LOCATION)
30
- $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
31
- require 'rubygems'
32
- Gem.use_paths(File.realpath(GEMS_LOCATION))
30
+ real_gems_path = File.realpath(GEMS_LOCATION)
31
+ if !defined?(Gem) || Gem.path != [real_gems_path]
32
+ $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
33
+ require 'rubygems'
34
+ Gem.use_paths(real_gems_path)
35
+ end
33
36
  end
34
37
 
35
38
  $LOAD_PATH << RUBY_LIB_LOCATION
@@ -79,8 +82,8 @@ CommandParser::CmdParser.new(ARGV) do
79
82
  ########################################################################
80
83
  set :option, CommandParser::OPTIONS + OpenNebulaHelper::CLIENT_OPTIONS
81
84
 
82
- list_options = CLIHelper::OPTIONS
83
- list_options << OpenNebulaHelper::XML
85
+ list_options = CLIHelper::OPTIONS
86
+ list_options += OpenNebulaHelper::FORMAT
84
87
  list_options << OpenNebulaHelper::NUMERIC
85
88
  list_options << OpenNebulaHelper::DESCRIBE
86
89
 
@@ -339,7 +342,7 @@ CommandParser::CmdParser.new(ARGV) do
339
342
  EOT
340
343
 
341
344
  command :show, show_desc, :vrouterid,
342
- :options => [OpenNebulaHelper::XML, OneVMHelper::ALL_TEMPLATE] do
345
+ :options => [OpenNebulaHelper::FORMAT, OneVMHelper::ALL_TEMPLATE] do
343
346
  helper.show_resource(args[0], options)
344
347
  end
345
348
 
data/bin/onezone CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  # -------------------------------------------------------------------------- #
4
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
4
+ # Copyright 2002-2021, 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 #
@@ -27,9 +27,12 @@ else
27
27
  end
28
28
 
29
29
  if File.directory?(GEMS_LOCATION)
30
- $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
31
- require 'rubygems'
32
- Gem.use_paths(File.realpath(GEMS_LOCATION))
30
+ real_gems_path = File.realpath(GEMS_LOCATION)
31
+ if !defined?(Gem) || Gem.path != [real_gems_path]
32
+ $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
33
+ require 'rubygems'
34
+ Gem.use_paths(real_gems_path)
35
+ end
33
36
  end
34
37
 
35
38
  $LOAD_PATH << RUBY_LIB_LOCATION
@@ -54,7 +57,7 @@ CommandParser::CmdParser.new(ARGV) do
54
57
  }
55
58
 
56
59
  DATABASE = {
57
- :name => 'database',
60
+ :name => 'db',
58
61
  :large => '--db',
59
62
  :description => 'Also sync database'
60
63
  }
@@ -68,8 +71,8 @@ CommandParser::CmdParser.new(ARGV) do
68
71
  ########################################################################
69
72
  set :option, CommandParser::OPTIONS + OpenNebulaHelper::CLIENT_OPTIONS
70
73
 
71
- list_options = CLIHelper::OPTIONS
72
- list_options << OpenNebulaHelper::XML
74
+ list_options = CLIHelper::OPTIONS
75
+ list_options += OpenNebulaHelper::FORMAT
73
76
  list_options << OpenNebulaHelper::NUMERIC
74
77
  list_options << OpenNebulaHelper::DESCRIBE
75
78
 
@@ -208,7 +211,7 @@ CommandParser::CmdParser.new(ARGV) do
208
211
  Shows information for the given Zone
209
212
  EOT
210
213
 
211
- command :show, show_desc, :zoneid, :options => OpenNebulaHelper::XML do
214
+ command :show, show_desc, :zoneid, :options => OpenNebulaHelper::FORMAT do
212
215
  helper.show_resource(args[0], options)
213
216
  end
214
217
 
data/lib/cli_helper.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -181,7 +181,7 @@ module CLIHelper
181
181
  ANSI_YELLOW = "\33[33m"
182
182
 
183
183
  # CLI states
184
- OK_STATES = %w[runn rdy on configured SUCCESS RUNNING]
184
+ OK_STATES = %w[runn rdy on SUCCESS RUNNING]
185
185
  BAD_STATES = %w[fail
186
186
  err
187
187
  error
@@ -189,7 +189,7 @@ module CLIHelper
189
189
  FAILED_DEPLOYING
190
190
  FAILED_UNDEPLOYING
191
191
  FAILED_SCALING]
192
- REGULAR_STATES = %w[pending WARNING]
192
+ REGULAR_STATES = %w[PENDING DEPLOYING CONFIGURING WARNING]
193
193
 
194
194
  # Set state color
195
195
  #
@@ -211,6 +211,17 @@ module CLIHelper
211
211
  end
212
212
  end
213
213
 
214
+ # Get text in green colour
215
+ #
216
+ # @param text [String] String to print
217
+ def self.green(text)
218
+ if $stdout.tty?
219
+ ANSI_GREEN + text + ANSI_RESET
220
+ else
221
+ text
222
+ end
223
+ end
224
+
214
225
  # Print header
215
226
  #
216
227
  # @param str [String] String with header content
@@ -357,14 +368,14 @@ module CLIHelper
357
368
  # @param options [Hash] Object with CLI user options
358
369
  # @param top [Boolean] True to not update columns again
359
370
  def show(data, options = {}, top = false)
371
+ update_columns(options) unless top
372
+
360
373
  if options[:list]
361
374
  @cli_columns = options[:list].collect {|o| o.upcase.to_sym }
362
375
  else
363
376
  @cli_columns = @default_columns
364
377
  end
365
378
 
366
- update_columns(options) unless top
367
-
368
379
  if data.is_a? Hash
369
380
  @data = data
370
381
 
@@ -599,9 +610,7 @@ module CLIHelper
599
610
  end
600
611
  end
601
612
 
602
- if options
603
- filter_data!(res_data, options) if options[:filter]
604
- end
613
+ filter_data!(res_data, options) if options && options[:filter]
605
614
 
606
615
  res_data
607
616
  end
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -481,9 +481,12 @@ module CommandParser
481
481
  begin
482
482
  rc = comm[:proc].call
483
483
 
484
- if rc.instance_of?(Array)
484
+ if rc.instance_of?(Array) && rc[0] != 0
485
+ STDERR.puts rc[1]
486
+ exit(rc[0])
487
+ elsif rc.instance_of?(Array)
485
488
  puts rc[1]
486
- exit rc.first
489
+ exit(rc[0])
487
490
  else
488
491
  exit(@exit_code || rc)
489
492
  end
@@ -537,7 +540,7 @@ module CommandParser
537
540
  begin
538
541
  @cmdparse.parse!(@args)
539
542
  rescue => e
540
- puts e.message
543
+ STDERR.puts e.message
541
544
  exit -1
542
545
  end
543
546
 
@@ -547,8 +550,8 @@ module CommandParser
547
550
  if rc[0] == 0
548
551
  @options[e[:name].to_sym] = rc[1]
549
552
  else
550
- puts rc[1]
551
- puts "option #{e[:name]}: Parsing error"
553
+ STDERR.puts rc[1]
554
+ STDERR.puts "option #{e[:name]}: Parsing error"
552
555
  exit -1
553
556
  end
554
557
  end
@@ -557,11 +560,11 @@ module CommandParser
557
560
 
558
561
  def check_args!(name, arity, args_format)
559
562
  if @args.length < arity
560
- print "Command #{name} requires "
563
+ STDERR.print "Command #{name} requires "
561
564
  if arity>1
562
- puts "#{args_format.length} parameters to run."
565
+ STDERR.puts "#{args_format.length} parameters to run."
563
566
  else
564
- puts "one parameter to run"
567
+ STDERR.puts "one parameter to run"
565
568
  end
566
569
 
567
570
  print_command_help(name)
@@ -579,11 +582,11 @@ module CommandParser
579
582
  end
580
583
  }.join(' ')
581
584
 
582
- puts "Wrong number of arguments"
585
+ STDERR.puts "Wrong number of arguments"
583
586
  if args_str.empty?
584
- puts "No argument is required"
587
+ STDERR.puts "No argument is required"
585
588
  else
586
- puts "The arguments should be: #{args_str}"
589
+ STDERR.puts "The arguments should be: #{args_str}"
587
590
  end
588
591
  exit -1
589
592
  end
@@ -613,9 +616,9 @@ module CommandParser
613
616
 
614
617
  unless argument
615
618
  if error_msg
616
- puts error_msg
619
+ STDERR.puts error_msg
617
620
  else
618
- puts "command #{name}: argument #{id} must be one of #{format.join(', ')}"
621
+ STDERR.puts "command #{name}: argument #{id} must be one of #{format.join(', ')}"
619
622
  end
620
623
  exit -1
621
624
  end
data/lib/one_helper.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -30,17 +30,19 @@ include OpenNebula
30
30
  module OpenNebulaHelper
31
31
  ONE_VERSION=<<-EOT
32
32
  OpenNebula #{OpenNebula::VERSION}
33
- Copyright 2002-2020, OpenNebula Project, OpenNebula Systems
33
+ Copyright 2002-2021, OpenNebula Project, OpenNebula Systems
34
34
  EOT
35
35
 
36
36
  if ONE_LOCATION
37
- TABLE_CONF_PATH=ONE_LOCATION+"/etc/cli"
38
- VAR_LOCATION=ONE_LOCATION+"/var" if !defined?(VAR_LOCATION)
39
- CLI_ADDONS_LOCATION=ONE_LOCATION+"/lib/ruby/cli/addons"
37
+ TABLE_CONF_PATH = ONE_LOCATION + "/etc/cli"
38
+ VAR_LOCATION = ONE_LOCATION + "/var" if !defined?(VAR_LOCATION)
39
+ CLI_ADDONS_LOCATION = ONE_LOCATION + "/lib/ruby/cli/addons"
40
+ XSD_PATH = ONE_LOCATION + '/share/schemas/xsd'
40
41
  else
41
- TABLE_CONF_PATH="/etc/one/cli"
42
- VAR_LOCATION="/var/lib/one" if !defined?(VAR_LOCATION)
43
- CLI_ADDONS_LOCATION="/usr/lib/one/ruby/cli/addons"
42
+ TABLE_CONF_PATH = "/etc/one/cli"
43
+ VAR_LOCATION = "/var/lib/one" if !defined?(VAR_LOCATION)
44
+ CLI_ADDONS_LOCATION = "/usr/lib/one/ruby/cli/addons"
45
+ XSD_PATH = '/usr/share/one/schemas/xsd'
44
46
  end
45
47
 
46
48
  EDITOR_PATH='/usr/bin/vi'
@@ -55,6 +57,23 @@ EOT
55
57
  :description => "Show the resource in xml format"
56
58
  }
57
59
 
60
+ JSON = {
61
+ :name => 'json',
62
+ :short => '-j',
63
+ :large => '--json',
64
+ :description => 'Show the resource in JSON format',
65
+ :proc => lambda do |_, _|
66
+ require 'json'
67
+ end
68
+ }
69
+
70
+ YAML = {
71
+ :name => 'yaml',
72
+ :short => '-y',
73
+ :large => '--yaml',
74
+ :description => 'Show the resource in YAML format'
75
+ }
76
+
58
77
  NUMERIC={
59
78
  :name => "numeric",
60
79
  :short => "-n",
@@ -428,7 +447,9 @@ EOT
428
447
  UPDATECONF_OPTIONS_VM = TEMPLATE_OPTIONS[6..15] + [TEMPLATE_OPTIONS[2],
429
448
  TEMPLATE_OPTIONS[17], TEMPLATE_OPTIONS[18]]
430
449
 
431
- OPTIONS = XML, EXTENDED, NUMERIC, KILOBYTES
450
+ FORMAT = [XML, JSON, YAML]
451
+
452
+ OPTIONS = FORMAT, EXTENDED, NUMERIC, KILOBYTES
432
453
 
433
454
  class OneHelper
434
455
  attr_accessor :client
@@ -590,12 +611,10 @@ EOT
590
611
  end
591
612
 
592
613
  def print_page(pool, options)
593
- page = nil
614
+ elements = 0
615
+ page = ""
594
616
 
595
617
  if options[:xml]
596
- elements = 0
597
- page = ""
598
-
599
618
  pool.each {|e|
600
619
  elements += 1
601
620
  page << e.to_xml(true) << "\n"
@@ -604,8 +623,15 @@ EOT
604
623
  pname = pool.pool_name
605
624
  ename = pool.element_name
606
625
 
607
- page = pool.to_hash
608
- elems = page["#{pname}"]["#{ename}"]
626
+ if options[:decrypt]
627
+ page = pool.map do |element|
628
+ element.info(true)
629
+ element.to_hash[ename]
630
+ end
631
+ else
632
+ page = pool.to_hash
633
+ elems = page[pname][ename]
634
+ end
609
635
 
610
636
  if elems.class == Array
611
637
  elements = elems.length
@@ -626,7 +652,7 @@ EOT
626
652
  size = $stdout.winsize[0] - 1
627
653
 
628
654
  # ----------- First page, check if pager is needed -------------
629
- rc = pool.get_page(size, 0, false)
655
+ rc = pool.get_page(size, 0, false, options[:state])
630
656
  ps = ""
631
657
 
632
658
  return -1, rc.message if OpenNebula.is_error?(rc)
@@ -654,7 +680,7 @@ EOT
654
680
  options[:no_header] = true
655
681
 
656
682
  loop do
657
- rc = pool.get_page(size, current, false)
683
+ rc = pool.get_page(size, current, false, options[:state])
658
684
 
659
685
  return -1, rc.message if OpenNebula.is_error?(rc)
660
686
 
@@ -677,19 +703,20 @@ EOT
677
703
 
678
704
  stop_pager(ppid)
679
705
  else
680
- array = pool.get_hash
681
- return -1, array.message if OpenNebula.is_error?(array)
706
+ rc = pool.info
682
707
 
683
- rname = self.class.rname
684
- elements = array["#{rname}_POOL"][rname]
708
+ return -1, rc.message if OpenNebula.is_error?(rc)
709
+
710
+ elements, hash = print_page(pool, options)
685
711
 
686
- if options[:ids] && elements
687
- elements.reject! do |element|
712
+ if options[:ids] && elements
713
+ arr = [hash[pool.pool_name][pool.element_name]].flatten
714
+ arr.reject! do |element|
688
715
  !options[:ids].include?(element['ID'].to_i)
689
716
  end
690
717
  end
691
718
 
692
- table.show(array, options)
719
+ table.show(hash, options)
693
720
  end
694
721
 
695
722
  return 0
@@ -705,7 +732,7 @@ EOT
705
732
  size = $stdout.winsize[0] - 1
706
733
 
707
734
  # ----------- First page, check if pager is needed -------------
708
- rc = pool.get_page(size, 0, extended)
735
+ rc = pool.get_page(size, 0, extended, options[:state])
709
736
  ps = ""
710
737
 
711
738
  return -1, rc.message if OpenNebula.is_error?(rc)
@@ -740,7 +767,7 @@ EOT
740
767
  current = size
741
768
 
742
769
  loop do
743
- rc = pool.get_page(size, current, extended)
770
+ rc = pool.get_page(size, current, extended, options[:state])
744
771
 
745
772
  return -1, rc.message if OpenNebula.is_error?(rc)
746
773
 
@@ -779,6 +806,82 @@ EOT
779
806
  return 0
780
807
  end
781
808
 
809
+ #-----------------------------------------------------------------------
810
+ # List pool in JSON format, pagination is used in interactive output
811
+ #-----------------------------------------------------------------------
812
+ def list_pool_format(pool, options, filter_flag)
813
+ extended = options.include?(:extended) && options[:extended]
814
+
815
+ if $stdout.isatty and (!options.key?:no_pager)
816
+ size = $stdout.winsize[0] - 1
817
+
818
+ # ----------- First page, check if pager is needed -------------
819
+ rc = pool.get_page(size, 0, extended, options[:state])
820
+ ps = ""
821
+
822
+ return -1, rc.message if OpenNebula.is_error?(rc)
823
+
824
+ elements = get_format_size(pool, options)
825
+ ppid = -1
826
+
827
+ if elements >= size
828
+ ppid = start_pager
829
+ end
830
+
831
+ yield(pool) if block_given?
832
+
833
+ if elements < size
834
+ return 0
835
+ end
836
+
837
+ if elements < size
838
+ return 0
839
+ elsif !pool.is_paginated?
840
+ stop_pager(ppid)
841
+ return 0
842
+ end
843
+
844
+ # ------- Rest of the pages in the pool, piped to pager --------
845
+ current = size
846
+
847
+ loop do
848
+ rc = pool.get_page(size, current, extended, options[:state])
849
+
850
+ return -1, rc.message if OpenNebula.is_error?(rc)
851
+
852
+ current += size
853
+
854
+ begin
855
+ Process.waitpid(ppid, Process::WNOHANG)
856
+ rescue Errno::ECHILD
857
+ break
858
+ end
859
+
860
+ elements = get_format_size(pool, options)
861
+
862
+ break if elements < size
863
+
864
+ yield(pool) if block_given?
865
+
866
+ $stdout.flush
867
+ end
868
+
869
+ stop_pager(ppid)
870
+ else
871
+ if pool.pool_name == "VM_POOL" && extended
872
+ rc = pool.info_all_extended
873
+ else
874
+ rc = pool.info
875
+ end
876
+
877
+ return -1, rc.message if OpenNebula.is_error?(rc)
878
+
879
+ yield(pool) if block_given?
880
+ end
881
+
882
+ return 0
883
+ end
884
+
782
885
  #-----------------------------------------------------------------------
783
886
  # List pool table in top-like form
784
887
  #-----------------------------------------------------------------------
@@ -807,11 +910,27 @@ EOT
807
910
  filter_flag ||= OpenNebula::Pool::INFO_ALL
808
911
 
809
912
  pool = factory_pool(filter_flag)
913
+ pname = pool.pool_name
914
+ ename = pool.element_name
810
915
 
811
916
  if top
812
917
  return list_pool_top(table, pool, options)
813
918
  elsif options[:xml]
814
919
  return list_pool_xml(pool, options, filter_flag)
920
+ elsif options[:json]
921
+ list_pool_format(pool, options, filter_flag) do |pool|
922
+ hash = check_resource_xsd(pool, pname)
923
+ hash[pname] = check_resource_xsd(hash[pname], ename)
924
+
925
+ puts ::JSON.pretty_generate(hash)
926
+ end
927
+ elsif options[:yaml]
928
+ list_pool_format(pool, options, filter_flag) do |pool|
929
+ hash = check_resource_xsd(pool, pname)
930
+ hash[pname] = check_resource_xsd(hash[pname], ename)
931
+
932
+ puts hash.to_yaml(:indent => 4)
933
+ end
815
934
  else
816
935
  return list_pool_table(table, pool, options, filter_flag)
817
936
  end
@@ -855,6 +974,17 @@ EOT
855
974
 
856
975
  if options[:xml]
857
976
  return 0, resource.to_xml(true)
977
+ elsif options[:json]
978
+ # If body is set, the resource contains a JSON inside
979
+ if options[:body]
980
+ return 0, check_resource_xsd(resource)
981
+ else
982
+ return 0, ::JSON.pretty_generate(
983
+ check_resource_xsd(resource)
984
+ )
985
+ end
986
+ elsif options[:yaml]
987
+ return 0, check_resource_xsd(resource).to_yaml(:indent => 4)
858
988
  else
859
989
  format_resource(resource, options)
860
990
  return 0
@@ -881,7 +1011,7 @@ EOT
881
1011
  rc = perform_action(id,options,verbose,&block)
882
1012
 
883
1013
  unless rc[0]==0
884
- puts rc[1]
1014
+ STDERR.puts rc[1]
885
1015
  exit_code=rc[0]
886
1016
  end
887
1017
  end
@@ -1064,6 +1194,199 @@ EOT
1064
1194
 
1065
1195
  return 0, pool
1066
1196
  end
1197
+
1198
+ def get_format_size(pool, options)
1199
+ if options[:json]
1200
+ ::JSON.pretty_generate(pool.to_hash).split("\n").size
1201
+ elsif options[:yaml]
1202
+ pool.to_hash.to_yaml.split("\n").size
1203
+ else
1204
+ STDERR.puts 'ERROR: Format not found'
1205
+ exit(-1)
1206
+ end
1207
+ end
1208
+
1209
+ ########################################################################
1210
+ # XSD check and fix
1211
+ ########################################################################
1212
+
1213
+ # Check XSD values for a single resource
1214
+ #
1215
+ # @param resource [OpenNebula::Object] Resource to check
1216
+ # @param ename [String] Resource name
1217
+ #
1218
+ # @return [Object] Hash with correct values
1219
+ def check_resource_xsd(resource, ename = nil)
1220
+ hash = resource.to_hash
1221
+ ename = hash.keys.first unless ename
1222
+ xsd = read_xsd(ename)
1223
+
1224
+ return hash unless xsd
1225
+
1226
+ hash[ename] = check_xsd(hash[ename], nil, ename, xsd)
1227
+
1228
+ hash
1229
+ end
1230
+
1231
+ # Read XSD file and parse to XML
1232
+ #
1233
+ # @param ename [String] Element name to read XSD
1234
+ #
1235
+ # @return [Hash] XSD in hash format, nil if not found
1236
+ def read_xsd(ename)
1237
+ require 'active_support/core_ext/hash/conversions'
1238
+
1239
+ # Try GEM directory
1240
+ file = File.expand_path(
1241
+ "../share/schemas/xsd/#{ename.downcase}.xsd",
1242
+ File.dirname(__FILE__)
1243
+ )
1244
+
1245
+ file = "#{XSD_PATH}/#{ename.downcase}.xsd" unless File.exist?(file)
1246
+
1247
+ unless File.exist?(file)
1248
+ STDERR.puts "WARNING: XSD for #{ename} not found, skipping check"
1249
+ return nil
1250
+ end
1251
+
1252
+ hash = Hash.from_xml(Nokogiri::XML(File.read(file)).to_s)
1253
+ hash = hash['schema']['element']
1254
+
1255
+ if hash.keys.include?('complexType')
1256
+ hash['complexType']['sequence']['element']
1257
+ else
1258
+ hash['element']
1259
+ end
1260
+ end
1261
+
1262
+ # Check values XSD
1263
+ #
1264
+ # @param hash [Object] Resource information in hash format
1265
+ # @param elements [Array] Keys to check
1266
+ # @param ename [String] Element name to take XSD
1267
+ # @param xsd [Hash] XSD file content
1268
+ # @param parents [Array] Parent keys of current hash
1269
+ def check_xsd(hash, elements, ename, xsd, parents = [])
1270
+ return unless hash
1271
+
1272
+ if (hash.is_a? Hash) && !hash.empty?
1273
+ hash.map do |ki, vi|
1274
+ vi = [vi].flatten if is_array?(xsd, [ki])
1275
+
1276
+ if (vi.is_a? Hash) && !vi.empty?
1277
+ parents << ki
1278
+
1279
+ vi.map do |kj, vj|
1280
+ parents << kj
1281
+
1282
+ path = (parents + [ki, kj]).uniq
1283
+ vj = [vj].flatten if is_array?(xsd, path)
1284
+
1285
+ hash[ki][kj] = check_xsd(vj,
1286
+ [ki, kj],
1287
+ ename,
1288
+ xsd,
1289
+ parents)
1290
+ end
1291
+
1292
+ parents.clear
1293
+ elsif vi.is_a? Array
1294
+ hash[ki] = check_xsd(vi, [ki], ename, xsd, parents)
1295
+ else
1296
+ hash[ki] = check_xsd(vi, [ki], ename, xsd, parents)
1297
+ end
1298
+ end
1299
+
1300
+ hash
1301
+ elsif hash.is_a? Array
1302
+ ret = []
1303
+
1304
+ hash.each do |v|
1305
+ ret << check_xsd(v, elements, ename, xsd, parents)
1306
+ end
1307
+
1308
+ ret
1309
+ else
1310
+ check_type(hash) do
1311
+ type = get_xsd_path(xsd, elements)
1312
+ type['type'] unless type.nil?
1313
+ end
1314
+ end
1315
+ end
1316
+
1317
+ # Get xsd path value
1318
+ #
1319
+ # @param xsd [Hash] XSD information
1320
+ # @param elements [Array] Path to get
1321
+ #
1322
+ # @return [Hash] Path information
1323
+ def get_xsd_path(xsd, elements)
1324
+ return unless elements
1325
+
1326
+ element = elements.shift
1327
+
1328
+ # Return nil, because is an empty complexType
1329
+ return unless element
1330
+
1331
+ element = [xsd].flatten.find do |v|
1332
+ v['name'] == element || v['ref'] == element
1333
+ end
1334
+
1335
+ # Return nil, because element was not find in XSD
1336
+ return unless element
1337
+
1338
+ if element.keys.include?('complexType') && !elements.empty?
1339
+ if element['complexType']['all']
1340
+ element = element['complexType']['all']['element']
1341
+ else
1342
+ element = element['complexType']['sequence']['element']
1343
+ end
1344
+
1345
+ get_xsd_path(element, elements)
1346
+ else
1347
+ element
1348
+ end
1349
+ end
1350
+
1351
+ # CHeck if current element is an array
1352
+ #
1353
+ # @param xsd [Hash] XSD information
1354
+ # @param elements [Array] Path to check
1355
+ #
1356
+ # @return [Boolean] True if it's an array, false otherwise
1357
+ def is_array?(xsd, elements)
1358
+ max = get_xsd_path(xsd, elements)
1359
+ max = max['maxOccurs'] if max
1360
+
1361
+ max == 'unbounded' || max.to_i > 1
1362
+ end
1363
+
1364
+ # Check XSD type for especific value
1365
+ #
1366
+ # @param value [Object] Value to check
1367
+ #
1368
+ # @return [Object] nil if the type is not correct, value otherwise
1369
+ def check_type(value)
1370
+ type = yield if block_given?
1371
+
1372
+ # If there is no type, return current value
1373
+ return value unless type
1374
+
1375
+ types = %w[string decimal integer boolean date time]
1376
+ type = type.split(':')[1]
1377
+
1378
+ if types.include?(type)
1379
+ # If the current type is different, return string
1380
+ # because this value doesn't respect the type
1381
+ if (value.is_a? Hash) || (value.is_a? Array)
1382
+ ''
1383
+ else
1384
+ value
1385
+ end
1386
+ else
1387
+ value
1388
+ end
1389
+ end
1067
1390
  end
1068
1391
 
1069
1392
  def OpenNebulaHelper.rname_to_id(name, poolname)
@@ -1072,18 +1395,20 @@ EOT
1072
1395
  client=OneHelper.client
1073
1396
 
1074
1397
  pool = case poolname
1075
- when "HOST" then OpenNebula::HostPool.new(client)
1076
- when "HOOK" then OpenNebula::HookPool.new(client)
1077
- when "GROUP" then OpenNebula::GroupPool.new(client)
1078
- when "USER" then OpenNebula::UserPool.new(client)
1079
- when "DATASTORE" then OpenNebula::DatastorePool.new(client)
1080
- when "CLUSTER" then OpenNebula::ClusterPool.new(client)
1081
- when "VNET" then OpenNebula::VirtualNetworkPool.new(client)
1082
- when "IMAGE" then OpenNebula::ImagePool.new(client)
1083
- when "VMTEMPLATE" then OpenNebula::TemplatePool.new(client)
1084
- when "VM" then OpenNebula::VirtualMachinePool.new(client)
1085
- when "ZONE" then OpenNebula::ZonePool.new(client)
1086
- when "MARKETPLACE" then OpenNebula::MarketPlacePool.new(client)
1398
+ when "HOST" then OpenNebula::HostPool.new(client)
1399
+ when "HOOK" then OpenNebula::HookPool.new(client)
1400
+ when "GROUP" then OpenNebula::GroupPool.new(client)
1401
+ when "USER" then OpenNebula::UserPool.new(client)
1402
+ when "DATASTORE" then OpenNebula::DatastorePool.new(client)
1403
+ when "CLUSTER" then OpenNebula::ClusterPool.new(client)
1404
+ when "VNET" then OpenNebula::VirtualNetworkPool.new(client)
1405
+ when "IMAGE" then OpenNebula::ImagePool.new(client)
1406
+ when "VMTEMPLATE" then OpenNebula::TemplatePool.new(client)
1407
+ when "VNTEMPLATES" then OpenNebula::VNTemplatePool.new(client)
1408
+ when "VM" then OpenNebula::VirtualMachinePool.new(client)
1409
+ when "ZONE" then OpenNebula::ZonePool.new(client)
1410
+ when "MARKETPLACE" then OpenNebula::MarketPlacePool.new(client)
1411
+ when "FLOWTEMPLATES" then OpenNebula::ServiceTemplatePool.new(client)
1087
1412
  end
1088
1413
 
1089
1414
  rc = pool.info
@@ -1269,6 +1594,43 @@ EOT
1269
1594
  end
1270
1595
  end
1271
1596
 
1597
+ def OpenNebulaHelper.update_obj(obj, file, plain = false)
1598
+ rc = obj.info(true)
1599
+
1600
+ return rc if OpenNebula.is_error?(rc)
1601
+
1602
+ if file
1603
+ path = file
1604
+ else
1605
+ tmp = Tempfile.new(obj['ID'])
1606
+ path = tmp.path
1607
+
1608
+ tmp.write(yield(obj)) if block_given?
1609
+ tmp.flush
1610
+
1611
+ if ENV['EDITOR']
1612
+ editor_path = ENV['EDITOR']
1613
+ else
1614
+ editor_path = EDITOR_PATH
1615
+ end
1616
+
1617
+ system("#{editor_path} #{path}")
1618
+
1619
+ unless $CHILD_STATUS.exitstatus.zero?
1620
+ STDERR.puts 'Editor not defined'
1621
+ exit(-1)
1622
+ end
1623
+
1624
+ tmp.close
1625
+ end
1626
+
1627
+ if plain
1628
+ obj.update(File.read(path), plain)
1629
+ else
1630
+ obj.update(File.read(path))
1631
+ end
1632
+ end
1633
+
1272
1634
  def OpenNebulaHelper.editor_input(contents=nil)
1273
1635
  require 'tempfile'
1274
1636