opennebula-cli 5.10.5 → 5.11.80.pre

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 +9 -9
  11. data/bin/oneimage +2 -1
  12. data/bin/onemarket +2 -1
  13. data/bin/onemarketapp +2 -1
  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 +2 -1
  26. data/lib/cli_helper.rb +10 -4
  27. data/lib/command_parser.rb +32 -13
  28. data/lib/one_helper.rb +193 -2
  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 +1 -1
  32. data/lib/one_helper/onedatastore_helper.rb +1 -1
  33. data/lib/one_helper/oneflow_helper.rb +413 -0
  34. data/lib/one_helper/oneflowtemplate_helper.rb +306 -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 +29 -27
  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 +1 -1
  54. metadata +10 -8
@@ -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 #
@@ -28,6 +28,7 @@ end
28
28
 
29
29
  if File.directory?(GEMS_LOCATION)
30
30
  Gem.use_paths(GEMS_LOCATION)
31
+ $LOAD_PATH.reject! {|l| l =~ /(vendor|site)_ruby/ }
31
32
  end
32
33
 
33
34
  $LOAD_PATH << RUBY_LIB_LOCATION
@@ -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 #
@@ -28,6 +28,7 @@ end
28
28
 
29
29
  if File.directory?(GEMS_LOCATION)
30
30
  Gem.use_paths(GEMS_LOCATION)
31
+ $LOAD_PATH.reject! {|l| l =~ /(vendor|site)_ruby/ }
31
32
  end
32
33
 
33
34
  $LOAD_PATH << RUBY_LIB_LOCATION
@@ -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 #
@@ -28,6 +28,7 @@ end
28
28
 
29
29
  if File.directory?(GEMS_LOCATION)
30
30
  Gem.use_paths(GEMS_LOCATION)
31
+ $LOAD_PATH.reject! {|l| l =~ /(vendor|site)_ruby/ }
31
32
  end
32
33
 
33
34
  $LOAD_PATH << RUBY_LIB_LOCATION
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2020, 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,9 +181,15 @@ module CLIHelper
181
181
  ANSI_YELLOW = "\33[33m"
182
182
 
183
183
  # CLI states
184
- OK_STATES = %w[runn rdy on configured SUCCESS]
185
- BAD_STATES = %w[fail err error ERROR]
186
- REGULAR_STATES = %w[pending]
184
+ OK_STATES = %w[runn rdy on configured SUCCESS RUNNING]
185
+ BAD_STATES = %w[fail
186
+ err
187
+ error
188
+ ERROR
189
+ FAILED_DEPLOYING
190
+ FAILED_UNDEPLOYING
191
+ FAILED_SCALING]
192
+ REGULAR_STATES = %w[pending WARNING]
187
193
 
188
194
  # Set state color
189
195
  #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2020, 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 #
@@ -140,6 +140,7 @@ module CommandParser
140
140
  # @option options [String] :name
141
141
  # @option options [String] :short
142
142
  # @option options [String] :large
143
+ # @option options [Boolean] :multiple
143
144
  # @option options [String] :description
144
145
  # @option options [Class] :format
145
146
  # @option options [Block] :proc The block receives the value of the
@@ -452,7 +453,7 @@ module CommandParser
452
453
 
453
454
  if comm.nil?
454
455
  print_help
455
- exit -1
456
+ exit 0
456
457
  end
457
458
 
458
459
  if comm[:deprecated]
@@ -463,16 +464,27 @@ module CommandParser
463
464
  parse(extra_options)
464
465
 
465
466
  if comm
466
- @before_proc.call if @before_proc
467
+ begin
468
+ @before_proc.call if @before_proc
469
+ rescue StandardError => e
470
+ STDERR.puts e.message
471
+ exit(-1)
472
+ end
467
473
 
468
474
  check_args!(comm_name, comm[:arity], comm[:args_format])
469
475
 
470
- rc = comm[:proc].call
471
- if rc.instance_of?(Array)
472
- puts rc[1]
473
- exit rc.first
474
- else
475
- exit(@exit_code || rc)
476
+ begin
477
+ rc = comm[:proc].call
478
+
479
+ if rc.instance_of?(Array)
480
+ puts rc[1]
481
+ exit rc.first
482
+ else
483
+ exit(@exit_code || rc)
484
+ end
485
+ rescue StandardError => e
486
+ STDERR.puts e.message
487
+ exit(-1)
476
488
  end
