ring-sqa 0.0.19 → 0.0.20

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: 3118fdb4ee6c8ef1701ba4290bdee0c82bcb07db
4
- data.tar.gz: 5dc539f039179912322562d3354ceec8b55b99b5
3
+ metadata.gz: caa9122c18e3a803a62729778308c5af962fdfab
4
+ data.tar.gz: 877437aef04803f4baf0f9603e938f46b886445d
5
5
  SHA512:
6
- metadata.gz: bcdfe20771cb15f22135512d9861a7c56b3eafbd185e42f3cdfefa3ed7950f104e3bcda33d3026713a90d5250efba22e3449d02fb1f47cd6023f6e177bcb070e
7
- data.tar.gz: eee37b25fb65db3036e90ebc5327c093bbce7f2c67a453e16a8ebc42f5e59e0d1d661b108091812e5e80bb35c3f2d93248747235d0f4bd4f22ebd4f737dedaec
6
+ metadata.gz: b0fde0350ff73add7549347cb05b493a01bdb98f8cac9669616c10c4c53045ac32ed8e4e52c63654d1470810bf50d1260556503b0bc95376a1648b67fc2f290a
7
+ data.tar.gz: bded7fb091e59c8706412efabe163ccb7e72516fe6feaf0ef6b9eeb1a469561d7afe05f1da09a32fed4b34e5d82752fabf777e6706f4ccfd1b75a9fa04811756
data/Rakefile CHANGED
@@ -43,4 +43,5 @@ end
43
43
  desc 'Push to rubygems'
44
44
  task :push do
45
45
  system "gem push gems/#{file}"
46
+ system "git tag #{gemspec.version}"
46
47
  end
@@ -1,9 +1,9 @@
1
1
  require_relative 'alarm/email'
2
2
  require_relative 'alarm/udp2irc'
3
3
  require_relative 'alarm/cfg'
4
+ require_relative 'alarm/message'
4
5
  require_relative 'mtr'
5
6
  require_relative 'paste'
6
- require_relative 'nodes_json'
7
7
 
8
8
  module Ring
9
9
  class SQA
@@ -30,19 +30,19 @@ class SQA
30
30
 
31
31
  private
32
32
 
33
- def initialize
33
+ def initialize nodes
34
+ @nodes = nodes
34
35
  @methods = []
35
36
  @methods << Email.new if CFG.email.to?
36
37
  @methods << UDP2IRC.new if CFG.irc.password?
38
+ @hostname = Ring::SQA::CFG.host.name
37
39
  @alarm = false
38
- @hostname = (Socket.gethostname rescue 'anonymous')
39
40
  end
40
41
 
41
42
  def compose_message alarm_buffer
42
43
  exceeding_nodes = alarm_buffer.exceeding_nodes
43
44
  msg = {short: "#{@hostname}: raising alarm - #{exceeding_nodes.size} new nodes down"}
44
- nodes_json = NodesJSON.new
45
- exceeding_nodes = exceeding_nodes.map { |node| nodes_json.get node }
45
+ exceeding_nodes = exceeding_nodes.map { |node| @nodes.get node }
46
46
 
47
47
  nodes_list = ''
48
48
  exceeding_nodes.sort_by{ |node| node[:cc] }.each do |node|
@@ -64,40 +64,7 @@ class SQA
64
64
  time -= 1
65
65
  end
66
66
 
67
- msg[:long] = <<EOF
68
- Regarding: #{hostname}
69
-
70
- This is an automated alert from the distributed partial outage
71
- monitoring system "RING SQA".
72
-
73
- At #{Time.now.utc} the following measurements were analysed
74
- as indicating that there is a high probability your NLNOG RING node
75
- cannot reach the entire internet. Possible causes could be an outage
76
- in your upstream's or peer's network.
77
-
78
- The following #{exceeding_nodes.size} nodes previously were reachable, but became unreachable
79
- over the course of the last 3 minutes:
80
-
81
- #{nodes_list}
82
-
83
- As a debug starting point 3 traceroutes were launched right after
84
- detecting the event, they might assist in pinpointing what broke:
85
-
86
- #{mtr_list}
87
-
88
- An alarm is raised under the following conditions: every 30 seconds
89
- your node pings all other nodes. The amount of nodes that cannot be
90
- reached is stored in a circular buffer, with each element representing
91
- a minute of measurements. In the event that the last three minutes are
92
- #{Ring::SQA::CFG.analyzer.tolerance} above the median of the previous 27 measurement slots, a partial
93
- outage is assumed. The ring buffer's output is as following:
94
-
95
- #{buffer_list}
96
-
97
- Kind regards,
98
-
99
- NLNOG RING
100
- EOF
67
+ msg[:long] = message nodes_list, mtr_list, buffer_list
101
68
  msg
102
69
  end
103
70
 
