opennebula-cli 5.10.4 → 5.12.0
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 +2 -1
- data/bin/oneacl +2 -1
- data/bin/onecluster +2 -1
- data/bin/onedatastore +2 -1
- data/bin/oneflow +149 -551
- data/bin/oneflow-template +171 -292
- data/bin/onegroup +2 -1
- data/bin/onehook +2 -1
- data/bin/onehost +76 -9
- data/bin/oneimage +2 -1
- data/bin/onemarket +2 -1
- data/bin/onemarketapp +15 -3
- data/bin/onesecgroup +2 -1
- data/bin/oneshowback +2 -1
- data/bin/onetemplate +2 -1
- data/bin/oneuser +2 -1
- data/bin/onevcenter +2 -1
- data/bin/onevdc +2 -1
- data/bin/onevm +88 -16
- data/bin/onevmgroup +2 -1
- data/bin/onevnet +11 -3
- data/bin/onevntemplate +2 -1
- data/bin/onevrouter +2 -1
- data/bin/onezone +5 -1
- data/lib/cli_helper.rb +54 -30
- data/lib/command_parser.rb +33 -14
- 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 +419 -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 +2 -1
- data/lib/one_helper/onevdc_helper.rb +1 -1
- data/lib/one_helper/onevm_helper.rb +11 -6
- data/lib/one_helper/onevmgroup_helper.rb +1 -1
- data/lib/one_helper/onevnet_helper.rb +1 -1
- 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
@@ -0,0 +1,312 @@
|
|
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 Template command helper
|
20
|
+
class OneFlowTemplateHelper < OpenNebulaHelper::OneHelper
|
21
|
+
|
22
|
+
# Configuration file
|
23
|
+
def self.conf_file
|
24
|
+
'oneflowtemplate.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 template pool
|
40
|
+
def format_service_template_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', :left, :expand => true do |d|
|
57
|
+
d['NAME']
|
58
|
+
end
|
59
|
+
|
60
|
+
default :ID, :USER, :GROUP, :NAME
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# List service template pool
|
65
|
+
#
|
66
|
+
# @param client [Service::Client] Petition client
|
67
|
+
# @param options [Hash] CLI options
|
68
|
+
def list_service_template_pool(client, options)
|
69
|
+
response = client.get(RESOURCE_PATH)
|
70
|
+
|
71
|
+
if CloudClient.is_error?(response)
|
72
|
+
[response.code.to_i, response.to_s]
|
73
|
+
else
|
74
|
+
if options[:json]
|
75
|
+
[0, response.body]
|
76
|
+
else
|
77
|
+
documents = JSON.parse(response.body)['DOCUMENT_POOL']
|
78
|
+
format_service_template_pool.show(documents['DOCUMENT'])
|
79
|
+
|
80
|
+
0
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# List service template pool continiously
|
86
|
+
#
|
87
|
+
# @param client [Service::Client] Petition client
|
88
|
+
# @param options [Hash] CLI options
|
89
|
+
def top_service_template_pool(client, options)
|
90
|
+
# TODO: make default delay configurable
|
91
|
+
options[:delay] ? delay = options[:delay] : delay = 4
|
92
|
+
|
93
|
+
begin
|
94
|
+
loop do
|
95
|
+
CLIHelper.scr_cls
|
96
|
+
CLIHelper.scr_move(0, 0)
|
97
|
+
|
98
|
+
list_service_template_pool(client, options)
|
99
|
+
|
100
|
+
sleep delay
|
101
|
+
end
|
102
|
+
rescue StandardError => e
|
103
|
+
STDERR.puts e.message
|
104
|
+
exit(-1)
|
105
|
+
end
|
106
|
+
|
107
|
+
0
|
108
|
+
end
|
109
|
+
|
110
|
+
# Show service template detailed information
|
111
|
+
#
|
112
|
+
# @param client [Service::Client] Petition client
|
113
|
+
# @param service_template [Integer] Service template ID
|
114
|
+
# @param options [Hash] CLI options
|
115
|
+
def format_resource(client, service_template, options)
|
116
|
+
response = client.get("#{RESOURCE_PATH}/#{service_template}")
|
117
|
+
|
118
|
+
if CloudClient.is_error?(response)
|
119
|
+
[response.code.to_i, response.to_s]
|
120
|
+
else
|
121
|
+
if options[:json]
|
122
|
+
[0, response.body]
|
123
|
+
else
|
124
|
+
str = '%-20s: %-20s'
|
125
|
+
str_h1 = '%-80s'
|
126
|
+
|
127
|
+
document = JSON.parse(response.body)['DOCUMENT']
|
128
|
+
template = document['TEMPLATE']['BODY']
|
129
|
+
|
130
|
+
CLIHelper.print_header(
|
131
|
+
str_h1 % "SERVICE TEMPLATE #{document['ID']} INFORMATION"
|
132
|
+
)
|
133
|
+
|
134
|
+
puts Kernel.format str, 'ID', document['ID']
|
135
|
+
puts Kernel.format str, 'NAME', document['NAME']
|
136
|
+
puts Kernel.format str, 'USER', document['UNAME']
|
137
|
+
puts Kernel.format str, 'GROUP', document['GNAME']
|
138
|
+
|
139
|
+
puts
|
140
|
+
|
141
|
+
CLIHelper.print_header(str_h1 % 'PERMISSIONS', false)
|
142
|
+
|
143
|
+
%w[OWNER GROUP OTHER].each do |e|
|
144
|
+
mask = '---'
|
145
|
+
permissions_hash = document['PERMISSIONS']
|
146
|
+
mask[0] = 'u' if permissions_hash["#{e}_U"] == '1'
|
147
|
+
mask[1] = 'm' if permissions_hash["#{e}_M"] == '1'
|
148
|
+
mask[2] = 'a' if permissions_hash["#{e}_A"] == '1'
|
149
|
+
|
150
|
+
puts Kernel.format str, e, mask
|
151
|
+
end
|
152
|
+
|
153
|
+
puts
|
154
|
+
|
155
|
+
CLIHelper.print_header(str_h1 % 'TEMPLATE CONTENTS', false)
|
156
|
+
puts JSON.pretty_generate(template)
|
157
|
+
|
158
|
+
0
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Get custom attributes values from user
|
164
|
+
#
|
165
|
+
# @param custom_attrs [Hash] Custom attributes from template
|
166
|
+
#
|
167
|
+
# @return [Hash] Custom attributes values
|
168
|
+
def custom_attrs(custom_attrs)
|
169
|
+
# rubocop:disable Layout/LineLength
|
170
|
+
return if custom_attrs.nil? || custom_attrs.empty?
|
171
|
+
|
172
|
+
ret = {}
|
173
|
+
ret['custom_attrs_values'] = OpenNebulaHelper.parse_user_inputs(custom_attrs)
|
174
|
+
|
175
|
+
# rubocop:enable Layout/LineLength
|
176
|
+
ret
|
177
|
+
end
|
178
|
+
|
179
|
+
def networks(vnets)
|
180
|
+
return unless vnets
|
181
|
+
|
182
|
+
ret = {}
|
183
|
+
ret['networks_values'] = parse_networks(vnets)
|
184
|
+
|
185
|
+
ret
|
186
|
+
end
|
187
|
+
|
188
|
+
def parse_networks(vnets, get_defaults = false)
|
189
|
+
unless get_defaults
|
190
|
+
puts 'There are some networks that require user input. ' \
|
191
|
+
'Use the string <<EDITOR>> to launch an editor ' \
|
192
|
+
'(e.g. for multi-line inputs)'
|
193
|
+
end
|
194
|
+
|
195
|
+
answers = []
|
196
|
+
|
197
|
+
vnets.each do |key, val|
|
198
|
+
input_cfg = val.split('|', -1)
|
199
|
+
|
200
|
+
if input_cfg.length != 5
|
201
|
+
STDERR.puts 'Malformed user input. It should have 5'\
|
202
|
+
"parts separated by '|':"
|
203
|
+
STDERR.puts " #{key}: #{val}"
|
204
|
+
exit(-1)
|
205
|
+
end
|
206
|
+
|
207
|
+
mandatory, _type, description, _params, initial = input_cfg
|
208
|
+
|
209
|
+
vnet = {}
|
210
|
+
|
211
|
+
if initial && !initial.empty?
|
212
|
+
type, resource_id, extra = initial.split(':', -1)
|
213
|
+
end
|
214
|
+
|
215
|
+
if (type.nil? || resource_id.nil?) &&
|
216
|
+
(initial && !initial.empty?)
|
217
|
+
STDERR.puts 'Wrong type for user input default value:'
|
218
|
+
STDERR.puts " #{key}: #{val}"
|
219
|
+
exit(-1)
|
220
|
+
end
|
221
|
+
|
222
|
+
vnet[key] = {}
|
223
|
+
|
224
|
+
if get_defaults
|
225
|
+
vnet[key][type] = resource_id
|
226
|
+
vnet[key]['extra'] = extra
|
227
|
+
|
228
|
+
answers << vnet unless mandatory == 'M'
|
229
|
+
next
|
230
|
+
end
|
231
|
+
|
232
|
+
puts " * (#{key}) #{description}"
|
233
|
+
|
234
|
+
#######################################
|
235
|
+
# Asks for type
|
236
|
+
#######################################
|
237
|
+
|
238
|
+
header = ' '
|
239
|
+
header += 'TYPE Existing(1), Create(2), Reserve(3). '
|
240
|
+
|
241
|
+
if !type.nil? && type != ''
|
242
|
+
header += 'Press enter for default. '
|
243
|
+
end
|
244
|
+
|
245
|
+
print header
|
246
|
+
|
247
|
+
answer = STDIN.readline.chop
|
248
|
+
|
249
|
+
type_a = type
|
250
|
+
|
251
|
+
case answer.to_i
|
252
|
+
when 1
|
253
|
+
type_a = 'id'
|
254
|
+
when 2
|
255
|
+
type_a = 'template_id'
|
256
|
+
when 3
|
257
|
+
type_a = 'reserve_from'
|
258
|
+
end
|
259
|
+
|
260
|
+
#######################################
|
261
|
+
# Asks for resource id
|
262
|
+
#######################################
|
263
|
+
|
264
|
+
header = ' '
|
265
|
+
if type_a == 'template_id'
|
266
|
+
header += 'VN Template ID. '
|
267
|
+
else
|
268
|
+
header += 'VN ID. '
|
269
|
+
end
|
270
|
+
|
271
|
+
if !resource_id.nil? && resource_id != ''
|
272
|
+
header += "Press enter for default (#{resource_id}). "
|
273
|
+
end
|
274
|
+
|
275
|
+
print header
|
276
|
+
|
277
|
+
resource_id_a = STDIN.readline.chop
|
278
|
+
|
279
|
+
resource_id_a = resource_id if resource_id_a.empty?
|
280
|
+
|
281
|
+
#######################################
|
282
|
+
# Asks for extra
|
283
|
+
#######################################
|
284
|
+
|
285
|
+
if type_a != 'id'
|
286
|
+
header = ' '
|
287
|
+
header += 'EXTRA (Type EMPTY for leaving empty). '
|
288
|
+
|
289
|
+
if !extra.nil? && extra != ''
|
290
|
+
header += " Press enter for default (#{extra}). "
|
291
|
+
end
|
292
|
+
|
293
|
+
print header
|
294
|
+
|
295
|
+
extra_a = STDIN.readline.chop
|
296
|
+
|
297
|
+
if extra_a.empty?
|
298
|
+
vnet[key]['extra'] = extra
|
299
|
+
else
|
300
|
+
vnet[key]['extra'] = extra_a
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
vnet[key][type_a] = resource_id_a
|
305
|
+
|
306
|
+
answers << vnet
|
307
|
+
end
|
308
|
+
|
309
|
+
answers
|
310
|
+
end
|
311
|
+
|
312
|
+
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 #
|
@@ -17,6 +17,7 @@
|
|
17
17
|
require 'one_helper'
|
18
18
|
require 'one_helper/onevm_helper'
|
19
19
|
require 'rubygems'
|
20
|
+
require 'time'
|
20
21
|
|
21
22
|
# implements onehost command
|
22
23
|
class OneHostHelper < OpenNebulaHelper::OneHelper
|
@@ -48,25 +49,25 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
48
49
|
:az => {
|
49
50
|
:help => <<-EOT.unindent
|
50
51
|
#-----------------------------------------------------------------------
|
51
|
-
#
|
52
|
+
# Mandatory AZURE ATTRIBUTTES:
|
52
53
|
#
|
53
|
-
#
|
54
|
-
#
|
54
|
+
# AZ_SUB = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
55
|
+
# AZ_CLIENT = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
56
|
+
# AZ_SECRET = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
57
|
+
# AZ_TENANT = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
58
|
+
# AZ_REGION = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
55
59
|
#
|
56
|
-
#
|
60
|
+
# CAPACITY=[
|
61
|
+
# STANDARD_B1LS =<number of machines Standard_B1ls>,
|
62
|
+
# STANDARD_A1_V2=<number of machines Standard_A1_v2>
|
63
|
+
# ]
|
57
64
|
#
|
58
|
-
#
|
59
|
-
# Small = <number of small machines>,
|
60
|
-
# Medium = <number of medium machines>,
|
61
|
-
# Large = <number of large machines
|
62
|
-
# ]
|
63
|
-
#
|
64
|
-
# You can set any machine type supported by azure classic
|
65
|
-
# See your az_driver.conf for more information
|
65
|
+
# Optional AZURE ATTRIBUTES:
|
66
66
|
#
|
67
|
-
#
|
67
|
+
# AZ_RGROUP = ""
|
68
68
|
#
|
69
|
-
#
|
69
|
+
# You can set any machine type supported by azure
|
70
|
+
# See your az_driver.conf for more information
|
70
71
|
#
|
71
72
|
#-----------------------------------------------------------------------
|
72
73
|
EOT
|
@@ -75,6 +76,15 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
75
76
|
|
76
77
|
VERSION_XPATH = "#{TEMPLATE_XPATH}/VERSION"
|
77
78
|
|
79
|
+
MONITORING = {
|
80
|
+
'FREE_CPU' => 'CAPACITY',
|
81
|
+
'FREE_MEMORY' => 'CAPACITY',
|
82
|
+
'USED_CPU' => 'CAPACITY',
|
83
|
+
'USED_MEMORY' => 'CAPACITY',
|
84
|
+
'NETRX' => 'SYSTEM',
|
85
|
+
'NETTX' => 'SYSTEM'
|
86
|
+
}
|
87
|
+
|
78
88
|
def self.rname
|
79
89
|
'HOST'
|
80
90
|
end
|
@@ -359,14 +369,15 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
359
369
|
|
360
370
|
print_update_info(total - size, total, host['NAME'])
|
361
371
|
|
362
|
-
if options[:
|
363
|
-
sync_cmd = "rsync -Laz --delete #{REMOTES_LOCATION}" \
|
364
|
-
" #{host['NAME']}:#{remote_dir}"
|
365
|
-
else
|
372
|
+
if options[:ssh]
|
366
373
|
sync_cmd = "ssh #{host['NAME']}" \
|
374
|
+
" rm -rf '#{remote_dir}' 2>/dev/null;" \
|
367
375
|
" mkdir -p '#{remote_dir}' 2>/dev/null &&" \
|
368
376
|
" scp -rp #{REMOTES_LOCATION}/*" \
|
369
377
|
" #{host['NAME']}:#{remote_dir} 2> /dev/null"
|
378
|
+
else
|
379
|
+
sync_cmd = "rsync -Laz --delete #{REMOTES_LOCATION}/" \
|
380
|
+
" #{host['NAME']}:#{remote_dir}/"
|
370
381
|
end
|
371
382
|
|
372
383
|
retries = 3
|
@@ -424,8 +435,7 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
424
435
|
rc = pool.info
|
425
436
|
return -1, rc.message if OpenNebula.is_error?(rc)
|
426
437
|
|
427
|
-
|
428
|
-
queue = []
|
438
|
+
host_errors = []
|
429
439
|
|
430
440
|
pool.each do |host|
|
431
441
|
if host_ids
|
@@ -434,7 +444,6 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
434
444
|
next if host['CLUSTER_ID'].to_i != cluster_id
|
435
445
|
end
|
436
446
|
|
437
|
-
vm_mad = host['VM_MAD'].downcase
|
438
447
|
state = host['STATE']
|
439
448
|
|
440
449
|
# Skip this host from remote syncing if it's a PUBLIC_CLOUD host
|
@@ -443,60 +452,104 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
443
452
|
# Skip this host from remote syncing if it's OFFLINE
|
444
453
|
next if Host::HOST_STATES[state.to_i] == 'OFFLINE'
|
445
454
|
|
446
|
-
|
447
|
-
next if vm_mad == 'vcenter'
|
455
|
+
rc = host.forceupdate
|
448
456
|
|
449
|
-
|
457
|
+
host_errors << host['NAME'] if OpenNebula.is_error?(rc)
|
450
458
|
end
|
451
459
|
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
460
|
+
if host_errors.empty?
|
461
|
+
puts 'All hosts updated successfully.'
|
462
|
+
0
|
463
|
+
else
|
464
|
+
STDERR.puts 'Failed to update the following hosts:'
|
465
|
+
host_errors.each {|h| STDERR.puts "* #{h}" }
|
466
|
+
-1
|
467
|
+
end
|
468
|
+
end
|
457
469
|
|
458
|
-
|
459
|
-
|
460
|
-
|
470
|
+
def monitoring(host, attr, options)
|
471
|
+
unit = options[:unit] || 'G'
|
472
|
+
start_d = options[:start]
|
473
|
+
end_d = options[:end]
|
474
|
+
n_elems = options[:n_elems] || 8
|
475
|
+
|
476
|
+
# Different available size units
|
477
|
+
units = %w[K M G T]
|
478
|
+
|
479
|
+
# Attrs that need units conversion
|
480
|
+
attrs = %w[FREE_MEMORY USED_MEMORY]
|
481
|
+
|
482
|
+
if unit && !units.include?(unit)
|
483
|
+
STDERR.puts "Invalid unit `#{unit}`"
|
484
|
+
exit(-1)
|
461
485
|
end
|
462
486
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
host = nil
|
467
|
-
size = 0
|
487
|
+
attr = attr.upcase
|
488
|
+
start_d = Time.parse(start_d) if start_d
|
489
|
+
end_d = Time.parse(end_d) if end_d
|
468
490
|
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
491
|
+
# Get monitoring data from user path
|
492
|
+
#
|
493
|
+
# 0 -> timestamp
|
494
|
+
# 1 -> data retrieved
|
495
|
+
monitoring_data = host.monitoring(["#{MONITORING[attr]}/#{attr}"])
|
496
|
+
monitoring_data = monitoring_data["#{MONITORING[attr]}/#{attr}"]
|
473
497
|
|
474
|
-
|
498
|
+
if monitoring_data.empty?
|
499
|
+
STDERR.puts 'No monitoring data found'
|
500
|
+
return
|
501
|
+
end
|
475
502
|
|
476
|
-
|
477
|
-
|
503
|
+
# Get data max and min date
|
504
|
+
start_d ||= Time.at(monitoring_data.min {|v| v[0].to_i }[0].to_i)
|
505
|
+
end_d ||= Time.at(monitoring_data.max {|v| v[0].to_i }[0].to_i)
|
478
506
|
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
507
|
+
# Filter data betwen dates
|
508
|
+
monitoring_data.reject! do |v|
|
509
|
+
v[0].to_i < start_d.to_i || v[0].to_i > end_d.to_i
|
510
|
+
end
|
511
|
+
|
512
|
+
if monitoring_data.empty?
|
513
|
+
STDERR.puts "No monitoring data found between #{start_d} " \
|
514
|
+
"and #{end_d}"
|
515
|
+
return
|
516
|
+
end
|
517
|
+
|
518
|
+
start_d = start_d.strftime('%d/%m/%Y %H:%M')
|
519
|
+
end_d = end_d.strftime('%d/%m/%Y %H:%M')
|
520
|
+
|
521
|
+
# Parse dcollected data
|
522
|
+
x = monitoring_data.collect {|v| Time.at(v[0].to_i).strftime('%H:%M') }
|
523
|
+
y = monitoring_data.collect do |v|
|
524
|
+
if attrs.include?(attr)
|
525
|
+
# GB is the default unit
|
526
|
+
v = OpenNebulaHelper.bytes_to_unit(v[1].to_i, unit).round(2)
|
527
|
+
"#{v} #{unit}B"
|
528
|
+
else
|
529
|
+
v[1]
|
487
530
|
end
|
488
531
|
end
|
489
532
|
|
490
|
-
|
491
|
-
|
533
|
+
title = ''
|
534
|
+
title << "Host #{host.id} #{attr} "
|
535
|
+
title << "in #{unit}B " if unit && attrs.include?(attr)
|
536
|
+
title << "from #{start_d} to #{end_d}"
|
492
537
|
|
493
|
-
|
494
|
-
|
495
|
-
|
538
|
+
x = x.last(n_elems)
|
539
|
+
y = y.last(n_elems)
|
540
|
+
|
541
|
+
if options[:table]
|
542
|
+
print_monitoring_table(x, y, title)
|
543
|
+
elsif options[:csv]
|
544
|
+
csv = ''
|
545
|
+
|
546
|
+
csv << "TIME#{options[:csv]}VALUE\n"
|
547
|
+
|
548
|
+
x.zip(y) {|x_v, y_v| csv << "#{x_v}#{options[:csv]}#{y_v}\n" }
|
549
|
+
|
550
|
+
puts csv
|
496
551
|
else
|
497
|
-
|
498
|
-
host_errors.each {|h| STDERR.puts "* #{h}" }
|
499
|
-
-1
|
552
|
+
puts OpenNebulaHelper.get_plot(x, y, attr, title)
|
500
553
|
end
|
501
554
|
end
|
502
555
|
|
@@ -565,7 +618,7 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
565
618
|
puts format(str, 'IM_MAD', host['IM_MAD'])
|
566
619
|
puts format(str, 'VM_MAD', host['VM_MAD'])
|
567
620
|
puts format(str, 'LAST MONITORING TIME',
|
568
|
-
OpenNebulaHelper.time_to_str(host['
|
621
|
+
OpenNebulaHelper.time_to_str(host['MONITORING/TIMESTAMP']))
|
569
622
|
puts
|
570
623
|
|
571
624
|
CLIHelper.print_header(str_h1 % 'HOST SHARES', false)
|
@@ -579,8 +632,9 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
579
632
|
OpenNebulaHelper.unit_to_str(host['HOST_SHARE/MAX_MEM']
|
580
633
|
.to_i, {}))
|
581
634
|
puts format(str, ' USED (REAL)',
|
582
|
-
OpenNebulaHelper
|
583
|
-
|
635
|
+
OpenNebulaHelper
|
636
|
+
.unit_to_str(host['MONITORING/CAPACITY/USED_MEMORY']
|
637
|
+
.to_i, {}))
|
584
638
|
puts format(str, ' USED (ALLOCATED)',
|
585
639
|
OpenNebulaHelper.unit_to_str(host['HOST_SHARE/MEM_USAGE']
|
586
640
|
.to_i, {}))
|
@@ -588,7 +642,7 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
588
642
|
CLIHelper.print_header(str_h1 % 'CPU', false)
|
589
643
|
puts format(str, ' TOTAL', host['HOST_SHARE/TOTAL_CPU'])
|
590
644
|
puts format(str, ' TOTAL +/- RESERVED', host['HOST_SHARE/MAX_CPU'])
|
591
|
-
puts format(str, ' USED (REAL)', host['
|
645
|
+
puts format(str, ' USED (REAL)', host['MONITORING/CAPACITY/USED_CPU'])
|
592
646
|
puts format(str, ' USED (ALLOCATED)', host['HOST_SHARE/CPU_USAGE'])
|
593
647
|
puts
|
594
648
|
|
@@ -662,13 +716,13 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
662
716
|
.split("\n")
|
663
717
|
name = wild['VM_NAME']
|
664
718
|
import = wild_tmplt.select do |line|
|
665
|
-
line[
|
719
|
+
line[/DEPLOY_ID/]
|
666
720
|
end[0].split('=')[1].tr('"', ' ').strip
|
667
721
|
memory = wild_tmplt.select do |line|
|
668
|
-
line[
|
722
|
+
line[/MEMORY/]
|
669
723
|
end[0].split('=')[1].tr('"', ' ').strip
|
670
724
|
cpu = wild_tmplt.select do |line|
|
671
|
-
line[
|
725
|
+
line[/CPU/]
|
672
726
|
end[0].split('=')[1].tr('"', ' ').strip
|
673
727
|
else
|
674
728
|
name = wild['DEPLOY_ID']
|
@@ -918,4 +972,30 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
918
972
|
table.show(hugepages)
|
919
973
|
end
|
920
974
|
|
975
|
+
def print_monitoring_table(x, y, title)
|
976
|
+
puts
|
977
|
+
CLIHelper.print_header(title, true)
|
978
|
+
puts
|
979
|
+
|
980
|
+
table = CLIHelper::ShowTable.new(nil, self) do
|
981
|
+
column :TIME, 'Timestamp', :size => 8, :left => false do |d|
|
982
|
+
d['TIME']
|
983
|
+
end
|
984
|
+
|
985
|
+
column :VALUE, 'Value', :size => 8, :left => false do |d|
|
986
|
+
d['VALUE']
|
987
|
+
end
|
988
|
+
|
989
|
+
default :TIME, :VALUE
|
990
|
+
end
|
991
|
+
|
992
|
+
data = []
|
993
|
+
|
994
|
+
x.zip(y) do |x_v, y_v|
|
995
|
+
data << { 'TIME' => x_v, 'VALUE' => y_v }
|
996
|
+
end
|
997
|
+
|
998
|
+
table.show(data)
|
999
|
+
end
|
1000
|
+
|
921
1001
|
end
|