opennebula-cli 5.10.5 → 5.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/bin/oneacct +4 -2
  3. data/bin/oneacl +4 -2
  4. data/bin/onecluster +4 -2
  5. data/bin/onedatastore +4 -2
  6. data/bin/oneflow +151 -552
  7. data/bin/oneflow-template +173 -293
  8. data/bin/onegroup +4 -2
  9. data/bin/onehook +4 -2
  10. data/bin/onehost +78 -10
  11. data/bin/oneimage +4 -2
  12. data/bin/onemarket +4 -2
  13. data/bin/onemarketapp +17 -4
  14. data/bin/onesecgroup +4 -2
  15. data/bin/oneshowback +4 -2
  16. data/bin/onetemplate +4 -2
  17. data/bin/oneuser +4 -2
  18. data/bin/onevcenter +4 -2
  19. data/bin/onevdc +4 -2
  20. data/bin/onevm +170 -17
  21. data/bin/onevmgroup +4 -2
  22. data/bin/onevnet +16 -41
  23. data/bin/onevntemplate +4 -2
  24. data/bin/onevrouter +4 -2
  25. data/bin/onezone +7 -2
  26. data/lib/cli_helper.rb +54 -30
  27. data/lib/command_parser.rb +53 -19
  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 +423 -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 +5 -4
  47. data/lib/one_helper/onevdc_helper.rb +1 -1
  48. data/lib/one_helper/onevm_helper.rb +117 -21
  49. data/lib/one_helper/onevmgroup_helper.rb +1 -1
  50. data/lib/one_helper/onevnet_helper.rb +66 -2
  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,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,11 +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
34
-
35
- Licensed under the Apache License, Version 2.0 (the "License"); you may
36
- not use this file except in compliance with the License. You may obtain
37
- a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
33
+ Copyright 2002-2020, OpenNebula Project, OpenNebula Systems
38
34
  EOT
39
35
 
40
36
  if ONE_LOCATION
@@ -1203,6 +1199,18 @@ EOT
1203
1199
  end
1204
1200
  end
1205
1201
 
1202
+ def OpenNebulaHelper.bytes_to_unit(value, unit = 'K')
1203
+ j = 0
1204
+ i = BinarySufix.index(unit).to_i
1205
+
1206
+ while j < i do
1207
+ value /= 1024.0
1208
+ j += 1
1209
+ end
1210
+
1211
+ value
1212
+ end
1213
+
1206
1214
  # If the cluster name is empty, returns a '-' char.
1207
1215
  #
1208
1216
  # @param str [String || Hash] Cluster name, or empty Hash (when <CLUSTER/>)
@@ -1696,4 +1704,248 @@ EOT
1696
1704
  "-"
1697
1705
  end
1698
1706
  end
