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 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