@@ -0,0 +1,44 @@
1
+ module Ring
2
+ class SQA
3
+
4
+ class Alarm
5
+ def message nodes_list, mtr_list, buffer_list
6
+ "
7
+ Regarding: #{Ring::SQA::CFG.host.name}
8
+
9
+ This is an automated alert from the distributed partial outage
10
+ monitoring system 'RING SQA'.
11
+
12
+ At #{Time.now.utc} the following measurements were analysed
13
+ as indicating that there is a high probability your NLNOG RING node
14
+ cannot reach the entire internet. Possible causes could be an outage
15
+ in your upstream's or peer's network.
16
+
17
+ The following #{nodes_list.size} nodes previously were reachable, but became unreachable
18
+ over the course of the last 3 minutes:
19
+
20
+ #{nodes_list}
21
+
22
+ As a debug starting point 3 traceroutes were launched right after
23
+ detecting the event, they might assist in pinpointing what broke:
24
+
25
+ #{mtr_list}
26
+
27
+ An alarm is raised under the following conditions: every 30 seconds
28
+ your node pings all other nodes. The amount of nodes that cannot be
29
+ reached is stored in a circular buffer, with each element representing
30
+ a minute of measurements. In the event that the last three minutes are
31
+ #{Ring::SQA::CFG.analyzer.tolerance} above the median of the previous 27 measurement slots, a partial
32
+ outage is assumed. The ring buffer's output is as following:
33
+
34
+ #{buffer_list}
35
+
36
+ Kind regards,
37
+
38
+ NLNOG RING
39
+ "
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -30,8 +30,8 @@ class SQA
30
30
  def initialize database, nodes
31
31
  @db = database
32
32
  @nodes = nodes
33
- @alarm = Alarm.new
34
- @buffer = AnalyzeBuffer.new @nodes.list.size
33
+ @alarm = Alarm.new @nodes
34
+ @buffer = AnalyzeBuffer.new @nodes.all.size
35
35
  @db_id_seen = 0
36
36
  end
37
37
  end
data/lib/ring/sqa/cfg.rb CHANGED
@@ -27,8 +27,9 @@ module Ring
27
27
 
28
28
  CFG = Config.cfg
29
29
 
30
- CFG.bind.ipv4 = Socket::getaddrinfo(Socket.gethostname,"echo",Socket::AF_INET)[0][3]
31
- CFG.bind.ipv6 = Socket::getaddrinfo(Socket.gethostname,"echo",Socket::AF_INET6)[0][3]
30
+ CFG.host.name = Socket.gethostname
31
+ CFG.host.ipv4 = Socket::getaddrinfo(CFG.host.name,"echo",Socket::AF_INET)[0][3]
32
+ CFG.host.ipv6 = Socket::getaddrinfo(CFG.host.name,"echo",Socket::AF_INET6)[0][3]
32
33
 
33
34
  raise NoConfig, 'edit /etc/ring-sqa/main.conf' if Config.create
34
35
  end
@@ -1,29 +1,34 @@
1
1
  require 'rb-inotify'
2
2
  require 'ipaddr'
3
+ require 'json'
3
4
 
4
5
  module Ring
5
6
  class SQA
6
7
 
7
8
  class Nodes
8
- FILE = '/etc/hosts'
9
- attr_reader :list
9
+ FILE = '/etc/hosts'
10
+ attr_reader :all
10
11
 
11
12
  def run
12
13
  Thread.new { @inotify.run }
13
14
  end
14
15
 
16
+ def get node
17
+ (@all[node] or {})
18
+ end
19
+
15
20
  private
16
21
 
17
22
  def initialize
18
- @list = get_list
23
+ @all = read_nodes
19
24
  @inotify = INotify::Notifier.new
20
25
  @inotify.watch(File.dirname(FILE), :modify, :create) do |event|
21
- @list = get_list if event.name == FILE.split('/').last
26
+ @all = read_nodes if event.name == FILE.split('/').last
22
27
  end
23
28
  run
24
29
  end
25
30
 
26
- def get_list
31
+ def read_nodes
27
32
  Log.info "loading #{FILE}"
28
33
  list = []
29
34
  File.read(FILE).lines.each do |line|
@@ -31,26 +36,55 @@ class SQA
31
36
  next if entry_skip? entry
32
37
  list << entry.first
33
38
  end
34
- list.sort
39
+ nodes_hash list
40
+ rescue => error
41
+ Log.warn "#{error.class} raised with message '#{error.message}' while generating nodes list"
42
+ @all
43
+ end
44
+
45
+ def nodes_hash ips, file=CFG.nodes_json
46
+ nodes = {}
47
+ json = JSON.load File.read(file)
48
+ json['results']['nodes'].each do |node|
49
+ addr = CFG.ipv6? ? node['ipv6'] : node['ipv4']
50
+ next unless ips.include? addr
51
+ nodes[addr] = node
52
+ end
53
+ json_to_nodes_hash nodes
35
54
  end
