port-authority 0.3.1
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 +15 -0
- data/bin/pa-master-watchdog +3 -0
- data/lib/port-authority/util/config.rb +62 -0
- data/lib/port-authority/util/etcd.rb +37 -0
- data/lib/port-authority/util/helpers.rb +27 -0
- data/lib/port-authority/util/loadbalancer.rb +52 -0
- data/lib/port-authority/util/logger.rb +42 -0
- data/lib/port-authority/util/vip.rb +72 -0
- data/lib/port-authority/watchdog/init.rb +38 -0
- data/lib/port-authority/watchdog/master.rb +145 -0
- data/lib/port-authority/watchdog/threads/icmp.rb +22 -0
- data/lib/port-authority/watchdog/threads/swarm.rb +20 -0
- data/lib/port-authority.rb +7 -0
- metadata +136 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OGQyMDZkOGNmMTM1ZTEyYTI4ZDA5YWYxZDc2M2ZhYjY5NDIwZGJmOA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZjMwNDUxNWY0MzllNTc2ZjZhNWEyZWQyYWNlYWY2NTQ4ZjhhM2NhOQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MDcxNWMxYTVhODE1MjMwM2U1ODk0OGUxOWQ0MDAyYWIzZTMwYTE4NGU3YWU4
|
10
|
+
OGViYzJmODc4NmM4NjMwZmM3MTVkYTg1YWQ4Y2Y4NDdiMTFmODc3NDE1NzRm
|
11
|
+
M2IzYWM2NDFhY2I1MTQzMjUwMmExNTFhMmRlMDhlOGY2Y2E3NWI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YjM3ZDEzOGNmZmM4MDU2ZGY2ZDc0NDc1ZjE1OWZlYTI3NzkxN2E2MGE3MGZj
|
14
|
+
NWI3MmQ4ZjBmNWRjMzBhYzQxZDc5Mjk0M2M3ZThhYWVkYjA3MjE0NGExYjE3
|
15
|
+
ZjI2ZjhhZGRhMjc3MTdkYzI2YWNmNzdjMTJkOGI5ODQ2ZWJkZDk=
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'etcd-tools'
|
3
|
+
|
4
|
+
module PortAuthority
|
5
|
+
module Util
|
6
|
+
module Config
|
7
|
+
private
|
8
|
+
|
9
|
+
def default_config
|
10
|
+
{ debug: false,
|
11
|
+
syslog: false,
|
12
|
+
etcd: {
|
13
|
+
endpoint: 'http://localhost:4001',
|
14
|
+
interval: 1,
|
15
|
+
timeout: 2
|
16
|
+
},
|
17
|
+
docker: {
|
18
|
+
socket: 'tcp://localhost:4243'
|
19
|
+
},
|
20
|
+
icmp: {
|
21
|
+
count: 2,
|
22
|
+
interval: 1
|
23
|
+
},
|
24
|
+
arping: {
|
25
|
+
count: 1,
|
26
|
+
wait: 1
|
27
|
+
},
|
28
|
+
vip: {
|
29
|
+
interval: 1,
|
30
|
+
ip: '172.17.1.5',
|
31
|
+
mask: '255.255.255.0',
|
32
|
+
interface: 'eth0'
|
33
|
+
},
|
34
|
+
lb: {
|
35
|
+
image: 'docker-registry.prz/stackdocks/haproxy:latest',
|
36
|
+
name: 'lb',
|
37
|
+
network: 'overlay'
|
38
|
+
},
|
39
|
+
commands: {
|
40
|
+
arping: `which arping`.chomp,
|
41
|
+
arp: `which arp`.chomp,
|
42
|
+
iproute: `which ip`.chomp
|
43
|
+
}
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def config
|
48
|
+
cfg = default_config
|
49
|
+
if File.exist? '/etc/port-authority.yaml'
|
50
|
+
cfg = cfg.deep_merge YAML.load_file('/etc/port-authority.yaml')
|
51
|
+
puts 'loaded config from /etc/port-authority.yaml'
|
52
|
+
elsif File.exist? './port-authority.yaml'
|
53
|
+
cfg = cfg.deep_merge YAML.load_file('./port-authority.yaml')
|
54
|
+
puts 'loaded config from ./port-authority.yaml'
|
55
|
+
else
|
56
|
+
puts 'no config file loaded, using defaults'
|
57
|
+
end
|
58
|
+
cfg
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'etcd'
|
2
|
+
|
3
|
+
module PortAuthority
|
4
|
+
module Util
|
5
|
+
module Etcd
|
6
|
+
# connect to ETCD
|
7
|
+
def etcd_connect!
|
8
|
+
(host, port) = @config[:etcd][:endpoint].gsub(/^https?:\/\//, '').gsub(/\/$/, '').split(':')
|
9
|
+
etcd = ::Etcd.client(host: host, port: port)
|
10
|
+
begin
|
11
|
+
versions = JSON.parse(etcd.version)
|
12
|
+
info "conncted to ETCD at #{@config[:etcd][:endpoint]}"
|
13
|
+
info "server version: #{versions['etcdserver']}"
|
14
|
+
info "cluster version: #{versions['etcdcluster']}"
|
15
|
+
info "healthy: #{etcd.healthy?}"
|
16
|
+
return etcd
|
17
|
+
rescue Exception => e
|
18
|
+
err "couldn't connect to etcd at #{host}:#{port}"
|
19
|
+
err "#{e.message}"
|
20
|
+
@exit = true
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def swarm_leader(etcd)
|
26
|
+
etcd.get('/_pa/docker/swarm/leader')
|
27
|
+
end
|
28
|
+
|
29
|
+
def am_i_leader?(etcd)
|
30
|
+
Socket.ip_address_list.map(){|a| a.ip_address }.member?(swarm_leader(etcd).split(':').first)
|
31
|
+
rescue Exception => e
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module PortAuthority
|
4
|
+
module Util
|
5
|
+
module Helpers
|
6
|
+
def hostname
|
7
|
+
@hostname ||= Socket.gethostname
|
8
|
+
end
|
9
|
+
|
10
|
+
def my_ip
|
11
|
+
@my_ip ||= Socket.ip_address_list.detect { |i| i.ipv4_private? }.ip_address
|
12
|
+
end
|
13
|
+
|
14
|
+
def arping
|
15
|
+
@config[:commands][:arping]
|
16
|
+
end
|
17
|
+
|
18
|
+
def iproute
|
19
|
+
@config[:commands][:iproute]
|
20
|
+
end
|
21
|
+
|
22
|
+
def arp
|
23
|
+
@config[:commands][:arp]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'docker-api'
|
2
|
+
|
3
|
+
module PortAuthority
|
4
|
+
module Util
|
5
|
+
module LoadBalancer
|
6
|
+
# connect to ETCD
|
7
|
+
def lb_docker_setup!
|
8
|
+
Docker.url = @config[:lb][:docker_endpoint]
|
9
|
+
Docker.version
|
10
|
+
true
|
11
|
+
rescue
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def lb_create
|
16
|
+
img = Docker::Image.create('fromImage' => @config[:lb][:image])
|
17
|
+
|
18
|
+
# setup port bindings hash
|
19
|
+
port_bindings = Hash.new
|
20
|
+
img.json['ContainerConfig']['ExposedPorts'].keys.each do |port|
|
21
|
+
port_bindings[port] = [ { 'HostPort' => "#{port.split('/').first}" } ]
|
22
|
+
end
|
23
|
+
|
24
|
+
# create container with
|
25
|
+
@lb_container = Docker::Container.create(
|
26
|
+
'Image' => i.json['Id'],
|
27
|
+
'name' => @config[:lb][:name],
|
28
|
+
'Hostname' => @config[:lb][:name],
|
29
|
+
'Env' => [ "ETCDCTL_ENDPOINT=#{@config[:etcd][:endpoint]}" ],
|
30
|
+
'RestartPolicy' => { 'Name' => 'never' },
|
31
|
+
'HostConfig' => {
|
32
|
+
'PortBindings' => port_bindings,
|
33
|
+
'NetworkMode' => @config[:lb][:network]
|
34
|
+
}
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def lb_up?
|
39
|
+
@lb_container.info['Status'] =~ /^[Uu]p/
|
40
|
+
end
|
41
|
+
|
42
|
+
def lb_start!
|
43
|
+
@lb_container.start
|
44
|
+
end
|
45
|
+
|
46
|
+
def lb_stop!
|
47
|
+
@lb_container.stop
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module PortAuthority
|
4
|
+
module Util
|
5
|
+
module Logger
|
6
|
+
def info(message)
|
7
|
+
if @config[:debug]
|
8
|
+
@semaphore[:log].synchronize do
|
9
|
+
$stdout.puts(Time.now.to_s + ' INFO (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
10
|
+
$stdout.flush
|
11
|
+
end
|
12
|
+
else
|
13
|
+
@semaphore[:log].synchronize do
|
14
|
+
$stdout.puts(Time.now.to_s + ' INFO ' + message.to_s)
|
15
|
+
$stdout.flush
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def err(message)
|
21
|
+
if @config[:debug]
|
22
|
+
@semaphore[:log].synchronize do
|
23
|
+
$stdout.puts(Time.now.to_s + ' ERROR (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
24
|
+
$stdout.flush
|
25
|
+
end
|
26
|
+
else
|
27
|
+
@semaphore[:log].synchronize do
|
28
|
+
$stdout.puts(Time.now.to_s + ' ERROR ' + message.to_s)
|
29
|
+
$stdout.flush
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def debug(message)
|
35
|
+
@semaphore[:log].synchronize do
|
36
|
+
$stdout.puts(Time.now.to_s + ' DEBUG (TID:' + Thread.current.object_id.to_s + ') ' + message.to_s)
|
37
|
+
$stdout.flush
|
38
|
+
end if @config[:debug]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module PortAuthority
|
2
|
+
module Util
|
3
|
+
module Vip
|
4
|
+
# add or remove VIP on interface
|
5
|
+
# <IMPLEMENTED>
|
6
|
+
def vip_handle!(leader)
|
7
|
+
ip = IPAddr.new(@config[:vip][:ip])
|
8
|
+
mask = @config[:vip][:mask]
|
9
|
+
cmd = [ iproute,
|
10
|
+
'address',
|
11
|
+
'',
|
12
|
+
"#{ip}/#{mask}",
|
13
|
+
'dev',
|
14
|
+
@config[:vip][:interface],
|
15
|
+
'label',
|
16
|
+
@config[:vip][:interface] + '-vip',
|
17
|
+
'>/dev/null 2>&1'
|
18
|
+
]
|
19
|
+
leader ? cmd[2] = 'add' : cmd[2] = 'delete'
|
20
|
+
debug "#{cmd.join(' ')}"
|
21
|
+
if system(cmd.join(' '))
|
22
|
+
return true
|
23
|
+
else
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# send gratuitous ARP to the network
|
29
|
+
def vip_update_arp!
|
30
|
+
cmd = [ arping, '-U', '-q',
|
31
|
+
'-c', @config[:arping][:count],
|
32
|
+
'-I', @config[:vip][:interface],
|
33
|
+
@config[:vip][:ip] ]
|
34
|
+
debug "#{cmd.join(' ')}"
|
35
|
+
if system(cmd.join(' '))
|
36
|
+
return true
|
37
|
+
else
|
38
|
+
return false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# check whether VIP is assigned to me
|
43
|
+
def got_vip?
|
44
|
+
Socket.ip_address_list.map(){|a| a.ip_address }.member?(@config[:vip][:ip])
|
45
|
+
end
|
46
|
+
|
47
|
+
# check reachability of VIP by ICMP echo
|
48
|
+
def vip_alive?(icmp)
|
49
|
+
(1..@config[:icmp][:count]).each { return true if icmp.ping }
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
|
53
|
+
# check whether the IP is registered anywhere
|
54
|
+
def vip_dup?
|
55
|
+
cmd_arp = [ arp, '-d', @config[:vip][:ip], '>/dev/null 2>&1' ]
|
56
|
+
cmd_arping = [ arping, '-D', '-q',
|
57
|
+
'-c', @config[:arping][:count],
|
58
|
+
'-w', @config[:arping][:wait],
|
59
|
+
'-I', @config[:vip][:interface],
|
60
|
+
@config[:vip][:ip] ]
|
61
|
+
debug "#{cmd_arp.join(' ')}"
|
62
|
+
system(cmd_arp.join(' '))
|
63
|
+
debug "#{cmd_arping.join(' ')}"
|
64
|
+
if system(cmd_arping.join(' '))
|
65
|
+
return false
|
66
|
+
else
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'json'
|
3
|
+
require 'etcd-tools'
|
4
|
+
require 'port-authority/util/config'
|
5
|
+
require 'port-authority/util/logger'
|
6
|
+
require 'port-authority/util/helpers'
|
7
|
+
|
8
|
+
module PortAuthority
|
9
|
+
module Watchdog
|
10
|
+
class Init
|
11
|
+
|
12
|
+
include PortAuthority::Util::Config
|
13
|
+
include PortAuthority::Util::Logger
|
14
|
+
include PortAuthority::Util::Helpers
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@config = { debug: false }
|
18
|
+
@config = config
|
19
|
+
@exit = false
|
20
|
+
@exit_sigs = ['INT', 'TERM']
|
21
|
+
@exit_sigs.each { |sig| Signal.trap(sig) { @exit = true } }
|
22
|
+
Signal.trap('USR1') { @config[:debug] = false }
|
23
|
+
Signal.trap('USR2') { @config[:debug] = true }
|
24
|
+
Signal.trap('HUP') { @config = config }
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup(proc_name, nice = -20)
|
28
|
+
if RUBY_VERSION >= '2.1'
|
29
|
+
Process.setproctitle(proc_name)
|
30
|
+
else
|
31
|
+
$0 = proc_name
|
32
|
+
end
|
33
|
+
Process.setpriority(Process::PRIO_PROCESS, 0, nice)
|
34
|
+
# FIXME: Process.daemon ...
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
require 'port-authority/util/vip'
|
3
|
+
require 'port-authority/util/etcd'
|
4
|
+
require 'port-authority/util/loadbalancer'
|
5
|
+
require 'port-authority/watchdog/init'
|
6
|
+
require 'port-authority/watchdog/threads/icmp'
|
7
|
+
require 'port-authority/watchdog/threads/swarm'
|
8
|
+
|
9
|
+
module PortAuthority
|
10
|
+
module Watchdog
|
11
|
+
class Manager < PortAuthority::Watchdog::Init
|
12
|
+
|
13
|
+
include PortAuthority::Util::Etcd
|
14
|
+
include PortAuthority::Util::Vip
|
15
|
+
include PortAuthority::Util::LoadBalancer
|
16
|
+
include PortAuthority::Watchdog::Threads
|
17
|
+
|
18
|
+
def run
|
19
|
+
# exit if not root
|
20
|
+
if Process.euid != 0
|
21
|
+
$stderr.puts 'Must run under root user!'
|
22
|
+
exit! 1
|
23
|
+
end
|
24
|
+
|
25
|
+
# set process name and nice level (default: -20)
|
26
|
+
setup 'pa-master-watchdog'
|
27
|
+
|
28
|
+
# prepare semaphores
|
29
|
+
@semaphore = {
|
30
|
+
log: Mutex.new,
|
31
|
+
swarm: Mutex.new,
|
32
|
+
icmp: Mutex.new
|
33
|
+
}
|
34
|
+
|
35
|
+
# prepare threads
|
36
|
+
@thread = {
|
37
|
+
icmp: thread_icmp,
|
38
|
+
etcd: thread_swarm,
|
39
|
+
}
|
40
|
+
|
41
|
+
# prepare status vars
|
42
|
+
@status_swarm = false
|
43
|
+
@status_icmp = false
|
44
|
+
|
45
|
+
# start threads
|
46
|
+
@thread.each_value(&:run)
|
47
|
+
|
48
|
+
# wait for threads to make sure they gather something
|
49
|
+
debug 'waiting for threads to gather something...'
|
50
|
+
sleep @config[:vip][:interval]
|
51
|
+
first_cycle = true
|
52
|
+
|
53
|
+
# main loop
|
54
|
+
while !@exit do
|
55
|
+
# initialize local state vars on first iteration
|
56
|
+
status_swarm = status_icmp = false if first_cycle
|
57
|
+
|
58
|
+
# iteration interval
|
59
|
+
sleep @config[:vip][:interval]
|
60
|
+
|
61
|
+
# sync state to local variables
|
62
|
+
@semaphore[:icmp].synchronize { status_icmp = @status_icmp }
|
63
|
+
@semaphore[:swarm].synchronize { status_swarm = @status_swarm }
|
64
|
+
|
65
|
+
# the logic (should be self-explanatory ;))
|
66
|
+
if am_i_leader?
|
67
|
+
if got_vip?
|
68
|
+
debug 'i am the leader with VIP, that is OK'
|
69
|
+
else
|
70
|
+
info 'i am the leader without VIP, checking whether it is free'
|
71
|
+
if status_icmp
|
72
|
+
info 'VIP is still up! (ICMP)'
|
73
|
+
# FIXME: notify by sensu client socket
|
74
|
+
else
|
75
|
+
info 'VIP is unreachable by ICMP, checking for duplicates on L2'
|
76
|
+
if vip_dup?
|
77
|
+
info 'VIP is still assigned! (ARP)'
|
78
|
+
# FIXME: notify by sensu client socket
|
79
|
+
else
|
80
|
+
info 'VIP is free :) assigning'
|
81
|
+
vip_handle! status_swarm
|
82
|
+
info 'updating other hosts about change'
|
83
|
+
vip_update_arp!
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
if lb_up?
|
88
|
+
debug 'i am the leader and load-balancer is up, that is OK'
|
89
|
+
else
|
90
|
+
info 'i am the leader and load-balancer is down, starting'
|
91
|
+
lb_start!
|
92
|
+
end
|
93
|
+
else
|
94
|
+
if got_vip?
|
95
|
+
info 'i got VIP and should not, removing'
|
96
|
+
vip_handle! status_swarm
|
97
|
+
info 'updating other hosts about change'
|
98
|
+
vip_update_arp!
|
99
|
+
else
|
100
|
+
debug 'i am not the leader and i do not have the VIP, that is OK'
|
101
|
+
end
|
102
|
+
if lb_up?
|
103
|
+
info 'i am not the leader and load-balancer is up, stopping'
|
104
|
+
lb_stop!
|
105
|
+
else
|
106
|
+
debug 'i am not the leader and load-balancer is down, that is OK'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# short report on first cycle
|
111
|
+
if first_cycle
|
112
|
+
info "i #{status_swarm ? 'AM' : 'am NOT'} the leader"
|
113
|
+
info "i #{got_vip? ? 'DO' : 'do NOT'} have the VIP"
|
114
|
+
info "i #{status_icmp ? 'CAN' : 'CANNOT'} see the VIP"
|
115
|
+
info "i #{status_haproxy ? 'CAN' : 'CANNOT'} see the VIP"
|
116
|
+
first_cycle = false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# this is triggerred on exit
|
121
|
+
info 'SIGTERM received'
|
122
|
+
info 'waiting for threads to finish...'
|
123
|
+
@thread.each_value(&:join)
|
124
|
+
|
125
|
+
# remove VIP on shutdown
|
126
|
+
if got_vip?
|
127
|
+
info 'removing VIP'
|
128
|
+
vip_handle! false
|
129
|
+
vip_update_arp!
|
130
|
+
end
|
131
|
+
|
132
|
+
# stop LB on shutdown
|
133
|
+
if lb_up?
|
134
|
+
info 'stopping load-balancer'
|
135
|
+
lb_stop!
|
136
|
+
end
|
137
|
+
|
138
|
+
info 'exiting...'
|
139
|
+
exit 0
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'net/ping'
|
2
|
+
|
3
|
+
module PortAuthority
|
4
|
+
module Watchdog
|
5
|
+
module Threads
|
6
|
+
def thread_icmp
|
7
|
+
Thread.new do
|
8
|
+
debug 'starting ICMP thread...'
|
9
|
+
icmp = Net::Ping::ICMP.new(@config[:vip][:ip])
|
10
|
+
while !@exit do
|
11
|
+
debug 'checking state by ICMP echo'
|
12
|
+
status = vip_alive? icmp
|
13
|
+
@semaphore[:icmp].synchronize { @status_icmp = status }
|
14
|
+
debug "VIP is #{status ? 'alive' : 'down' } according to ICMP"
|
15
|
+
sleep @config[:icmp][:interval]
|
16
|
+
end
|
17
|
+
info 'ending ICMP thread...'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module PortAuthority
|
2
|
+
module Watchdog
|
3
|
+
module Threads
|
4
|
+
def thread_swarm
|
5
|
+
Thread.new do
|
6
|
+
debug '<swarm> starting thread...'
|
7
|
+
etcd = etcd_connect!
|
8
|
+
while !@exit do
|
9
|
+
debug '<swarm> checking etcd state'
|
10
|
+
status = am_i_leader? etcd
|
11
|
+
@semaphore[:swarm].synchronize { @status_swarm = status }
|
12
|
+
debug "<swarm> i am #{status ? 'the leader' : 'not the leader' }"
|
13
|
+
sleep @config[:etcd][:interval]
|
14
|
+
end
|
15
|
+
info '<swarm> ending thread...'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: port-authority
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Radek 'blufor' Slavicinsky
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: etcd
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.3'
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.3.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.3'
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.3.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: etcd-tools
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ~>
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.2'
|
40
|
+
- - ! '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.2.9
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ~>
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.2'
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.2.9
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: net-ping
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.7'
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.7.8
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.7'
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.7.8
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: docker-api
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ~>
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '1.0'
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.25.0
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
90
|
+
- - ! '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.25.0
|
93
|
+
description: Tools for PortAuthority
|
94
|
+
email: radek.slavicinsky@gmail.com
|
95
|
+
executables:
|
96
|
+
- pa-master-watchdog
|
97
|
+
extensions: []
|
98
|
+
extra_rdoc_files: []
|
99
|
+
files:
|
100
|
+
- bin/pa-master-watchdog
|
101
|
+
- lib/port-authority.rb
|
102
|
+
- lib/port-authority/util/config.rb
|
103
|
+
- lib/port-authority/util/etcd.rb
|
104
|
+
- lib/port-authority/util/helpers.rb
|
105
|
+
- lib/port-authority/util/loadbalancer.rb
|
106
|
+
- lib/port-authority/util/logger.rb
|
107
|
+
- lib/port-authority/util/vip.rb
|
108
|
+
- lib/port-authority/watchdog/init.rb
|
109
|
+
- lib/port-authority/watchdog/master.rb
|
110
|
+
- lib/port-authority/watchdog/threads/icmp.rb
|
111
|
+
- lib/port-authority/watchdog/threads/swarm.rb
|
112
|
+
homepage: https://github.com/blufor/etcd-tools
|
113
|
+
licenses:
|
114
|
+
- GPLv2
|
115
|
+
metadata: {}
|
116
|
+
post_install_message:
|
117
|
+
rdoc_options: []
|
118
|
+
require_paths:
|
119
|
+
- lib
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.9.3
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
requirements: []
|
131
|
+
rubyforge_project:
|
132
|
+
rubygems_version: 2.4.3
|
133
|
+
signing_key:
|
134
|
+
specification_version: 4
|
135
|
+
summary: Port Authority
|
136
|
+
test_files: []
|