opennebula-cli 5.10.5 → 5.12.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 (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