vpsadmin-client 2.3.2 → 2.5.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/CHANGELOG +5 -0
- data/lib/vpsadmin/cli.rb +1 -0
- data/lib/vpsadmin/cli/commands/ip_traffic_top.rb +333 -0
- data/lib/vpsadmin/client/version.rb +1 -1
- data/vpsadmin-client.gemspec +2 -1
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba8192c7d8fd4f47bb344a6edfa0b27a30d850f0
|
4
|
+
data.tar.gz: 0fec21ca7c50c3fba23e15a50c4ecf2618e04423
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 743be4bedeccfb27de7355fea993dc1ee381e20f80cfbaa5bb1cebd43ff79c612bee0f505a073d71dc80965c51ba8dc0cdfaec2e9ddb2f3d7e7eda3a501aab1b
|
7
|
+
data.tar.gz: 15ef4a6f1a62934f78c60d2a97c37c80e5332e268096c7186fe7aec19f89374eee396e0ceeb5bb2d93a14d807a54893349aea9226e1e12ffd10855b21d33d4a9
|
data/CHANGELOG
CHANGED
data/lib/vpsadmin/cli.rb
CHANGED
@@ -0,0 +1,333 @@
|
|
1
|
+
require 'curses'
|
2
|
+
|
3
|
+
module VpsAdmin::CLI::Commands
|
4
|
+
class IpTrafficTop < BackupDataset
|
5
|
+
include Curses
|
6
|
+
|
7
|
+
REFRESH_RATE = 10
|
8
|
+
FILTERS = %i(limit ip_address ip_version environment location network ip_range node vps)
|
9
|
+
|
10
|
+
cmd :ip_traffic, :top
|
11
|
+
args ''
|
12
|
+
desc 'Live IP traffic monitor'
|
13
|
+
|
14
|
+
def options(opts)
|
15
|
+
@opts = {
|
16
|
+
unit: :bits,
|
17
|
+
}
|
18
|
+
|
19
|
+
opts.on('--unit UNIT', %w(bytes bits), 'Select data unit (bytes or bits)') do |v|
|
20
|
+
@opts[:unit] = v.to_sym
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on('--limit LIMIT', Integer, 'Number of IP addresses to monitor') do |v|
|
24
|
+
@opts[:limit] = v
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on('--ip-address ADDR', 'ADDR or ID of IP addresses to monitor') do |v|
|
28
|
+
id = ip_address_id(v)
|
29
|
+
|
30
|
+
if id
|
31
|
+
@opts[:ip_address] = id
|
32
|
+
|
33
|
+
else
|
34
|
+
warn "IP address '#{v}' not found"
|
35
|
+
exit(1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on('--ip-version VER', [4, 6], 'Filter IP addresses by version') do |v|
|
40
|
+
@opts[:ip_version] = v
|
41
|
+
end
|
42
|
+
|
43
|
+
(FILTERS - %i(limit ip_address ip_version)).each do |f|
|
44
|
+
opts.on("--#{f.to_s.gsub(/_/, '-')} ID", Integer, "Filter IP addresses by #{f}") do |v|
|
45
|
+
@opts[f] = v
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def exec(args)
|
51
|
+
if @global_opts[:list_output]
|
52
|
+
exclude = %i(id ip_address user updated_at delta)
|
53
|
+
|
54
|
+
@api.ip_traffic_monitor.actions[:index].params.each_key do |name|
|
55
|
+
next if exclude.include?(name)
|
56
|
+
puts name
|
57
|
+
end
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
|
61
|
+
set_global_opts
|
62
|
+
init_screen
|
63
|
+
start_color
|
64
|
+
crmode
|
65
|
+
stdscr.keypad = true
|
66
|
+
curs_set(0) # hide cursor
|
67
|
+
use_default_colors
|
68
|
+
|
69
|
+
init_pair(1, COLOR_BLACK, COLOR_WHITE)
|
70
|
+
last = nil
|
71
|
+
|
72
|
+
loop do
|
73
|
+
now = Time.now
|
74
|
+
|
75
|
+
if @refresh || last.nil? || (now - last) >= REFRESH_RATE
|
76
|
+
@refresh = false
|
77
|
+
render(now, true)
|
78
|
+
last = Time.now
|
79
|
+
self.timeout = REFRESH_RATE * 1000
|
80
|
+
|
81
|
+
else
|
82
|
+
render(last, false)
|
83
|
+
self.timeout = (REFRESH_RATE - (now - last)) * 1000
|
84
|
+
end
|
85
|
+
|
86
|
+
case getch
|
87
|
+
when 'q'
|
88
|
+
break
|
89
|
+
|
90
|
+
when Key::LEFT
|
91
|
+
clear
|
92
|
+
sort_next(-1)
|
93
|
+
|
94
|
+
when Key::RIGHT
|
95
|
+
clear
|
96
|
+
sort_next(+1)
|
97
|
+
|
98
|
+
when Key::UP, Key::DOWN
|
99
|
+
clear
|
100
|
+
sort_inverse
|
101
|
+
|
102
|
+
when Key::RESIZE
|
103
|
+
clear
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
rescue Interrupt
|
108
|
+
ensure
|
109
|
+
close_screen
|
110
|
+
end
|
111
|
+
|
112
|
+
protected
|
113
|
+
def set_global_opts
|
114
|
+
if @global_opts[:output]
|
115
|
+
@params = @global_opts[:output].split(',').map(&:to_sym)
|
116
|
+
|
117
|
+
else
|
118
|
+
@params = %i(bytes_in bytes_out bytes)
|
119
|
+
end
|
120
|
+
|
121
|
+
if @global_opts[:sort]
|
122
|
+
v = @global_opts[:sort]
|
123
|
+
@sort_desc = v.start_with?('-')
|
124
|
+
@sort_param = (v.start_with?('-') ? v[1..-1] : v).to_sym
|
125
|
+
|
126
|
+
else
|
127
|
+
@sort_desc = true
|
128
|
+
@sort_param = :bytes
|
129
|
+
end
|
130
|
+
|
131
|
+
@columns = []
|
132
|
+
|
133
|
+
@params.each do |p|
|
134
|
+
title = p.to_s.split('_').map do |v|
|
135
|
+
if @opts[:unit] == :bits
|
136
|
+
v.to_s.gsub(/bytes/, 'bits').capitalize
|
137
|
+
|
138
|
+
else
|
139
|
+
v.capitalize
|
140
|
+
end
|
141
|
+
end.join('') + '/s'
|
142
|
+
|
143
|
+
size = title.size + 1
|
144
|
+
|
145
|
+
@columns << {
|
146
|
+
name: p,
|
147
|
+
title: title,
|
148
|
+
width: size < 8 ? 8 : size,
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def fetch
|
154
|
+
return @data if @data
|
155
|
+
|
156
|
+
limit = @opts[:limit] || lines - 6
|
157
|
+
|
158
|
+
params = {
|
159
|
+
limit: limit > 0 ? limit : 25,
|
160
|
+
order: "#{@sort_desc ? '-' : ''}#{@sort_param}",
|
161
|
+
meta: {includes: 'ip_address'}
|
162
|
+
}
|
163
|
+
|
164
|
+
FILTERS.each do |f|
|
165
|
+
next unless @opts[f]
|
166
|
+
|
167
|
+
params[f] = @opts[f]
|
168
|
+
end
|
169
|
+
|
170
|
+
@data = @api.ip_traffic_monitor.list(params)
|
171
|
+
end
|
172
|
+
|
173
|
+
def render(t, refresh)
|
174
|
+
if refresh
|
175
|
+
@data = nil
|
176
|
+
@header = nil
|
177
|
+
end
|
178
|
+
|
179
|
+
setpos(0, 0)
|
180
|
+
addstr("#{File.basename($0)} ip_traffic top - #{t.strftime('%H:%M:%S')}, ")
|
181
|
+
addstr("next update at #{(t + REFRESH_RATE).strftime('%H:%M:%S')}")
|
182
|
+
|
183
|
+
attron(color_pair(1))
|
184
|
+
setpos(2, 0)
|
185
|
+
header
|
186
|
+
attroff(color_pair(1))
|
187
|
+
|
188
|
+
i = 3
|
189
|
+
|
190
|
+
fetch.each do |data|
|
191
|
+
setpos(i, 0)
|
192
|
+
print_row(data)
|
193
|
+
|
194
|
+
i += 1
|
195
|
+
|
196
|
+
break if i >= (lines - 5)
|
197
|
+
end
|
198
|
+
|
199
|
+
stats
|
200
|
+
refresh
|
201
|
+
end
|
202
|
+
|
203
|
+
def header
|
204
|
+
unless @header
|
205
|
+
fmt = (['%-30s', '%6s'] + @columns.map { |c| "%#{c[:width]}s" }).join(' ')
|
206
|
+
|
207
|
+
@header = sprintf(
|
208
|
+
fmt,
|
209
|
+
'IP Address',
|
210
|
+
'VPS',
|
211
|
+
*@columns.map { |c| c[:title] },
|
212
|
+
)
|
213
|
+
|
214
|
+
@header << (' ' * (cols - @header.size)) << "\n"
|
215
|
+
end
|
216
|
+
|
217
|
+
addstr(@header)
|
218
|
+
end
|
219
|
+
|
220
|
+
def print_row(data)
|
221
|
+
addstr(sprintf('%-30s %6s', data.ip_address.addr, data.ip_address.vps_id))
|
222
|
+
|
223
|
+
@columns.each do |c|
|
224
|
+
p = c[:name]
|
225
|
+
|
226
|
+
attron(A_BOLD) if p == @sort_param
|
227
|
+
addstr(sprintf(" %#{c[:width]}s", unitize(data.send(p), data.delta)))
|
228
|
+
attroff(A_BOLD) if p == @sort_param
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def stats
|
233
|
+
fields = %i(packets bytes public_bytes private_bytes)
|
234
|
+
stats = {}
|
235
|
+
delta_sum = 0
|
236
|
+
|
237
|
+
fields.each do |f|
|
238
|
+
stats[f] = 0
|
239
|
+
|
240
|
+
%i(in out).each do |dir|
|
241
|
+
stats[:"#{f}_#{dir}"] = 0
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
fetch.each do |data|
|
246
|
+
delta_sum += data.delta
|
247
|
+
|
248
|
+
fields.each do |f|
|
249
|
+
stats[f] += data.send(f)
|
250
|
+
|
251
|
+
%i(in out).each do |dir|
|
252
|
+
stats[:"#{f}_#{dir}"] += data.send("#{f}_#{dir}")
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
avg_delta = delta_sum.to_f / fetch.count
|
258
|
+
|
259
|
+
setpos(lines-5, 0)
|
260
|
+
addstr('─' * cols)
|
261
|
+
|
262
|
+
fmt = '%10s %10s %10s %14s %14s'
|
263
|
+
unit = @opts[:unit].to_s.capitalize
|
264
|
+
|
265
|
+
setpos(lines-4, 0)
|
266
|
+
addstr(sprintf(
|
267
|
+
fmt,
|
268
|
+
'',
|
269
|
+
'Packets/s',
|
270
|
+
"#{unit}/s",
|
271
|
+
"Public#{unit}/s",
|
272
|
+
"Private#{unit}/s"
|
273
|
+
))
|
274
|
+
|
275
|
+
setpos(lines-3, 0)
|
276
|
+
addstr(sprintf(fmt, 'In', *fields.map { |f| unitize(stats[:"#{f}_in"], avg_delta) }))
|
277
|
+
|
278
|
+
setpos(lines-2, 0)
|
279
|
+
addstr(sprintf(fmt, 'Out', *fields.map { |f| unitize(stats[:"#{f}_out"], avg_delta) }))
|
280
|
+
|
281
|
+
setpos(lines-1, 0)
|
282
|
+
attron(A_BOLD)
|
283
|
+
addstr(sprintf(fmt, 'Total', *fields.map { |f| unitize(stats[:"#{f}_in"] + stats[:"#{f}_out"], avg_delta) }))
|
284
|
+
attroff(A_BOLD)
|
285
|
+
end
|
286
|
+
|
287
|
+
def unitize(n, delta)
|
288
|
+
if @opts[:unit] == :bytes
|
289
|
+
per_s = n / delta.to_f
|
290
|
+
else
|
291
|
+
per_s = n * 8 / delta.to_f
|
292
|
+
end
|
293
|
+
|
294
|
+
bits = 39
|
295
|
+
units = %i(T G M K)
|
296
|
+
|
297
|
+
units.each do |u|
|
298
|
+
threshold = 2 << bits
|
299
|
+
|
300
|
+
return "#{(per_s / threshold).round(2)}#{u}" if per_s >= threshold
|
301
|
+
|
302
|
+
bits -= 10
|
303
|
+
end
|
304
|
+
|
305
|
+
per_s.round(2).to_s
|
306
|
+
end
|
307
|
+
|
308
|
+
def sort_next(n)
|
309
|
+
cur_i = @params.index(@sort_param)
|
310
|
+
next_i = cur_i + n
|
311
|
+
return unless @params[next_i]
|
312
|
+
|
313
|
+
@sort_param = @params[next_i]
|
314
|
+
@refresh = true
|
315
|
+
end
|
316
|
+
|
317
|
+
def sort_inverse
|
318
|
+
@sort_desc = !@sort_desc
|
319
|
+
@refresh = true
|
320
|
+
end
|
321
|
+
|
322
|
+
def ip_address_id(v)
|
323
|
+
return v if /^\d+$/ =~ v
|
324
|
+
|
325
|
+
ips = @api.ip_address.list(addr: v)
|
326
|
+
return false if ips.count < 1
|
327
|
+
ips.first.id
|
328
|
+
|
329
|
+
rescue HaveAPI::Client::ActionFailed
|
330
|
+
return false
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
data/vpsadmin-client.gemspec
CHANGED
@@ -21,9 +21,10 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
22
22
|
spec.add_development_dependency 'rake'
|
23
23
|
|
24
|
-
spec.add_runtime_dependency 'haveapi-client', '~> 0.
|
24
|
+
spec.add_runtime_dependency 'haveapi-client', '~> 0.6.0'
|
25
25
|
spec.add_runtime_dependency 'eventmachine', '~> 1.0.3'
|
26
26
|
spec.add_runtime_dependency 'em-http-request', '~> 1.1.3'
|
27
27
|
spec.add_runtime_dependency 'json', '~> 1.8.3'
|
28
28
|
spec.add_runtime_dependency 'ruby-progressbar', '~> 1.7.5'
|
29
|
+
spec.add_runtime_dependency 'curses'
|
29
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vpsadmin-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jakub Skokan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: 0.6.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.6.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: eventmachine
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ~>
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 1.7.5
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: curses
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
description: Ruby API and CLI for vpsAdmin API
|
112
126
|
email:
|
113
127
|
- jakub.skokan@vpsfree.cz
|
@@ -128,6 +142,7 @@ files:
|
|
128
142
|
- lib/vpsadmin/cli/commands/backup_dataset.rb
|
129
143
|
- lib/vpsadmin/cli/commands/backup_vps.rb
|
130
144
|
- lib/vpsadmin/cli/commands/base_download.rb
|
145
|
+
- lib/vpsadmin/cli/commands/ip_traffic_top.rb
|
131
146
|
- lib/vpsadmin/cli/commands/snapshot_download.rb
|
132
147
|
- lib/vpsadmin/cli/commands/snapshot_send.rb
|
133
148
|
- lib/vpsadmin/cli/commands/vps_migrate_many.rb
|
@@ -156,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
171
|
version: '0'
|
157
172
|
requirements: []
|
158
173
|
rubyforge_project:
|
159
|
-
rubygems_version: 2.2
|
174
|
+
rubygems_version: 2.5.2
|
160
175
|
signing_key:
|
161
176
|
specification_version: 4
|
162
177
|
summary: Ruby API and CLI for vpsAdmin API
|