etcd-tools 0.2.9 → 0.3.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 +8 -8
- data/lib/etcd-tools/erb.rb +6 -9
- data/lib/etcd-tools/etcd.rb +21 -25
- data/lib/{etcd_tools.rb → etcd-tools.rb} +2 -4
- metadata +4 -38
- data/bin/etcd-watchdog-haproxy +0 -4
- data/bin/etcd-watchdog-vip +0 -4
- data/lib/etcd-tools/watchdog/haproxy.rb +0 -23
- data/lib/etcd-tools/watchdog/init.rb +0 -43
- data/lib/etcd-tools/watchdog/threads/etcd.rb +0 -20
- data/lib/etcd-tools/watchdog/threads/icmp.rb +0 -22
- data/lib/etcd-tools/watchdog/util/config.rb +0 -43
- data/lib/etcd-tools/watchdog/util/etcd.rb +0 -34
- data/lib/etcd-tools/watchdog/util/helpers.rb +0 -25
- data/lib/etcd-tools/watchdog/util/logger.rb +0 -44
- data/lib/etcd-tools/watchdog/vip.rb +0 -170
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
Yzc0YWVjZTY0ODdhOTA1NGE4YTAyMGI2MDk4NDc2YzVkYzk0ZWYwYg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
M2JjMWVhOGIzZGRjMjMwOGYzODQ2ZmVkNTYzNjRhNGFkOTViOGY0Zg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NTc3MTExOGFjY2M1NGM5YWM5NzVhYzcyYTAxZjgwMzQ1NDYzODEzYmZhNDdm
|
10
|
+
MWViYmZjMDE0NmJlZGIxNTUxN2Q1Yzc1ZWRhMDI0MDI3NWQyZmI3MDlmNzdh
|
11
|
+
ZGIzN2Y0NzNhZGUzNzk1NDg3YThmZTI4Yzk3MGZhOWFkYTc0NDk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTQ2NzE2NmM3NjU2ZGNhOGVjYTVjYTcyMzkyYTk2ODFiYjNhZmFiYmRhOGY0
|
14
|
+
OWZhZTk0Y2E3OTM5MDkxYThkOTNiODEyYjhiOTE0YmQ4ZWRjN2RkMThhNDFj
|
15
|
+
MTNmNTUyZGE2ZmQzMWE4OTJiNzJiNWEzNzFhNjQzMzZkMWY3ZDk=
|
data/lib/etcd-tools/erb.rb
CHANGED
@@ -15,10 +15,9 @@ module EtcdTools
|
|
15
15
|
end
|
16
16
|
@etcd = etcd
|
17
17
|
compiler = ::ERB::Compiler.new('-')
|
18
|
-
set_eoutvar(compiler,
|
18
|
+
set_eoutvar(compiler, '_erbout')
|
19
19
|
@src, @enc = *compiler.compile(template)
|
20
20
|
@filename = nil
|
21
|
-
# super template
|
22
21
|
end
|
23
22
|
|
24
23
|
def result
|
@@ -26,7 +25,7 @@ module EtcdTools
|
|
26
25
|
end
|
27
26
|
|
28
27
|
def value path
|
29
|
-
|
28
|
+
@etcd.get('/' + path.sub(/^\//, '')).value
|
30
29
|
end
|
31
30
|
|
32
31
|
def keys path
|
@@ -39,15 +38,13 @@ module EtcdTools
|
|
39
38
|
end
|
40
39
|
|
41
40
|
def hash path
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
{}
|
46
|
-
end
|
41
|
+
etcd2hash @etcd, path
|
42
|
+
rescue
|
43
|
+
{}
|
47
44
|
end
|
48
45
|
|
49
46
|
def members
|
50
|
-
Hash[ @etcd.members.map { |id, md| [ id, md.merge({
|
47
|
+
Hash[ @etcd.members.map { |id, md| [ id, md.merge({ 'ip' => md['clientURLs'].first.sub(/https?:\/\//, '').sub(/:[0-9]+/, '') }) ] } ]
|
51
48
|
end
|
52
49
|
|
53
50
|
end
|
data/lib/etcd-tools/etcd.rb
CHANGED
@@ -3,7 +3,7 @@ require 'etcd-tools/mixins'
|
|
3
3
|
|
4
4
|
module EtcdTools
|
5
5
|
module Etcd
|
6
|
-
def etcd_connect
|
6
|
+
def etcd_connect(url)
|
7
7
|
(host, port) = url.gsub(/^https?:\/\//, '').gsub(/\/$/, '').split(':')
|
8
8
|
etcd = ::Etcd.client(host: host, port: port)
|
9
9
|
begin
|
@@ -14,36 +14,32 @@ module EtcdTools
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def hash2etcd
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
etcd.set(etcd_key, value: value)
|
26
|
-
end
|
17
|
+
def hash2etcd(etcd, hash, path = '')
|
18
|
+
hash.each do |key, value|
|
19
|
+
path = "" if path == '/'
|
20
|
+
etcd_key = path + '/' + key.to_s
|
21
|
+
if value.class == Hash
|
22
|
+
hash2etcd(etcd, value, etcd_key)
|
23
|
+
else
|
24
|
+
etcd.set(etcd_key, value: value)
|
27
25
|
end
|
28
|
-
rescue Exception => e
|
29
|
-
raise e #fixme
|
30
26
|
end
|
27
|
+
rescue Exception => e
|
28
|
+
raise e #fixme
|
31
29
|
end
|
32
30
|
|
33
|
-
def etcd2hash
|
34
|
-
|
35
|
-
|
36
|
-
etcd.get(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
h[child.key.split('/').last.to_s] = child.value
|
41
|
-
end
|
31
|
+
def etcd2hash(etcd, path = '')
|
32
|
+
h = {}
|
33
|
+
etcd.get(path).children.each do |child|
|
34
|
+
if etcd.get(child.key).directory?
|
35
|
+
h[child.key.split('/').last.to_s] = etcd2hash etcd, child.key
|
36
|
+
else
|
37
|
+
h[child.key.split('/').last.to_s] = child.value
|
42
38
|
end
|
43
|
-
return Hash[h.sort]
|
44
|
-
rescue Exception => e
|
45
|
-
return nil
|
46
39
|
end
|
40
|
+
return Hash[h.sort]
|
41
|
+
rescue Exception => e
|
42
|
+
return nil
|
47
43
|
end
|
48
44
|
end
|
49
45
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: etcd-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Radek 'blufor' Slavicinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: etcd
|
@@ -30,32 +30,9 @@ dependencies:
|
|
30
30
|
- - ! '>='
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 0.3.0
|
33
|
-
-
|
34
|
-
name: net-ping
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - ~>
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '1.7'
|
40
|
-
- - ! '>='
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: 1.7.8
|
43
|
-
type: :runtime
|
44
|
-
prerelease: false
|
45
|
-
version_requirements: !ruby/object:Gem::Requirement
|
46
|
-
requirements:
|
47
|
-
- - ~>
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '1.7'
|
50
|
-
- - ! '>='
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: 1.7.8
|
53
|
-
description: A set of handful daemons and command-line utils for ETCD (is part of
|
54
|
-
PortAuthority)
|
33
|
+
description: A set of handful command-line utils for ETCD
|
55
34
|
email: radek.slavicinsky@gmail.com
|
56
35
|
executables:
|
57
|
-
- etcd-watchdog-haproxy
|
58
|
-
- etcd-watchdog-vip
|
59
36
|
- etcd-erb
|
60
37
|
- yaml2etcd
|
61
38
|
- etcd2yaml
|
@@ -63,26 +40,15 @@ extensions: []
|
|
63
40
|
extra_rdoc_files: []
|
64
41
|
files:
|
65
42
|
- bin/etcd-erb
|
66
|
-
- bin/etcd-watchdog-haproxy
|
67
|
-
- bin/etcd-watchdog-vip
|
68
43
|
- bin/etcd2yaml
|
69
44
|
- bin/yaml2etcd
|
45
|
+
- lib/etcd-tools.rb
|
70
46
|
- lib/etcd-tools/cli/etcd2yaml.rb
|
71
47
|
- lib/etcd-tools/cli/etcd_erb.rb
|
72
48
|
- lib/etcd-tools/cli/yaml2etcd.rb
|
73
49
|
- lib/etcd-tools/erb.rb
|
74
50
|
- lib/etcd-tools/etcd.rb
|
75
51
|
- lib/etcd-tools/mixins.rb
|
76
|
-
- lib/etcd-tools/watchdog/haproxy.rb
|
77
|
-
- lib/etcd-tools/watchdog/init.rb
|
78
|
-
- lib/etcd-tools/watchdog/threads/etcd.rb
|
79
|
-
- lib/etcd-tools/watchdog/threads/icmp.rb
|
80
|
-
- lib/etcd-tools/watchdog/util/config.rb
|
81
|
-
- lib/etcd-tools/watchdog/util/etcd.rb
|
82
|
-
- lib/etcd-tools/watchdog/util/helpers.rb
|
83
|
-
- lib/etcd-tools/watchdog/util/logger.rb
|
84
|
-
- lib/etcd-tools/watchdog/vip.rb
|
85
|
-
- lib/etcd_tools.rb
|
86
52
|
homepage: https://github.com/blufor/etcd-tools
|
87
53
|
licenses:
|
88
54
|
- GPLv2
|
data/bin/etcd-watchdog-haproxy
DELETED
data/bin/etcd-watchdog-vip
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'etcd-tools/watchdog/init'
|
2
|
-
# require 'etcd-tools/watchdogthreads/haproxy'
|
3
|
-
require 'etcd-tools/erb'
|
4
|
-
|
5
|
-
module EtcdTools
|
6
|
-
module Watchdog
|
7
|
-
class HAproxy < EtcdTools::Watchdog::Init
|
8
|
-
|
9
|
-
def run
|
10
|
-
while @etcd.watch(@config[:haproxy_cfg]) do
|
11
|
-
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def generate_config
|
16
|
-
end
|
17
|
-
|
18
|
-
def reload_haproxy
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'timeout'
|
2
|
-
require 'json'
|
3
|
-
require 'time'
|
4
|
-
require 'etcd-tools/mixins'
|
5
|
-
require 'etcd-tools/watchdog/util/config'
|
6
|
-
require 'etcd-tools/watchdog/util/logger'
|
7
|
-
require 'etcd-tools/watchdog/util/helpers'
|
8
|
-
require 'etcd-tools/watchdog/util/etcd'
|
9
|
-
require 'etcd-tools/watchdog/threads/etcd'
|
10
|
-
|
11
|
-
module EtcdTools
|
12
|
-
module Watchdog
|
13
|
-
class Init
|
14
|
-
|
15
|
-
include EtcdTools::Watchdog::Util::Config
|
16
|
-
include EtcdTools::Watchdog::Util::Logger
|
17
|
-
include EtcdTools::Watchdog::Util::Helpers
|
18
|
-
include EtcdTools::Watchdog::Util::Etcd
|
19
|
-
include EtcdTools::Watchdog::Threads
|
20
|
-
|
21
|
-
def initialize
|
22
|
-
@config = { debug: false }
|
23
|
-
@config = config
|
24
|
-
@exit = false
|
25
|
-
@exit_sigs = ['INT', 'TERM']
|
26
|
-
@exit_sigs.each { |sig| Signal.trap(sig) { @exit = true } }
|
27
|
-
Signal.trap('USR1') { @config[:debug] = false }
|
28
|
-
Signal.trap('USR2') { @config[:debug] = true }
|
29
|
-
Signal.trap('HUP') { @config = config }
|
30
|
-
end
|
31
|
-
|
32
|
-
def setup(proc_name, nice = -20)
|
33
|
-
if RUBY_VERSION >= '2.1'
|
34
|
-
Process.setproctitle(proc_name)
|
35
|
-
else
|
36
|
-
$0 = proc_name
|
37
|
-
end
|
38
|
-
Process.setpriority(Process::PRIO_PROCESS, 0, nice)
|
39
|
-
# TODO: Process.daemon ...
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module EtcdTools
|
2
|
-
module Watchdog
|
3
|
-
module Threads
|
4
|
-
def thread_etcd
|
5
|
-
Thread.new do
|
6
|
-
debug '<etcd> starting thread...'
|
7
|
-
etcd = etcd_connect!
|
8
|
-
while !@exit do
|
9
|
-
debug '<etcd> checking etcd state'
|
10
|
-
status = leader? etcd
|
11
|
-
@semaphore[:etcd].synchronize { @status_etcd = status }
|
12
|
-
debug "<etcd> i am #{status ? 'the leader' : 'not a leader' }"
|
13
|
-
sleep @config[:parameters][:etcd_interval]
|
14
|
-
end
|
15
|
-
info '<etcd> ending thread...'
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'net/ping'
|
2
|
-
|
3
|
-
module EtcdTools
|
4
|
-
module Watchdog
|
5
|
-
module Threads
|
6
|
-
def thread_icmp
|
7
|
-
Thread.new do
|
8
|
-
debug '<icmp> starting thread...'
|
9
|
-
icmp = Net::Ping::ICMP.new(@config[:parameters][:vip])
|
10
|
-
while !@exit do
|
11
|
-
debug '<icmp> checking state by ping'
|
12
|
-
status = vip_alive? icmp
|
13
|
-
@semaphore[:icmp].synchronize { @status_icmp = status }
|
14
|
-
debug "<icmp> VIP is #{status ? 'alive' : 'down' }"
|
15
|
-
sleep @config[:parameters][:icmp_interval]
|
16
|
-
end
|
17
|
-
info '<icmp> ending thread...'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'etcd-tools/mixins'
|
3
|
-
|
4
|
-
module EtcdTools
|
5
|
-
module Watchdog
|
6
|
-
module Util
|
7
|
-
module Config
|
8
|
-
private
|
9
|
-
def default_config
|
10
|
-
{ debug: false,
|
11
|
-
parameters: { interface: 'eth0',
|
12
|
-
vip: '192.168.0.168',
|
13
|
-
mask: '255.255.255.0',
|
14
|
-
interval: 1,
|
15
|
-
etcd_endpoint: 'http://127.0.0.1:4001',
|
16
|
-
etcd_interval: 1,
|
17
|
-
etcd_timeout: 5,
|
18
|
-
icmp_count: 2,
|
19
|
-
icmp_interval: 1,
|
20
|
-
arping_count: 1,
|
21
|
-
arping_wait: 1 },
|
22
|
-
commands: { arping: `which arping`.chomp,
|
23
|
-
iproute: `which ip`.chomp,
|
24
|
-
arp: `which arp`.chomp } }
|
25
|
-
end
|
26
|
-
|
27
|
-
def config
|
28
|
-
cfg = default_config
|
29
|
-
if File.exist? '/etc/etcd-watchdog.yaml'
|
30
|
-
cfg = cfg.deep_merge YAML.load_file('/etc/etcd-watchdog.yaml')
|
31
|
-
puts 'loaded config from /etc/etcd-watchdog.yaml'
|
32
|
-
elsif File.exist? './etcd-watchdog.yaml'
|
33
|
-
cfg = cfg.deep_merge YAML.load_file('./etcd-watchdog.yaml')
|
34
|
-
puts 'loaded config from ./etcd-watchdog.yaml'
|
35
|
-
else
|
36
|
-
puts 'no config file loaded, using defaults'
|
37
|
-
end
|
38
|
-
cfg
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'etcd'
|
2
|
-
|
3
|
-
module EtcdTools
|
4
|
-
module Watchdog
|
5
|
-
module Util
|
6
|
-
module Etcd
|
7
|
-
# connect to ETCD
|
8
|
-
def etcd_connect!
|
9
|
-
(host, port) = @config[:parameters][:etcd_endpoint].gsub(/^https?:\/\//, '').gsub(/\/$/, '').split(':')
|
10
|
-
etcd = ::Etcd.client(host: host, port: port)
|
11
|
-
begin
|
12
|
-
versions = JSON.parse(etcd.version)
|
13
|
-
info "<etcd> conncted to ETCD at #{@config[:parameters][:etcd_endpoint]}"
|
14
|
-
info "<etcd> server version: #{versions['etcdserver']}"
|
15
|
-
info "<etcd> cluster version: #{versions['etcdcluster']}"
|
16
|
-
info "<etcd> healthy: #{etcd.healthy?}"
|
17
|
-
return etcd
|
18
|
-
rescue Exception => e
|
19
|
-
err "<etcd> couldn't connect to etcd at #{host}:#{port}"
|
20
|
-
err "<etcd> #{e.message}"
|
21
|
-
@exit = true
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# is my ETCD the leader?
|
26
|
-
# <IMPLEMENTED>
|
27
|
-
def leader?(etcd)
|
28
|
-
etcd.stats(:self)['id'] == etcd.stats(:self)['leaderInfo']['leader']
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
|
3
|
-
module EtcdTools
|
4
|
-
module Watchdog
|
5
|
-
module Util
|
6
|
-
module Helpers
|
7
|
-
def hostname
|
8
|
-
@hostname ||= Socket.gethostname
|
9
|
-
end
|
10
|
-
|
11
|
-
def arping
|
12
|
-
@config[:commands][:arping]
|
13
|
-
end
|
14
|
-
|
15
|
-
def iproute
|
16
|
-
@config[:commands][:iproute]
|
17
|
-
end
|
18
|
-
|
19
|
-
def arp
|
20
|
-
@config[:commands][:arp]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'logger'
|
2
|
-
|
3
|
-
module EtcdTools
|
4
|
-
module Watchdog
|
5
|
-
module Util
|
6
|
-
module Logger
|
7
|
-
def info(message)
|
8
|
-
if @config[:debug]
|
9
|
-
@semaphore[:log].synchronize do
|
10
|
-
$stdout.puts(Time.now.to_s + ' INFO (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
11
|
-
$stdout.flush
|
12
|
-
end
|
13
|
-
else
|
14
|
-
@semaphore[:log].synchronize do
|
15
|
-
$stdout.puts(Time.now.to_s + ' INFO ' + message.to_s)
|
16
|
-
$stdout.flush
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def err(message)
|
22
|
-
if @config[:debug]
|
23
|
-
@semaphore[:log].synchronize do
|
24
|
-
$stdout.puts(Time.now.to_s + ' ERROR (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
25
|
-
$stdout.flush
|
26
|
-
end
|
27
|
-
else
|
28
|
-
@semaphore[:log].synchronize do
|
29
|
-
$stdout.puts(Time.now.to_s + ' ERROR ' + message.to_s)
|
30
|
-
$stdout.flush
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def debug(message)
|
36
|
-
@semaphore[:log].synchronize do
|
37
|
-
$stdout.puts(Time.now.to_s + ' DEBUG (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
38
|
-
$stdout.flush
|
39
|
-
end if @config[:debug]
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,170 +0,0 @@
|
|
1
|
-
require 'ipaddr'
|
2
|
-
require 'etcd-tools/watchdog/init'
|
3
|
-
require 'etcd-tools/watchdog/threads/icmp'
|
4
|
-
|
5
|
-
module EtcdTools
|
6
|
-
module Watchdog
|
7
|
-
class Vip < EtcdTools::Watchdog::Init
|
8
|
-
|
9
|
-
def run
|
10
|
-
if Process.euid != 0
|
11
|
-
$stderr.puts 'Must run under root user!'
|
12
|
-
exit! 1
|
13
|
-
end
|
14
|
-
setup 'etcd-vip-watchdog'
|
15
|
-
@semaphore = {
|
16
|
-
log: Mutex.new,
|
17
|
-
etcd: Mutex.new,
|
18
|
-
icmp: Mutex.new
|
19
|
-
}
|
20
|
-
@thread = { icmp: thread_icmp, etcd: thread_etcd }
|
21
|
-
@status_etcd = false
|
22
|
-
@status_icmp = false
|
23
|
-
@thread.each_value(&:run)
|
24
|
-
sleep @config[:parameters][:interval]
|
25
|
-
first_cycle = true
|
26
|
-
while !@exit do
|
27
|
-
status_etcd = status_icmp = false # FIXME: introduce CVs...
|
28
|
-
@semaphore[:icmp].synchronize { status_icmp = @status_icmp }
|
29
|
-
@semaphore[:etcd].synchronize { status_etcd = @status_etcd }
|
30
|
-
if status_etcd
|
31
|
-
if got_vip?
|
32
|
-
debug '<main> i am the leader with VIP, that is OK'
|
33
|
-
else
|
34
|
-
info '<main> i am the leader without VIP, checking whether it is free'
|
35
|
-
if status_icmp
|
36
|
-
info '<main> VIP is still up! (ICMP)'
|
37
|
-
# FIXME: notify by sensu client socket
|
38
|
-
else
|
39
|
-
info '<main> VIP is unreachable by ICMP, checking for duplicates on L2'
|
40
|
-
if vip_dup?
|
41
|
-
info '<main> VIP is still assigned! (ARP)'
|
42
|
-
# FIXME: notify by sensu client socket
|
43
|
-
else
|
44
|
-
info '<main> VIP is free, assigning'
|
45
|
-
vip_handle! status_etcd
|
46
|
-
info '<main> updating other hosts about change'
|
47
|
-
vip_update_arp!
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
else
|
52
|
-
if got_vip?
|
53
|
-
info '<main> i got VIP and should not, removing'
|
54
|
-
vip_handle! status_etcd
|
55
|
-
info '<main> updating other hosts about change'
|
56
|
-
vip_update_arp!
|
57
|
-
else
|
58
|
-
debug '<main> i am not a leader and i do not have the VIP, that is OK'
|
59
|
-
end
|
60
|
-
end
|
61
|
-
sleep @config[:parameters][:interval]
|
62
|
-
if first_cycle
|
63
|
-
@semaphore[:icmp].synchronize { status_icmp = @status_icmp }
|
64
|
-
@semaphore[:etcd].synchronize { status_etcd = @status_etcd }
|
65
|
-
info "<main> i #{status_etcd ? 'AM' : 'am NOT'} the leader"
|
66
|
-
info "<main> i #{got_vip? ? 'DO' : 'do NOT'} have the VIP"
|
67
|
-
info "<main> i #{status_icmp ? 'CAN' : 'CANNOT'} see the VIP"
|
68
|
-
end
|
69
|
-
first_cycle = false
|
70
|
-
end
|
71
|
-
info '<main> terminated!'
|
72
|
-
if got_vip?
|
73
|
-
info '<main> removing VIP'
|
74
|
-
vip_handle! false
|
75
|
-
vip_update_arp!
|
76
|
-
end
|
77
|
-
info '<main> stopping threads...'
|
78
|
-
@thread.each_value(&:join)
|
79
|
-
info '<main> exiting...'
|
80
|
-
exit 0
|
81
|
-
end
|
82
|
-
|
83
|
-
# add or remove VIP on interface
|
84
|
-
# <IMPLEMENTED>
|
85
|
-
def vip_handle!(leader)
|
86
|
-
ip = IPAddr.new(@config[:parameters][:vip])
|
87
|
-
mask = @config[:parameters][:mask]
|
88
|
-
cmd = [ iproute,
|
89
|
-
'address',
|
90
|
-
'',
|
91
|
-
"#{ip}/#{mask}",
|
92
|
-
'dev',
|
93
|
-
@config[:parameters][:interface],
|
94
|
-
'label',
|
95
|
-
@config[:parameters][:interface] + '-vip',
|
96
|
-
'>/dev/null 2>&1'
|
97
|
-
]
|
98
|
-
leader ? cmd[2] = 'add' : cmd[2] = 'delete'
|
99
|
-
debug "<shell> #{cmd.join(' ')}"
|
100
|
-
if system(cmd.join(' '))
|
101
|
-
return true
|
102
|
-
else
|
103
|
-
return false
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# send gratuitous ARP to the network
|
108
|
-
# <IMPLEMENTED>
|
109
|
-
def vip_update_arp!
|
110
|
-
cmd = [ arping, '-U', '-q',
|
111
|
-
'-c', @config[:parameters][:arping_count],
|
112
|
-
'-I', @config[:parameters][:interface],
|
113
|
-
@config[:parameters][:vip] ]
|
114
|
-
debug "<shell> #{cmd.join(' ')}"
|
115
|
-
if system(cmd.join(' '))
|
116
|
-
return true
|
117
|
-
else
|
118
|
-
return false
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
# check whether VIP is assigned to me
|
123
|
-
# <IMPLEMENTED>
|
124
|
-
def got_vip?
|
125
|
-
cmd = [ iproute,
|
126
|
-
'address',
|
127
|
-
'show',
|
128
|
-
'label',
|
129
|
-
"#{@config[:parameters][:interface]}-vip",
|
130
|
-
'|',
|
131
|
-
'grep',
|
132
|
-
'-q',
|
133
|
-
"#{@config[:parameters][:interface]}-vip"
|
134
|
-
]
|
135
|
-
debug "<shell> #{cmd.join(' ')}"
|
136
|
-
if system(cmd.join(' '))
|
137
|
-
return true
|
138
|
-
else
|
139
|
-
return false
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
# check reachability of VIP by ICMP echo
|
144
|
-
# <--- REWORK
|
145
|
-
def vip_alive?(icmp)
|
146
|
-
(1..@config[:parameters][:icmp_count]).each { return true if icmp.ping }
|
147
|
-
return false
|
148
|
-
end
|
149
|
-
|
150
|
-
# check whether the IP is registered anywhere
|
151
|
-
#
|
152
|
-
def vip_dup?
|
153
|
-
cmd_arp = [ arp, '-d', @config[:parameters][:vip], '>/dev/null 2>&1' ]
|
154
|
-
cmd_arping = [ arping, '-D', '-q',
|
155
|
-
'-c', @config[:parameters][:arping_count],
|
156
|
-
'-w', @config[:parameters][:arping_wait],
|
157
|
-
'-I', @config[:parameters][:interface],
|
158
|
-
@config[:parameters][:vip] ]
|
159
|
-
debug "<shell> #{cmd_arp.join(' ')}"
|
160
|
-
system(cmd_arp.join(' '))
|
161
|
-
debug "<shell> #{cmd_arping.join(' ')}"
|
162
|
-
if system(cmd_arping.join(' '))
|
163
|
-
return false
|
164
|
-
else
|
165
|
-
return true
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|