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.
- checksums.yaml +4 -4
- data/bin/oneacct +4 -2
- data/bin/oneacl +4 -2
- data/bin/onecluster +4 -2
- data/bin/onedatastore +4 -2
- data/bin/oneflow +151 -552
- data/bin/oneflow-template +173 -293
- data/bin/onegroup +4 -2
- data/bin/onehook +4 -2
- data/bin/onehost +78 -10
- data/bin/oneimage +4 -2
- data/bin/onemarket +4 -2
- data/bin/onemarketapp +17 -4
- data/bin/onesecgroup +4 -2
- data/bin/oneshowback +4 -2
- data/bin/onetemplate +4 -2
- data/bin/oneuser +4 -2
- data/bin/onevcenter +4 -2
- data/bin/onevdc +4 -2
- data/bin/onevm +170 -17
- data/bin/onevmgroup +4 -2
- data/bin/onevnet +16 -41
- data/bin/onevntemplate +4 -2
- data/bin/onevrouter +4 -2
- data/bin/onezone +7 -2
- data/lib/cli_helper.rb +54 -30
- data/lib/command_parser.rb +53 -19
- data/lib/one_helper.rb +258 -6
- data/lib/one_helper/oneacct_helper.rb +1 -1
- data/lib/one_helper/oneacl_helper.rb +1 -1
- data/lib/one_helper/onecluster_helper.rb +4 -4
- data/lib/one_helper/onedatastore_helper.rb +1 -1
- data/lib/one_helper/oneflow_helper.rb +423 -0
- data/lib/one_helper/oneflowtemplate_helper.rb +312 -0
- data/lib/one_helper/onegroup_helper.rb +1 -1
- data/lib/one_helper/onehook_helper.rb +1 -1
- data/lib/one_helper/onehost_helper.rb +148 -68
- data/lib/one_helper/oneimage_helper.rb +2 -2
- data/lib/one_helper/onemarket_helper.rb +1 -1
- data/lib/one_helper/onemarketapp_helper.rb +1 -1
- data/lib/one_helper/oneprovision_helper.rb +104 -60
- data/lib/one_helper/onequota_helper.rb +1 -1
- data/lib/one_helper/onesecgroup_helper.rb +1 -1
- data/lib/one_helper/onetemplate_helper.rb +9 -180
- data/lib/one_helper/oneuser_helper.rb +1 -1
- data/lib/one_helper/onevcenter_helper.rb +5 -4
- data/lib/one_helper/onevdc_helper.rb +1 -1
- data/lib/one_helper/onevm_helper.rb +117 -21
- data/lib/one_helper/onevmgroup_helper.rb +1 -1
- data/lib/one_helper/onevnet_helper.rb +66 -2
- data/lib/one_helper/onevntemplate_helper.rb +1 -1
- data/lib/one_helper/onevrouter_helper.rb +1 -1
- data/lib/one_helper/onezone_helper.rb +3 -1
- metadata +8 -6
data/lib/one_helper.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -------------------------------------------------------------------------- #
|
2
|
-
# Copyright 2002-
|
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-
|
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-
|
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-
|
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-
|
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-
|
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
|