477
489
  end
478
490
  end
@@ -490,21 +502,28 @@ module CommandParser
490
502
  args = []
491
503
  args << e[:short] if e[:short]
492
504
  args << e[:large]
505
+ args << e[:multiple] if e[:multiple]
493
506
  args << e[:format]
494
507
  args << e[:description]
495
508
 
496
509
  opts.on(*args) do |o|
497
- if e[:proc]
510
+ if e[:proc] && !e[:multiple]
498
511
  @options[e[:name].to_sym]=o
499
512
  with_proc<<e
500
513
  elsif e[:name]=="help"
501
514
  print_help
502
- exit
515
+ exit 0
503
516
  elsif e[:name]=="version"
504
517
  puts @version
505
- exit
506
- else
518
+ exit 0
519
+ elsif !e[:multiple]
507
520
  @options[e[:name].to_sym]=o
521
+ else
522
+ if @options[e[:name].to_sym].nil?
523
+ @options[e[:name].to_sym] = []
524
+ end
525
+
526
+ @options[e[:name].to_sym] << o
508
527
  end
509
528
  end
510
529
  end
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2020, 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,7 +30,7 @@ include OpenNebula
30
30
  module OpenNebulaHelper
31
31
  ONE_VERSION=<<-EOT
32
32
  OpenNebula #{OpenNebula::VERSION}
33
- Copyright 2002-2019, OpenNebula Project, OpenNebula Systems
33
+ Copyright 2002-2020, OpenNebula Project, OpenNebula Systems
34
34
 
35
35
  Licensed under the Apache License, Version 2.0 (the "License"); you may
36
36
  not use this file except in compliance with the License. You may obtain
@@ -1696,4 +1696,195 @@ EOT
1696
1696
  "-"
1697
1697
  end
1698
1698
  end
