vpsadmin-client 2.3.2 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 306006d7f2b4824401856a6f22c2a882d64557c9
4
- data.tar.gz: 5c1ef15cbda427d8880ad818695f7de944819f85
3
+ metadata.gz: ba8192c7d8fd4f47bb344a6edfa0b27a30d850f0
4
+ data.tar.gz: 0fec21ca7c50c3fba23e15a50c4ecf2618e04423
5
5
  SHA512:
6
- metadata.gz: 7538ed7acad5ef3e69653456c1bc955eba14c55bfa0b42fbf3784d001408d393ded37446d3362deaeea0839a211606850f5929fed8f9b8391e9bda64c024c420
7
- data.tar.gz: 9feb2731a3f8321bc00d9681241e005838e330206f7793b76376954a490361f75fabdf6cddc84da01640f2435c718236cdccd4d8c7b887ef7ab878569c726125
6
+ metadata.gz: 743be4bedeccfb27de7355fea993dc1ee381e20f80cfbaa5bb1cebd43ff79c612bee0f505a073d71dc80965c51ba8dc0cdfaec2e9ddb2f3d7e7eda3a501aab1b
7
+ data.tar.gz: 15ef4a6f1a62934f78c60d2a97c37c80e5332e268096c7186fe7aec19f89374eee396e0ceeb5bb2d93a14d807a54893349aea9226e1e12ffd10855b21d33d4a9
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ - New command ip_traffic top
2
+
3
+ * Fri Jun 24 2016 - version 2.4.0
4
+ - No changes
5
+
1
6
  * Tue Jun 14 2016 - version 2.3.2
2
7
  - Don't set download progress on new request
3
8
 
data/lib/vpsadmin/cli.rb CHANGED
@@ -22,3 +22,4 @@ require 'vpsadmin/cli/commands/snapshot_download'
22
22
  require 'vpsadmin/cli/commands/snapshot_send'
23
23
  require 'vpsadmin/cli/commands/backup_dataset'
24
24
  require 'vpsadmin/cli/commands/backup_vps'
25
+ require 'vpsadmin/cli/commands/ip_traffic_top'
@@ -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
@@ -1,5 +1,5 @@
1
1
  module VpsAdmin
2
2
  module Client
3
- VERSION = '2.3.2'
3
+ VERSION = '2.5.0'
4
4
  end
5
5
  end
@@ -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.5.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.3.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-06-14 00:00:00.000000000 Z
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.5.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.5.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.5
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