36
55
 
56
+ def json_to_nodes_hash from_json
57
+ nodes= {}
58
+ from_json.each do |ip, json|
59
+ node = {
60
+ name: json['hostname'],
61
+ ip: ip,
62
+ as: json['asn'],
63
+ cc: json['countrycode'],
64
+ }
65
+ next if CFG.host.name == node[:name]
66
+ nodes[ip] = node
67
+ end
68
+ nodes
69
+ end
70
+
71
+
37
72
  def entry_skip? entry
38
73
  return true unless entry.size > 2
39
- return true if entry.first.match /^\s*#/
74
+ return true if entry.first.match(/^\s*#/)
40
75
  return true if CFG.hosts.ignore.any? { |re| entry[2].match Regexp.new(re) }
41
76
  return true unless CFG.hosts.load.any? { |re| entry[2].match Regexp.new(re) }
42
77
 
43
78
  address = IPAddr.new(entry.first) rescue (return true)
44
79
  if CFG.ipv6?
45
80
  return true if address.ipv4?
46
- return true if address == IPAddr.new(CFG.bind.ipv6)
81
+ return true if address == IPAddr.new(CFG.host.ipv6)
47
82
  else
48
83
  return true if address.ipv6?
49
- return true if address == IPAddr.new(CFG.bind.ipv4)
84
+ return true if address == IPAddr.new(CFG.host.ipv4)
50
85
  end
51
86
  false
52
87
  end
53
-
54
88
  end
55
89
 
56
90
  end
@@ -6,8 +6,8 @@ class SQA
6
6
  class Paste
7
7
  def self.add string
8
8
  Paste.new.add string
9
- rescue
10
- 'paste failed'
9
+ rescue => error
10
+ "paste raised '#{error.class}' with message '#{error.message}'"
11
11
  end
12
12
 
13
13
  def add string, url=CFG.paste.url
@@ -5,7 +5,8 @@ class SQA
5
5
  MAX_READ = 500
6
6
 
7
7
  def address
8
- CFG.ipv6? ? CFG.bind.ipv6 : CFG.bind.ipv4
8
+ #CFG.ipv6? ? CFG.host.ipv6 : CFG.host.ipv4
9
+ CFG.ipv6? ? '::' : '0.0.0.0' # NAT 1:1 does not have expected address where we can bind
9
10
  end
10
11
 
11
12
  def port
@@ -9,7 +9,7 @@ class SQA
9
9
  udp = udp_socket
10
10
  loop do
11
11
  loop_start = Time.now
12
- @nodes.list.each do |node|
12
+ @nodes.all.each do |node, _|
13
13
  query node, udp
14
14
  sleep INTER_NODE_GAP
15
15
  end
data/ring-sqa.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'ring-sqa'
3
- s.version = '0.0.19'
3
+ s.version = '0.0.20'
4
4
  s.licenses = %w( Apache-2.0 )
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = [ 'Saku Ytti', 'Job Snijders' ]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ring-sqa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.19
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Saku Ytti
@@ -103,6 +103,7 @@ files:
103
103
  - lib/ring/sqa/alarm.rb
104
104
  - lib/ring/sqa/alarm/cfg.rb
105
105
  - lib/ring/sqa/alarm/email.rb
106
+ - lib/ring/sqa/alarm/message.rb
106
107
  - lib/ring/sqa/alarm/udp2irc.rb
107
108
  - lib/ring/sqa/analyzer.rb
108
109
  - lib/ring/sqa/cfg.rb
@@ -113,7 +114,6 @@ files:
113
114
  - lib/ring/sqa/log.rb
114
115
  - lib/ring/sqa/mtr.rb
115
116
  - lib/ring/sqa/nodes.rb
116
- - lib/ring/sqa/nodes_json.rb
117
117
  - lib/ring/sqa/paste.rb
118
118
  - lib/ring/sqa/poller.rb
119
119
  - lib/ring/sqa/poller/receiver.rb
@@ -1,38 +0,0 @@
1
- require 'json'
2
-
3
- module Ring
4
- class SQA
5
-
6
- class NodesJSON
7
- def get node
8
- json = (@nodes[node] or {})
9
- {
10
- name: json['hostname'],
11
- ip: node,
12
- as: json['asn'],
13
- cc: json['countrycode'],
14
- }
15
- rescue
16
- {}
17
- end
18
-
19
- private
20
-
21
- def initialize
22
- @file = CFG.nodes_json
23
- @nodes = (load_json rescue {})
24
- end
25
-
26
- def load_json
27
- nodes = {}
28
- json = JSON.load File.read(@file)
29
- json['results']['nodes'].each do |node|
30
- addr = CFG.ipv6? ? node['ipv6'] : node['ipv4']
31
- nodes[addr] = node
32
- end
33
- nodes
34
- end
35
- end
36
-
37
- end
38
- end