1699
+
1700
+ def OpenNebulaHelper.parse_user_inputs(inputs, get_defaults = false)
1701
+ unless get_defaults
1702
+ puts 'There are some parameters that require user input. ' \
1703
+ 'Use the string <<EDITOR>> to launch an editor ' \
1704
+ '(e.g. for multi-line inputs)'
1705
+ end
1706
+
1707
+ answers = {}
1708
+
1709
+ inputs.each do |key, val|
1710
+ input_cfg = val.split('|', -1)
1711
+
1712
+ if input_cfg.length < 3
1713
+ STDERR.puts 'Malformed user input. It should have at least 3 '\
1714
+ "parts separated by '|':"
1715
+ STDERR.puts " #{key}: #{val}"
1716
+ exit(-1)
1717
+ end
1718
+
1719
+ mandatory, type, description, params, initial = input_cfg
1720
+ optional = mandatory.strip == 'O'
1721
+ type.strip!
1722
+ description.strip!
1723
+
1724
+ if input_cfg.length > 3
1725
+ if input_cfg.length != 5
1726
+ STDERR.puts 'Malformed user input. It should have 5 parts'\
1727
+ " separated by '|':"
1728
+ STDERR.puts " #{key}: #{val}"
1729
+ exit(-1)
1730
+ end
1731
+
1732
+ params.strip!
1733
+ initial.strip!
1734
+ end
1735
+
1736
+ if get_defaults
1737
+ answers[key]= initial unless mandatory == 'M'
1738
+ next
1739
+ end
1740
+
1741
+ puts " * (#{key}) #{description}"
1742
+
1743
+ header = ' '
1744
+ if !initial.nil? && initial != ''
1745
+ header += "Press enter for default (#{initial}). "
1746
+ end
1747
+
1748
+ case type
1749
+ when 'text', 'text64'
1750
+ print header
1751
+
1752
+ answer = STDIN.readline.chop
1753
+
1754
+ if answer == '<<EDITOR>>'
1755
+ answer = OpenNebulaHelper.editor_input
1756
+ end
1757
+
1758
+ # use default in case it's empty
1759
+ answer = initial if answer.empty?
1760
+
1761
+ if type == 'text64'
1762
+ answer = Base64.encode64(answer).strip.delete("\n")
1763
+ end
1764
+
1765
+ when 'boolean'
1766
+ print header
1767
+
1768
+ answer = STDIN.readline.chop
1769
+
1770
+ # use default in case it's empty
1771
+ answer = initial if answer.empty?
1772
+
1773
+ unless %w[YES NO].include?(answer)
1774
+ STDERR.puts "Invalid boolean '#{answer}'"
1775
+ STDERR.puts 'Boolean has to be YES or NO'
1776
+ exit(-1)
1777
+ end
1778
+
1779
+ when 'password'
1780
+ print header
1781
+
1782
+ answer = OpenNebulaHelper::OneHelper.get_password
1783
+
1784
+ # use default in case it's empty
1785
+ answer = initial if answer.empty?
1786
+
1787
+ when 'number', 'number-float'
1788
+ if type == 'number'
1789
+ header += 'Integer: '
1790
+ exp = INT_EXP
1791
+ else
1792
+ header += 'Float: '
1793
+ exp = FLOAT_EXP
1794
+ end
1795
+
1796
+ begin
1797
+ print header
1798
+ answer = STDIN.readline.chop
1799
+
1800
+ answer = initial if answer == ''
1801
+ noanswer = ((answer == '') && optional)
1802
+ end while !noanswer && (answer =~ exp) == nil
1803
+
1804
+ if noanswer
1805
+ next
1806
+ end
1807
+
1808
+ when 'range', 'range-float'
1809
+ min, max = params.split('..')
1810
+
1811
+ if min.nil? || max.nil?
1812
+ STDERR.puts 'Malformed user input. '\
1813
+ "Parameters should be 'min..max':"
1814
+ STDERR.puts " #{key}: #{val}"
1815
+ exit(-1)
1816
+ end
1817
+
1818
+ if type == 'range'
1819
+ exp = INT_EXP
1820
+ min = min.to_i
1821
+ max = max.to_i
1822
+
1823
+ header += "Integer in the range [#{min}..#{max}]: "
1824
+ else
1825
+ exp = FLOAT_EXP
1826
+ min = min.to_f
1827
+ max = max.to_f
1828
+
1829
+ header += "Float in the range [#{min}..#{max}]: "
1830
+ end
1831
+
1832
+ begin
1833
+ print header
1834
+ answer = STDIN.readline.chop
1835
+
1836
+ answer = initial if answer == ''
1837
+
1838
+ noanswer = (answer == '') && optional
1839
+ end while !noanswer && ((answer =~ exp) == nil ||
1840
+ answer.to_f < min || answer.to_f > max)
1841
+
1842
+ if noanswer
1843
+ next
1844
+ end
1845
+
1846
+ when 'list'
1847
+ options = params.split(',')
1848
+
1849
+ options.each_with_index do |opt, i|
1850
+ puts " #{i} #{opt}"
1851
+ end
1852
+
1853
+ puts
1854
+
1855
+ header += 'Please type the selection number: '
1856
+
1857
+ begin
1858
+ print header
1859
+ answer = STDIN.readline.chop
1860
+
1861
+ if answer == ''
1862
+ answer = initial
1863
+ else
1864
+ answer = options[answer.to_i]
1865
+ end
1866
+
1867
+ noanswer = ((answer == '') && optional)
1868
+ end while !noanswer && !options.include?(answer)
1869
+
1870
+ if noanswer
1871
+ next
1872
+ end
1873
+
1874
+ when 'fixed'
1875
+ puts " Fixed value of (#{initial}). Cannot be changed"
1876
+ answer = initial
1877
+
1878
+ else
1879
+ STDERR.puts 'Wrong type for user input:'
1880
+ STDERR.puts " #{key}: #{val}"
1881
+ exit(-1)
1882
+ end
1883
+
1884
+ answers[key] = answer
1885
+ end
1886
+
1887
+ answers
1888
+ end
1889
+
1699
1890
  end
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2020, 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 #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2020, 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 #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2020, 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 #
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2020, 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 #
@@ -0,0 +1,413 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
3
+ # #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+
17
+ require 'one_helper'
18
+
19
+ # Oneflow command helper
20
+ class OneFlowHelper < OpenNebulaHelper::OneHelper
21
+
22
+ # Get client to make request
23
+ #
24
+ # @options [Hash] CLI options
25
+ def client(options)
26
+ Service::Client.new(
27
+ :username => options[:username],
28
+ :password => options[:password],
29
+ :url => options[:server],
30
+ :user_agent => USER_AGENT
31
+ )
32
+ end
33
+
34
+ # Get service pool table
35
+ def format_service_pool
36
+ # TODO: config file
37
+ CLIHelper::ShowTable.new(nil, self) do
38
+ column :ID, 'ID', :size => 10 do |d|
39
+ d['ID']
40
+ end
41
+
42
+ column :USER, 'Username', :left, :size => 15 do |d|
43
+ d['UNAME']
44
+ end
45
+
46
+ column :GROUP, 'Group', :left, :size => 15 do |d|
47
+ d['GNAME']
48
+ end
49
+
50
+ column :NAME, 'Name', :expand => true, :left => true do |d|
51
+ d['NAME']
52
+ end
53
+
54
+ column :STAT, 'State', :size => 11, :left => true do |d|
55
+ Service.state_str(d['TEMPLATE']['BODY']['state'])
56
+ end
57
+
58
+ default :ID, :USER, :GROUP, :NAME, :STAT
59
+ end
60
+ end
61
+
62
+ # List service pool
63
+ #
64
+ # @param client [Service::Client] Petition client
65
+ # @param options [Hash] CLI options
66
+ def list_service_pool(client, options)
67
+ response = client.get(RESOURCE_PATH)
68
+
69
+ if CloudClient.is_error?(response)
70
+ [response.code.to_i, response.to_s]
71
+ else
72
+ array_list = JSON.parse(response.body)
73
+ array_list = array_list['DOCUMENT_POOL']['DOCUMENT']
74
+
75
+ array_list = [] if array_list.nil?
76
+
77
+ unless options.key? :done
78
+ # remove from list flows in DONE state
79
+ array_list.reject! do |value|
80
+ value['TEMPLATE']['BODY']['state'] == 5
81
+ end
82
+ end
83
+
84
+ if options[:json]
85
+ if array_list.empty?
86
+ 0
87
+ else
88
+ [0, JSON.pretty_generate(array_list)]
89
+ end
90
+ else
91
+ format_service_pool.show(array_list)
92
+
93
+ 0
94
+ end
95
+ end
96
+ end
97
+
98
+ # List service pool continiously
99
+ #
100
+ # @param client [Service::Client] Petition client
101
+ # @param options [Hash] CLI options
102
+ def top_service_pool(client, options)
103
+ # TODO: make default delay configurable
104
+ options[:delay] ? delay = options[:delay] : delay = 4
105
+
106
+ begin
107
+ loop do
108
+ CLIHelper.scr_cls
109
+ CLIHelper.scr_move(0, 0)
110
+
111
+ list_service_pool(client, options)
112
+
113
+ sleep delay
114
+ end
115
+ rescue StandardError => e
116
+ STDERR.puts e.message
117
+ exit(-1)
118
+ end
119
+
120
+ 0
121
+ end
122
+
123
+ # Show service detailed information
124
+ #
125
+ # @param client [Service::Client] Petition client
126
+ # @param service [Integer] Service ID
127
+ # @param options [Hash] CLI options
128
+ def format_resource(client, service, options)
129
+ response = client.get("#{RESOURCE_PATH}/#{service}")
130
+
131
+ if CloudClient.is_error?(response)
132
+ [response.code.to_i, response.to_s]
133
+ else
134
+ if options[:json]
135
+ [0, response.body]
136
+ else
137
+ str_h1 = '%-80s'
138
+ document = JSON.parse(response.body)['DOCUMENT']
139
+ template = document['TEMPLATE']['BODY']
140
+
141
+ CLIHelper.print_header(
142
+ str_h1 % "SERVICE #{document['ID']} INFORMATION"
143
+ )
144
+
145
+ print_service_info(document)
146
+
147
+ print_roles_info(template['roles'])
148
+
149
+ return 0 unless template['log']
150
+
151
+ CLIHelper.print_header(str_h1 % 'LOG MESSAGES', false)
152
+
153
+ template['log'].each do |log|
154
+ t = Time.at(log['timestamp']).strftime('%m/%d/%y %H:%M')
155
+ puts "#{t} [#{log['severity']}] #{log['message']}"
156
+ end
157
+
158
+ 0
159
+ end
160
+ end
161
+ end
162
+
163
+ # Get policy adjust information in str format
164
+ #
165
+ # @param policy [Hash] Policy information
166
+ def self.adjust_str(policy)
167
+ policy['adjust'].to_i >= 0 ? sign = '+' : sign = '-'
168
+ adjust = policy['adjust'].to_i.abs
169
+
170
+ case policy['type']
171
+ when 'CARDINALITY'
172
+ "= #{adjust}"
173
+ when 'PERCENTAGE_CHANGE'
174
+ st = "#{sign} #{adjust} %"
175
+
176
+ if policy['min_adjust_step']
177
+ st << " (#{policy['min_adjust_step']})"
178
+ end
179
+
180
+ st
181
+ else
182
+ "#{sign} #{adjust}"
183
+ end
184
+ end
185
+
186
+ private
187
+
188
+ # Get nodes pool table
189
+ def format_node_pool
190
+ # TODO: config file
191
+ CLIHelper::ShowTable.new(nil, self) do
192
+ column :VM_ID,
193
+ 'ONE identifier for Virtual Machine',
194
+ :size => 6 do |d|
195
+ st = ''
196
+
197
+ if d['scale_up']
198
+ st << '\u2191 '
199
+ elsif d['disposed']
200
+ st << '\u2193 '
201
+ end
202
+
203
+ if d['vm_info'].nil?
204
+ st << d['deploy_id'].to_s
205
+ else
206
+ st << d['vm_info']['VM']['ID']
207
+ end
208
+
209
+ st
210
+ end
211
+
212
+ column :NAME,
213
+ 'Name of the Virtual Machine',
214
+ :left,
215
+ :size => 24 do |d|
216
+ if !d['vm_info'].nil?
217
+ if d['vm_info']['VM']['RESCHED'] == '1'
218
+ "*#{d['NAME']}"
219
+ else
220
+ d['vm_info']['VM']['NAME']
221
+ end
222
+ else
223
+ ''
224
+ end
225
+ end
226
+
227
+ column :USER,
228
+ 'Username of the Virtual Machine owner',
229
+ :left,
230
+ :size => 15 do |d|
231
+ if !d['vm_info'].nil?
232
+ d['vm_info']['VM']['UNAME']
233
+ else
234
+ ''
235
+ end
236
+ end
237
+
238
+ column :GROUP,
239
+ 'Group of the Virtual Machine',
240
+ :left,
241
+ :size => 15 do |d|
242
+ if !d['vm_info'].nil?
243
+ d['vm_info']['VM']['GNAME']
244
+ else
245
+ ''
246
+ end
247
+ end
248
+
249
+ default :VM_ID, :NAME, :USER, :GROUP
250
+ end
251
+ end
252
+
253
+ # Print service information
254
+ #
255
+ # @param document [Hash] Service document information
256
+ def print_service_info(document)
257
+ str = '%-20s: %-20s'
258
+ str_h1 = '%-80s'
259
+ template = document['TEMPLATE']['BODY']
260
+
261
+ puts Kernel.format(str, 'ID', document['ID'])
262
+ puts Kernel.format(str, 'NAME', document['NAME'])
263
+ puts Kernel.format(str, 'USER', document['UNAME'])
264
+ puts Kernel.format(str, 'GROUP', document['GNAME'])
265
+
266
+ puts Kernel.format(str, 'STRATEGY', template['deployment'])
267
+ puts Kernel.format(str,
268
+ 'SERVICE STATE',
269
+ Service.state_str(template['state']))
270
+
271
+ if template['shutdown_action']
272
+ puts Kernel.format(str, 'SHUTDOWN', template['shutdown_action'])
273
+ end
274
+
275
+ puts
276
+
277
+ CLIHelper.print_header(str_h1 % 'PERMISSIONS', false)
278
+
279
+ %w[OWNER GROUP OTHER].each do |e|
280
+ mask = '---'
281
+ permissions_hash = document['PERMISSIONS']
282
+ mask[0] = 'u' if permissions_hash["#{e}_U"] == '1'
283
+ mask[1] = 'm' if permissions_hash["#{e}_M"] == '1'
284
+ mask[2] = 'a' if permissions_hash["#{e}_A"] == '1'
285
+
286
+ puts Kernel.format(str, e, mask)
287
+ end
288
+
289
+ puts
290
+ end
291
+
292
+ # Print service roles information
293
+ #
294
+ # @param roles [Array] Service roles information
295
+ def print_roles_info(roles)
296
+ str = '%-20s: %-20s'
297
+
298
+ roles.each do |role|
299
+ CLIHelper.print_header("ROLE #{role['name']}", false)
300
+
301
+ puts Kernel.format(str,
302
+ 'ROLE STATE',
303
+ Role.state_str(role['state']))
304
+
305
+ if role['parents']
306
+ puts Kernel.format(str,
307
+ 'PARENTS',
308
+ role['parents'].join(', '))
309
+ end
310
+
311
+ puts Kernel.format(str, 'VM TEMPLATE', role['vm_template'])
312
+ puts Kernel.format(str, 'CARDINALITY', role['cardinality'])
313
+
314
+ if role['min_vms']
315
+ puts Kernel.format(str, 'MIN VMS', role['min_vms'])
316
+ end
317
+
318
+ if role['max_vms']
319
+ puts Kernel.format(str, 'MAX VMS', role['max_vms'])
320
+ end
321
+
322
+ if role['coolddown']
323
+ puts Kernel.format(str, 'COOLDOWN', "#{role['cooldown']}s")
324
+ end
325
+
326
+ if role['shutdown_action']
327
+ puts Kernel.format(str, 'SHUTDOWN', role['shutdown_action'])
328
+ end
329
+
330
+ if role['elasticity_policies'] &&
331
+ !role['elasticity_policies'].empty?
332
+ print_elasticity_info(role)
333
+ end
334
+
335
+ if role['scheduled_policies'] &&
336
+ !role['scheduled_policies'].empty?
337
+ print_scheduled_info(role)
338
+ end
339
+
340
+ puts
341
+ CLIHelper.print_header('NODES INFORMATION', false)
342
+
343
+ format_node_pool.show(role['nodes'])
344
+ puts
345
+ end
346
+ end
347
+
348
+ # Print role elasticity info
349
+ #
350
+ # @param role [OpenNebula::Role] Role information
351
+ def print_elasticity_info(role)
352
+ puts
353
+ CLIHelper.print_header('ROLE ELASTICITY', false)
354
+
355
+ CLIHelper::ShowTable.new(nil, self) do
356
+ column :ADJUST, '', :left, :size => 12 do |d|
357
+ OneFlowHelper.adjust_str(d)
358
+ end
359
+
360
+ column :EXPRESSION, '', :left, :size => 48 do |d|
361
+ if !d['expression_evaluated'].nil?
362
+ d['expression_evaluated']
363
+ else
364
+ d['expression']
365
+ end
366
+ end
367
+
368
+ column :EVALS, '', :right, :size => 5 do |d|
369
+ if d['period_number']
370
+ "#{d['true_evals'].to_i}/"\
371
+ "#{d['period_number']}"
372
+ else
373
+ '-'
374
+ end
375
+ end
376
+
377
+ column :PERIOD, '', :size => 6 do |d|
378
+ d['period'] ? "#{d['period']}s" : '-'
379
+ end
380
+
381
+ column :COOL, '', :size => 5 do |d|
382
+ d['cooldown'] ? "#{d['cooldown']}s" : '-'
383
+ end
384
+
385
+ default :ADJUST, :EXPRESSION, :EVALS, :PERIOD, :COOL
386
+ end.show([role['elasticity_policies']].flatten, {})
387
+ end
388
+
389
+ # Print role schedule info
390
+ #
391
+ # @param role [OpenNebula::Role] Role information
392
+ def print_scheduled_info(role)
393
+ puts
394
+ CLIHelper.print_header('ROLE ELASTICITY SCHEDULE', false)
395
+
396
+ CLIHelper::ShowTable.new(nil, self) do
397
+ column :ADJUST, '', :left, :size => 12 do |d|
398
+ OneFlowHelper.adjust_str(d)
399
+ end
400
+
401
+ column :TIME, '', :left, :size => 67 do |d|
402
+ if d['start_time']
403
+ Time.parse(d['start_time']).to_s
404
+ else
405
+ d['recurrence']
406
+ end
407
+ end
408
+
409
+ default :ADJUST, :TIME
410
+ end.show([role['scheduled_policies']].flatten, {})
411
+ end
412
+
413
+ end