1707
+
1708
+ def OpenNebulaHelper.parse_user_inputs(inputs, get_defaults = false)
1709
+ unless get_defaults
1710
+ puts 'There are some parameters that require user input. ' \
1711
+ 'Use the string <<EDITOR>> to launch an editor ' \
1712
+ '(e.g. for multi-line inputs)'
1713
+ end
1714
+
1715
+ answers = {}
1716
+
1717
+ inputs.each do |key, val|
1718
+ input_cfg = val.split('|', -1)
1719
+
1720
+ if input_cfg.length < 3
1721
+ STDERR.puts 'Malformed user input. It should have at least 3 '\
1722
+ "parts separated by '|':"
1723
+ STDERR.puts " #{key}: #{val}"
1724
+ exit(-1)
1725
+ end
1726
+
1727
+ mandatory, type, description, params, initial = input_cfg
1728
+ optional = mandatory.strip == 'O'
1729
+ type.strip!
1730
+ description.strip!
1731
+
1732
+ if input_cfg.length > 3
1733
+ if input_cfg.length != 5
1734
+ STDERR.puts 'Malformed user input. It should have 5 parts'\
1735
+ " separated by '|':"
1736
+ STDERR.puts " #{key}: #{val}"
1737
+ exit(-1)
1738
+ end
1739
+
1740
+ params.strip!
1741
+ initial.strip!
1742
+ end
1743
+
1744
+ if get_defaults
1745
+ answers[key]= initial unless mandatory == 'M'
1746
+ next
1747
+ end
1748
+
1749
+ puts " * (#{key}) #{description}"
1750
+
1751
+ header = ' '
1752
+ if !initial.nil? && initial != ''
1753
+ header += "Press enter for default (#{initial}). "
1754
+ end
1755
+
1756
+ case type
1757
+ when 'text', 'text64'
1758
+ print header
1759
+
1760
+ answer = STDIN.readline.chop
1761
+
1762
+ if answer == '<<EDITOR>>'
1763
+ answer = OpenNebulaHelper.editor_input
1764
+ end
1765
+
1766
+ # use default in case it's empty
1767
+ answer = initial if answer.empty?
1768
+
1769
+ if type == 'text64'
1770
+ answer = Base64.encode64(answer).strip.delete("\n")
1771
+ end
1772
+
1773
+ when 'boolean'
1774
+ print header
1775
+
1776
+ answer = STDIN.readline.chop
1777
+
1778
+ # use default in case it's empty
1779
+ answer = initial if answer.empty?
1780
+
1781
+ unless %w[YES NO].include?(answer)
1782
+ STDERR.puts "Invalid boolean '#{answer}'"
1783
+ STDERR.puts 'Boolean has to be YES or NO'
1784
+ exit(-1)
1785
+ end
1786
+
1787
+ when 'password'
1788
+ print header
1789
+
1790
+ answer = OpenNebulaHelper::OneHelper.get_password
1791
+
1792
+ # use default in case it's empty
1793
+ answer = initial if answer.empty?
1794
+
1795
+ when 'number', 'number-float'
1796
+ if type == 'number'
1797
+ header += 'Integer: '
1798
+ exp = INT_EXP
1799
+ else
1800
+ header += 'Float: '
1801
+ exp = FLOAT_EXP
1802
+ end
1803
+
1804
+ begin
1805
+ print header
1806
+ answer = STDIN.readline.chop
1807
+
1808
+ answer = initial if answer == ''
1809
+ noanswer = ((answer == '') && optional)
1810
+ end while !noanswer && (answer =~ exp) == nil
1811
+
1812
+ if noanswer
1813
+ next
1814
+ end
1815
+
1816
+ when 'range', 'range-float'
1817
+ min, max = params.split('..')
1818
+
1819
+ if min.nil? || max.nil?
1820
+ STDERR.puts 'Malformed user input. '\
1821
+ "Parameters should be 'min..max':"
1822
+ STDERR.puts " #{key}: #{val}"
1823
+ exit(-1)
1824
+ end
1825
+
1826
+ if type == 'range'
1827
+ exp = INT_EXP
1828
+ min = min.to_i
1829
+ max = max.to_i
1830
+
1831
+ header += "Integer in the range [#{min}..#{max}]: "
1832
+ else
1833
+ exp = FLOAT_EXP
1834
+ min = min.to_f
1835
+ max = max.to_f
1836
+
1837
+ header += "Float in the range [#{min}..#{max}]: "
1838
+ end
1839
+
1840
+ begin
1841
+ print header
1842
+ answer = STDIN.readline.chop
1843
+
1844
+ answer = initial if answer == ''
1845
+
1846
+ noanswer = (answer == '') && optional
1847
+ end while !noanswer && ((answer =~ exp) == nil ||
1848
+ answer.to_f < min || answer.to_f > max)
1849
+
1850
+ if noanswer
1851
+ next
1852
+ end
1853
+
1854
+ when 'list'
1855
+ options = params.split(',')
1856
+
1857
+ options.each_with_index do |opt, i|
1858
+ puts " #{i} #{opt}"
1859
+ end
1860
+
1861
+ puts
1862
+
1863
+ header += 'Please type the selection number: '
1864
+
1865
+ begin
1866
+ print header
1867
+ answer = STDIN.readline.chop
1868
+
1869
+ if answer == ''
1870
+ answer = initial
1871
+ else
1872
+ answer = options[answer.to_i]
1873
+ end
1874
+
1875
+ noanswer = ((answer == '') && optional)
1876
+ end while !noanswer && !options.include?(answer)
1877
+
1878
+ if noanswer
1879
+ next
1880
+ end
1881
+
1882
+ when 'fixed'
1883
+ puts " Fixed value of (#{initial}). Cannot be changed"
1884
+ answer = initial
1885
+
1886
+ else
1887
+ STDERR.puts 'Wrong type for user input:'
1888
+ STDERR.puts " #{key}: #{val}"
1889
+ exit(-1)
1890
+ end
1891
+
1892
+ answers[key] = answer
1893
+ end
1894
+
1895
+ answers
1896
+ end
1897
+
1898
+ # Returns plot object to print it on the CLI
1899
+ #
1900
+ # @param x [Array] Data to x axis (Time axis)
1901
+ # @param y [Array] Data to y axis
1902
+ # @param attr [String] Parameter to y axis
1903
+ # @param title [String] Plot title
1904
+ #
1905
+ # @return Gnuplot plot object
1906
+ def OpenNebulaHelper.get_plot(x, y, attr, title)
1907
+ # Require gnuplot gem only here
1908
+ begin
1909
+ require 'gnuplot'
1910
+ rescue LoadError, Gem::LoadError
1911
+ STDERR.puts(
1912
+ 'Gnuplot gem is not installed, run `gem install gnuplot` '\
1913
+ 'to install it'
1914
+ )
1915
+ exit(-1)
1916
+ end
1917
+
1918
+ # Check if gnuplot is installed on the system
1919
+ unless system('gnuplot --version')
1920
+ STDERR.puts(
1921
+ 'Gnuplot is not installed, install it depending on your distro'
1922
+ )
1923
+ exit(-1)
1924
+ end
1925
+
1926
+ Gnuplot.open do |gp|
1927
+ Gnuplot::Plot.new(gp) do |p|
1928
+ p.title title
1929
+
1930
+ p.xlabel 'Time'
1931
+ p.ylabel attr
1932
+
1933
+ p.xdata 'time'
1934
+ p.timefmt "'%H:%M'"
1935
+ p.format "x '%H:%M'"
1936
+
1937
+ p.style 'data lines'
1938
+ p.terminal 'dumb'
1939
+
1940
+ p.data << Gnuplot::DataSet.new([x, y]) do |ds|
1941
+ ds.with = 'linespoints'
1942
+ ds.linewidth = '3'
1943
+ ds.using = '1:2'
1944
+
1945
+ ds.notitle
1946
+ end
1947
+ end
1948
+ end
1949
+ end
1950
+
1699
1951
  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 #
@@ -63,15 +63,15 @@ class OneClusterHelper < OpenNebulaHelper::OneHelper
63
63
  end
64
64
 
65
65
  column :HOSTS, "Number of Hosts", :size=>5 do |d|
66
- @ext.element_size(d,"HOSTS")
66
+ @ext.element_size(d,"HOSTS") rescue 0
67
67
  end
68
68
 
69
69
  column :VNETS, "Number of Networks", :size=>5 do |d|
70
- @ext.element_size(d,"VNETS")
70
+ @ext.element_size(d,"VNETS") rescue 0
71
71
  end
72
72
 
73
73
  column :DATASTORES, "Number of Datastores", :size=>10 do |d|
74
- @ext.element_size(d,"DATASTORES")
74
+ @ext.element_size(d,"DATASTORES") rescue 0
75
75
  end
76
76
 
77
77
  default :ID, :NAME, :HOSTS, :VNETS, :DATASTORES
@@ -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,423 @@
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
+ # Configuration file
23
+ def self.conf_file
24
+ 'oneflow.yaml'
25
+ end
26
+
27
+ # Get client to make request
28
+ #
29
+ # @options [Hash] CLI options
30
+ def client(options)
31
+ Service::Client.new(
32
+ :username => options[:username],
33
+ :password => options[:password],
34
+ :url => options[:server],
35
+ :user_agent => USER_AGENT
36
+ )
37
+ end
38
+
39
+ # Get service pool table
40
+ def format_service_pool
41
+ config_file = self.class.table_conf
42
+
43
+ CLIHelper::ShowTable.new(config_file, self) do
44
+ column :ID, 'ID', :size => 10 do |d|
45
+ d['ID']
46
+ end
47
+
48
+ column :USER, 'Username', :left, :size => 15 do |d|
49
+ d['UNAME']
50
+ end
51
+
52
+ column :GROUP, 'Group', :left, :size => 15 do |d|
53
+ d['GNAME']
54
+ end
55
+
56
+ column :NAME, 'Name', :expand => true, :left => true do |d|
57
+ d['NAME']
58
+ end
59
+
60
+ column :STAT, 'State', :size => 11, :left => true do |d|
61
+ Service.state_str(d['TEMPLATE']['BODY']['state'])
62
+ end
63
+
64
+ default :ID, :USER, :GROUP, :NAME, :STAT
65
+ end
66
+ end
67
+
68
+ # List service pool
69
+ #
70
+ # @param client [Service::Client] Petition client
71
+ # @param options [Hash] CLI options
72
+ def list_service_pool(client, options)
73
+ response = client.get(RESOURCE_PATH)
74
+
75
+ if CloudClient.is_error?(response)
76
+ [response.code.to_i, response.to_s]
77
+ else
78
+ array_list = JSON.parse(response.body)
79
+ array_list = array_list['DOCUMENT_POOL']['DOCUMENT']
80
+
81
+ array_list = [] if array_list.nil?
82
+
83
+ unless options.key? :done
84
+ # remove from list flows in DONE state
85
+ array_list.reject! do |value|
86
+ value['TEMPLATE']['BODY']['state'] == 5
87
+ end
88
+ end
89
+
90
+ if options[:json]
91
+ if array_list.empty?
92
+ 0
93
+ else
94
+ [0, JSON.pretty_generate(array_list)]
95
+ end
96
+ else
97
+ format_service_pool.show(array_list)
98
+
99
+ 0
100
+ end
101
+ end
102
+ end
103
+
104
+ # List service pool continiously
105
+ #
106
+ # @param client [Service::Client] Petition client
107
+ # @param options [Hash] CLI options
108
+ def top_service_pool(client, options)
109
+ # TODO: make default delay configurable
110
+ options[:delay] ? delay = options[:delay] : delay = 4
111
+
112
+ begin
113
+ loop do
114
+ CLIHelper.scr_cls
115
+ CLIHelper.scr_move(0, 0)
116
+
117
+ list_service_pool(client, options)
118
+
119
+ sleep delay
120
+ end
121
+ rescue StandardError => e
122
+ STDERR.puts e.message
123
+ exit(-1)
124
+ end
125
+
126
+ 0
127
+ end
128
+
129
+ # Show service detailed information
130
+ #
131
+ # @param client [Service::Client] Petition client
132
+ # @param service [Integer] Service ID
133
+ # @param options [Hash] CLI options
134
+ def format_resource(client, service, options)
135
+ response = client.get("#{RESOURCE_PATH}/#{service}")
136
+
137
+ if CloudClient.is_error?(response)
138
+ [response.code.to_i, response.to_s]
139
+ else
140
+ if options[:json]
141
+ [0, response.body]
142
+ else
143
+ str_h1 = '%-80s'
144
+ document = JSON.parse(response.body)['DOCUMENT']
145
+ template = document['TEMPLATE']['BODY']
146
+
147
+ CLIHelper.print_header(
148
+ str_h1 % "SERVICE #{document['ID']} INFORMATION"
149
+ )
150
+
151
+ print_service_info(document)
152
+
153
+ print_roles_info(template['roles'])
154
+
155
+ return 0 unless template['log']
156
+
157
+ CLIHelper.print_header(str_h1 % 'LOG MESSAGES', false)
158
+
159
+ template['log'].each do |log|
160
+ t = Time.at(log['timestamp']).strftime('%m/%d/%y %H:%M')
161
+ puts "#{t} [#{log['severity']}] #{log['message']}"
162
+ end
163
+
164
+ 0
165
+ end
166
+ end
167
+ end
168
+
169
+ # Get policy adjust information in str format
170
+ #
171
+ # @param policy [Hash] Policy information
172
+ def self.adjust_str(policy)
173
+ policy['adjust'].to_i >= 0 ? sign = '+' : sign = '-'
174
+ adjust = policy['adjust'].to_i.abs
175
+
176
+ case policy['type']
177
+ when 'CARDINALITY'
178
+ "= #{adjust}"
179
+ when 'PERCENTAGE_CHANGE'
180
+ st = "#{sign} #{adjust} %"
181
+
182
+ if policy['min_adjust_step']
183
+ st << " (#{policy['min_adjust_step']})"
184
+ end
185
+
186
+ st
187
+ else
188
+ "#{sign} #{adjust}"
189
+ end
190
+ end
191
+
192
+ private
193
+
194
+ # Get nodes pool table
195
+ def format_node_pool
196
+ # TODO: config file
197
+ CLIHelper::ShowTable.new(nil, self) do
198
+ column :VM_ID,
199
+ 'ONE identifier for Virtual Machine',
200
+ :size => 6 do |d|
201
+ st = ''
202
+
203
+ if d['scale_up']
204
+ st << '\u2191 '
205
+ elsif d['disposed']
206
+ st << '\u2193 '
207
+ end
208
+
209
+ if d['vm_info'].nil?
210
+ st << d['deploy_id'].to_s
211
+ else
212
+ st << d['vm_info']['VM']['ID']
213
+ end
214
+
215
+ st
216
+ end
217
+
218
+ column :NAME,
219
+ 'Name of the Virtual Machine',
220
+ :left,
221
+ :size => 24 do |d|
222
+ if !d['vm_info'].nil?
223
+ if d['vm_info']['VM']['RESCHED'] == '1'
224
+ "*#{d['NAME']}"
225
+ else
226
+ d['vm_info']['VM']['NAME']
227
+ end
228
+ else
229
+ ''
230
+ end
231
+ end
232
+
233
+ column :USER,
234
+ 'Username of the Virtual Machine owner',
235
+ :left,
236
+ :size => 15 do |d|
237
+ if !d['vm_info'].nil?
238
+ d['vm_info']['VM']['UNAME']
239
+ else
240
+ ''
241
+ end
242
+ end
243
+
244
+ column :GROUP,
245
+ 'Group of the Virtual Machine',
246
+ :left,
247
+ :size => 15 do |d|
248
+ if !d['vm_info'].nil?
249
+ d['vm_info']['VM']['GNAME']
250
+ else
251
+ ''
252
+ end
253
+ end
254
+
255
+ default :VM_ID, :NAME, :USER, :GROUP
256
+ end
257
+ end
258
+
259
+ # Print service information
260
+ #
261
+ # @param document [Hash] Service document information
262
+ def print_service_info(document)
263
+ str = '%-20s: %-20s'
264
+ str_h1 = '%-80s'
265
+ template = document['TEMPLATE']['BODY']
266
+
267
+ puts Kernel.format(str, 'ID', document['ID'])
268
+ puts Kernel.format(str, 'NAME', document['NAME'])
269
+ puts Kernel.format(str, 'USER', document['UNAME'])
270
+ puts Kernel.format(str, 'GROUP', document['GNAME'])
271
+
272
+ puts Kernel.format(str, 'STRATEGY', template['deployment'])
273
+ puts Kernel.format(str,
274
+ 'SERVICE STATE',
275
+ Service.state_str(template['state']))
276
+
277
+ if template['shutdown_action']
278
+ puts Kernel.format(str, 'SHUTDOWN', template['shutdown_action'])
279
+ end
280
+
281
+ puts
282
+
283
+ CLIHelper.print_header(str_h1 % 'PERMISSIONS', false)
284
+
285
+ %w[OWNER GROUP OTHER].each do |e|
286
+ mask = '---'
287
+ permissions_hash = document['PERMISSIONS']
288
+ mask[0] = 'u' if permissions_hash["#{e}_U"] == '1'
289
+ mask[1] = 'm' if permissions_hash["#{e}_M"] == '1'
290
+ mask[2] = 'a' if permissions_hash["#{e}_A"] == '1'
291
+
292
+ puts Kernel.format(str, e, mask)
293
+ end
294
+
295
+ puts
296
+ end
297
+
298
+ # Print service roles information
299
+ #
300
+ # @param roles [Array] Service roles information
301
+ def print_roles_info(roles)
302
+ str = '%-20s: %-20s'
303
+
304
+ roles.each do |role|
305
+ CLIHelper.print_header("ROLE #{role['name']}", false)
306
+
307
+ puts Kernel.format(str,
308
+ 'ROLE STATE',
309
+ Role.state_str(role['state']))
310
+
311
+ if role['parents']
312
+ puts Kernel.format(str,
313
+ 'PARENTS',
314
+ role['parents'].join(', '))
315
+ end
316
+
317
+ puts Kernel.format(str, 'VM TEMPLATE', role['vm_template'])
318
+ puts Kernel.format(str, 'CARDINALITY', role['cardinality'])
319
+
320
+ if role['min_vms']
321
+ puts Kernel.format(str, 'MIN VMS', role['min_vms'])
322
+ end
323
+
324
+ if role['max_vms']
325
+ puts Kernel.format(str, 'MAX VMS', role['max_vms'])
326
+ end
327
+
328
+ if role['coolddown']
329
+ puts Kernel.format(str, 'COOLDOWN', "#{role['cooldown']}s")
330
+ end
331
+
332
+ if role['shutdown_action']
333
+ puts Kernel.format(str, 'SHUTDOWN', role['shutdown_action'])
334
+ end
335
+
336
+ if role['elasticity_policies'] &&
337
+ !role['elasticity_policies'].empty?
338
+ print_elasticity_info(role)
339
+ end
340
+
341
+ if role['scheduled_policies'] &&
342
+ !role['scheduled_policies'].empty?
343
+ print_scheduled_info(role)
344
+ end
345
+
346
+ puts
347
+ CLIHelper.print_header('NODES INFORMATION', false)
348
+
349
+ format_node_pool.show(role['nodes'])
350
+ puts
351
+ end
352
+ end
353
+
354
+ # Print role elasticity info
355
+ #
356
+ # @param role [OpenNebula::Role] Role information
357
+ def print_elasticity_info(role)
358
+ puts
359
+ CLIHelper.print_header('ROLE ELASTICITY', false)
360
+
361
+ CLIHelper::ShowTable.new(nil, self) do
362
+ column :ADJUST, '', :left, :size => 12 do |d|
363
+ OneFlowHelper.adjust_str(d)
364
+ end
365
+
366
+ column :EXPRESSION, '', :left, :size => 48 do |d|
367
+ if !d['expression_evaluated'].nil?
368
+ d['expression_evaluated']
369
+ else
370
+ d['expression']
371
+ end
372
+ end
373
+
374
+ column :EVALS, '', :right, :size => 5 do |d|
375
+ if d['period_number']
376
+ "#{d['true_evals'].to_i}/"\
377
+ "#{d['period_number']}"
378
+ else
379
+ '-'
380
+ end
381
+ end
382
+
383
+ column :PERIOD, '', :size => 6 do |d|
384
+ d['period'] ? "#{d['period']}s" : '-'
385
+ end
386
+
387
+ column :COOL, '', :size => 5 do |d|
388
+ d['cooldown'] ? "#{d['cooldown']}s" : '-'
389
+ end
390
+
391
+ default :ADJUST, :EXPRESSION, :EVALS, :PERIOD, :COOL
392
+ end.show([role['elasticity_policies']].flatten, {})
393
+ end
394
+
395
+ # Print role schedule info
396
+ #
397
+ # @param role [OpenNebula::Role] Role information
398
+ def print_scheduled_info(role)
399
+ puts
400
+ CLIHelper.print_header('ROLE ELASTICITY SCHEDULE', false)
401
+
402
+ CLIHelper::ShowTable.new(nil, self) do
403
+ column :ADJUST, '', :left, :size => 12 do |d|
404
+ OneFlowHelper.adjust_str(d)
405
+ end
406
+
407
+ column :TIME, '', :left, :size => 67 do |d|
408
+ if d['start_time']
409
+ if !d['start_time'].match(/^\d+$/)
410
+ Time.parse(d['start_time']).to_s
411
+ else
412
+ d['start_time']
413
+ end
414
+ else
415
+ d['recurrence']
416
+ end
417
+ end
418
+
419
+ default :ADJUST, :TIME
420
+ end.show([role['scheduled_policies']].flatten, {})
421
+ end
422
+
423
+ end