Skip to content

Commit fa18da9

Browse files
committed
f-93: Fix one-failover issues on Alpine 3.20
- Always run iptables service - Refactor one-failover logic to fix regressions after Alpine update - Improve one-failover performance - Add "standby" command for keepalived - Code cleanups
1 parent 4a3c9da commit fa18da9

File tree

14 files changed

+122
-100
lines changed

14 files changed

+122
-100
lines changed

appliances/VRouter/DNS/main.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,8 @@ def install(initdir: '/etc/init.d')
7070
install -o unbound -g unbound -m u=rwx,go=rx -d /var/log/unbound/
7171
SCRIPT
7272

73-
file "#{initdir}/one-dns", <<~SERVICE, mode: 'u=rwx,g=rx,o='
73+
file "#{initdir}/one-dns", <<~SERVICE, mode: 'u=rwx,go=rx'
7474
#!/sbin/openrc-run
75-
7675
source /run/one-context/one_env
7776
7877
command="/usr/bin/ruby"

appliances/VRouter/Failover/execute.rb

Lines changed: 77 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,35 @@ module Failover
99
VROUTER_ID = env :VROUTER_ID, nil
1010

1111
SERVICES = {
12-
'one-router4' => { _ENABLED: 'ONEAPP_VNF_ROUTER4_ENABLED',
13-
fallback: VROUTER_ID.nil? ? 'NO' : 'YES' },
12+
'one-router4' => { _ENABLED: 'ONEAPP_VNF_ROUTER4_ENABLED', fallback: VROUTER_ID.nil? ? 'NO' : 'YES' },
1413

15-
'one-nat4' => { _ENABLED: 'ONEAPP_VNF_NAT4_ENABLED',
16-
fallback: 'NO' },
14+
'one-nat4' => { _ENABLED: 'ONEAPP_VNF_NAT4_ENABLED' },
1715

18-
'one-lvs' => { _ENABLED: 'ONEAPP_VNF_LB_ENABLED',
19-
fallback: 'NO' },
16+
'one-lvs' => { _ENABLED: 'ONEAPP_VNF_LB_ENABLED' },
2017

21-
'one-haproxy' => { _ENABLED: 'ONEAPP_VNF_HAPROXY_ENABLED',
22-
fallback: 'NO' },
18+
'one-haproxy' => { _ENABLED: 'ONEAPP_VNF_HAPROXY_ENABLED' },
19+
'haproxy' => { _ENABLED: 'ONEAPP_VNF_HAPROXY_ENABLED', dependency: true },
2320

24-
'one-sdnat4' => { _ENABLED: 'ONEAPP_VNF_SDNAT4_ENABLED',
25-
fallback: 'NO' },
21+
'one-sdnat4' => { _ENABLED: 'ONEAPP_VNF_SDNAT4_ENABLED' },
2622

27-
'one-dns' => { _ENABLED: 'ONEAPP_VNF_DNS_ENABLED',
28-
fallback: 'NO' },
23+
'one-dns' => { _ENABLED: 'ONEAPP_VNF_DNS_ENABLED' },
24+
'unbound' => { _ENABLED: 'ONEAPP_VNF_DNS_ENABLED', dependency: true },
2925

30-
'one-dhcp4v2' => { _ENABLED: 'ONEAPP_VNF_DHCP4_ENABLED',
31-
fallback: 'NO' },
26+
'one-dhcp4v2' => { _ENABLED: 'ONEAPP_VNF_DHCP4_ENABLED' },
27+
'coredhcp' => { _ENABLED: 'ONEAPP_VNF_DHCP4_ENABLED', dependency: true },
3228

33-
'one-wg' => { _ENABLED: 'ONEAPP_VNF_WG_ENABLED',
34-
fallback: 'NO' }
29+
'one-wg' => { _ENABLED: 'ONEAPP_VNF_WG_ENABLED' }
3530
}
3631

3732
FIFO_PATH = '/run/keepalived/vrrp_notify_fifo.sock'
3833
STATE_PATH = '/run/one-failover.state'
3934

4035
STATE_TO_DIRECTION = {
4136
'BACKUP' => :down,
42-
'DELETED' => :down,
43-
'FAULT' => :down,
37+
'DELETED' => :stay,
38+
'FAULT' => :stay,
4439
'MASTER' => :up,
45-
'STOP' => :down,
40+
'STOP' => :stay,
4641
nil => :stay
4742
}
4843

@@ -62,7 +57,11 @@ def to_task(event)
6257
direction = :stay
6358
ignored = true
6459
else
65-
if STATE_TO_DIRECTION[event[:state]] == STATE_TO_DIRECTION[state[:state]]
60+
case
61+
when event[:state] == 'BACKUP'
62+
direction = STATE_TO_DIRECTION['BACKUP']
63+
ignored = false
64+
when STATE_TO_DIRECTION[event[:state]] == STATE_TO_DIRECTION[state[:state]]
6665
direction = :stay
6766
ignored = false
6867
else
@@ -100,13 +99,12 @@ def process_events(fifo_path = FIFO_PATH)
10099
f.each do |line|
101100
event = to_event line
102101
task = to_task event
103-
msg :info, task
102+
msg :debug, task
104103
method(task[:direction]).call
105104
end
106105
end
107106
rescue StandardError => e
108107
msg :error, e.full_message
109-
110108
# NOTE: We always disable all services on fatal errors
111109
# to avoid any potential conflicts.
112110
down
@@ -117,70 +115,88 @@ def process_events(fifo_path = FIFO_PATH)
117115
end
118116
end
119117

120-
def execute
121-
msg :info, 'Failover::execute'
122-
process_events
123-
end
124-
125-
def stay
126-
msg :debug, :STAY
127-
end
128-
129-
def up
130-
msg :debug, :UP
131-
132-
load_env
133-
118+
def wait_ready(role = :master)
134119
# Give one-context 30 seconds to fully start..
135120
6.times do
136121
bash 'rc-service one-context status', terminate: false
137122
break
138-
rescue RuntimeError
123+
rescue RuntimeError => e
124+
msg :error, e.full_message
139125
sleep 5
140126
end.then do |result|
141-
unless result.nil?
142-
msg :error, 'one-context not ready!'
143-
return
144-
end
127+
msg :error, 'one-context not ready!' unless result.nil?
145128
end
146-
147-
# Give keepalived 30 seconds to setup VIPs..
129+
# Give keepalived 30 seconds to fully start..
148130
6.times do
149-
bash 'rc-service keepalived ready', terminate: false
131+
bash "rc-service keepalived #{role == :master ? 'ready' : 'standby'}", terminate: false
150132
break
151-
rescue RuntimeError
133+
rescue RuntimeError => e
134+
msg :error, e.full_message
152135
sleep 5
153136
end.then do |result|
154-
unless result.nil?
155-
msg :error, 'keepalived not ready!'
156-
return
157-
end
137+
msg :error, 'keepalived not ready!' unless result.nil?
158138
end
139+
end
140+
141+
def execute
142+
msg :info, 'Failover::execute'
143+
process_events
144+
end
145+
146+
def stay
147+
msg :debug, ":STAY (pid = #{Process.pid})"
148+
end
149+
150+
def up
151+
msg :debug, ":UP (pid = #{Process.pid})"
152+
153+
wait_ready :master
154+
155+
load_env
159156

160157
SERVICES.each do |service, settings|
161-
enabled = env settings[:_ENABLED], settings[:fallback]
158+
if env settings[:_ENABLED], (settings[:fallback] || 'NO')
159+
next if settings[:dependency]
162160

163-
msg :debug, "#{service}(#{enabled ? ':enabled' : ':disabled'})"
161+
msg :info, "#{service}(:enabled)"
164162

165-
if enabled
166-
bash "rc-service #{service} restart ||:", terminate: false
163+
puts bash "rc-service #{service} restart ||:", terminate: false
167164
else
168-
bash "rc-service #{service} stop ||:" , terminate: false
169-
end
165+
msg :info, "#{service}(:disabled)"
170166

171-
sleep 1
167+
puts bash "rc-service #{service} stop ||:", terminate: false
168+
end
172169
end
170+
171+
puts bash 'rc-update -v -u ||:', terminate: false
173172
end
174173

175174
def down
176-
msg :debug, :DOWN
175+
msg :debug, ":DOWN (pid = #{Process.pid})"
176+
177+
wait_ready :standby
178+
179+
12.times do |attempt|
180+
services = bash 'rc-status --nocolor --format ini --servicelist', terminate: false
177181

178-
SERVICES.each do |service, _|
179-
msg :debug, "#{service}(:disabled)"
182+
stopped = services.lines.map(&:split)
183+
.select { |_, _, s| s == 'stopped' }
184+
.map(&:first)
180185

181-
bash "rc-service #{service} stop ||:", terminate: false
186+
break if (running = SERVICES.keys - stopped).empty?
182187

183-
sleep 1
188+
running.each do |service|
189+
msg :info, "#{service}(:disabled)"
190+
191+
puts bash "rc-service #{service} stop ||:", terminate: false
192+
end
193+
194+
puts bash 'rc-update -v -u ||:', terminate: false
195+
rescue RuntimeError => e
196+
msg :error, e.full_message
197+
sleep 5
198+
end.then do |result|
199+
msg :error, 'could not stop services!' unless result.nil?
184200
end
185201
end
186202
end

appliances/VRouter/Failover/main.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,22 @@ def install(initdir: '/etc/init.d')
1313

1414
puts bash 'apk --no-cache add ruby'
1515

16-
file "#{initdir}/one-failover", <<~SERVICE, mode: 'u=rwx,g=rx,o='
16+
file "#{initdir}/one-failover", <<~SERVICE, mode: 'u=rwx,go=rx'
1717
#!/sbin/openrc-run
18-
1918
source /run/one-context/one_env
2019
2120
command="/usr/bin/ruby"
2221
command_args="-r /etc/one-appliance/lib/helpers.rb -r #{__FILE__} -e Service::Failover.execute"
2322
24-
command_background="yes"
23+
command_background="YES"
2524
pidfile="/run/$RC_SVCNAME.pid"
2625
2726
output_log="/var/log/one-appliance/one-failover.log"
28-
error_log="/var/log/one-appliance/one-failover.log"
27+
error_log="/var/log/one-appliance/one-failover.err"
2928
3029
depend() {
3130
need keepalived
32-
after net
31+
after net firewall
3332
}
3433
SERVICE
3534

appliances/VRouter/HAProxy/main.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,21 @@ def install(initdir: '/etc/init.d')
2121

2222
puts bash 'apk --no-cache add haproxy ruby'
2323

24-
file "#{initdir}/one-haproxy", <<~SERVICE, mode: 'u=rwx,g=rx,o='
24+
file "#{initdir}/one-haproxy", <<~SERVICE, mode: 'u=rwx,go=rx'
2525
#!/sbin/openrc-run
26-
2726
source /run/one-context/one_env
2827
2928
command="/usr/bin/ruby"
3029
command_args="-r /etc/one-appliance/lib/helpers.rb -r #{__FILE__} -e Service::HAProxy.execute"
3130
32-
command_background="yes"
31+
command_background="YES"
3332
pidfile="/run/$RC_SVCNAME.pid"
3433
3534
output_log="/var/log/one-appliance/one-haproxy.log"
3635
error_log="/var/log/one-appliance/one-haproxy.log"
3736
3837
depend() {
39-
after net keepalived
38+
after net firewall keepalived
4039
}
4140
4241
start_pre() {

appliances/VRouter/Keepalived/main.rb

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def install(initdir: '/etc/init.d')
5858

5959
script = File.open("#{initdir}/keepalived").each_with_object([]) do |line, acc|
6060
if line =~ /^extra_started_commands="(.*)"$/
61-
acc << %{extra_started_commands="#{$1} ready"\n}
61+
acc << %{extra_started_commands="#{$1} ready standby"\n}
6262
else
6363
acc << line
6464
end
@@ -68,9 +68,16 @@ def install(initdir: '/etc/init.d')
6868
#{script}
6969
7070
ready() {
71-
ebegin "Checking readiness"
71+
ebegin "Checking readiness (:master)"
7272
source /run/one-context/one_env
73-
/usr/bin/ruby -r #{__FILE__} -e Service::Keepalived.ready
73+
/usr/bin/ruby -r #{__FILE__} -e 'Service::Keepalived.ready(:master)'
74+
eend $?
75+
}
76+
77+
standby() {
78+
ebegin "Checking readiness (:standby)"
79+
source /run/one-context/one_env
80+
/usr/bin/ruby -r #{__FILE__} -e 'Service::Keepalived.ready(:standby)'
7481
eend $?
7582
}
7683
SCRIPT
@@ -193,7 +200,7 @@ def bootstrap
193200
msg :info, 'Keepalived::bootstrap'
194201
end
195202

196-
def ready
203+
def ready(role = :master)
197204
detect_vips.each do |nic, vips|
198205
vips = vips.values.map do |vip|
199206
vip.split(%[/])[0] # remove the CIDR "prefixlen" if present
@@ -203,7 +210,7 @@ def ready
203210
acc << item['local'] unless item['local'].nil?
204211
end
205212

206-
if (vips & addrs) != vips
213+
if role == :master ? (vips & addrs) != vips : (vips & addrs) == vips
207214
msg :debug, { nic => { vips: vips, addrs: addrs, ready: false } }
208215
exit 1
209216
end

appliances/VRouter/LVS/main.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,21 @@ def install(initdir: '/etc/init.d')
2222

2323
puts bash 'apk --no-cache add ipvsadm ruby'
2424

25-
file "#{initdir}/one-lvs", <<~SERVICE, mode: 'u=rwx,g=rx,o='
25+
file "#{initdir}/one-lvs", <<~SERVICE, mode: 'u=rwx,go=rx'
2626
#!/sbin/openrc-run
27-
2827
source /run/one-context/one_env
2928
3029
command="/usr/bin/ruby"
3130
command_args="-r /etc/one-appliance/lib/helpers.rb -r #{__FILE__} -e Service::LVS.execute"
3231
33-
command_background="yes"
32+
command_background="YES"
3433
pidfile="/run/$RC_SVCNAME.pid"
3534
3635
output_log="/var/log/one-appliance/one-lvs.log"
3736
error_log="/var/log/one-appliance/one-lvs.log"
3837
3938
depend() {
40-
after net keepalived
39+
after net firewall keepalived
4140
}
4241
4342
stop_post() {

appliances/VRouter/NAT4/execute.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def execute
5555
IPTABLES
5656
end
5757

58-
toggle [:save, :start, :reload]
58+
toggle [:save, :reload]
5959
end
6060

6161
def cleanup

appliances/VRouter/NAT4/main.rb

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,8 @@ def install(initdir: '/etc/init.d')
6464

6565
puts bash 'apk --no-cache add iptables-openrc ruby'
6666

67-
file "#{initdir}/one-nat4", <<~SERVICE, mode: 'u=rwx,g=rx,o='
67+
file "#{initdir}/one-nat4", <<~SERVICE, mode: 'u=rwx,go=rx'
6868
#!/sbin/openrc-run
69-
7069
source /run/one-context/one_env
7170
7271
command="/usr/bin/ruby"
@@ -112,8 +111,6 @@ def toggle(operations)
112111
puts bash 'rc-update del one-nat4 default ||:'
113112
when :update
114113
puts bash 'rc-update -u'
115-
when :start
116-
puts bash 'rc-service iptables start'
117114
else
118115
puts bash "rc-service one-nat4 #{op.to_s}"
119116
end

appliances/VRouter/Router4/main.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ def install(initdir: '/etc/init.d')
2020

2121
puts bash 'apk --no-cache add procps ruby'
2222

23-
file "#{initdir}/one-router4", <<~SERVICE, mode: 'u=rwx,g=rx,o='
23+
file "#{initdir}/one-router4", <<~SERVICE, mode: 'u=rwx,go=rx'
2424
#!/sbin/openrc-run
25-
2625
source /run/one-context/one_env
2726
2827
command="/usr/bin/ruby"

appliances/VRouter/SDNAT4/execute.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def execute
101101
iptables -t nat -C PREROUTING -j DNAT4 || iptables -t nat -I PREROUTING 1 -j DNAT4
102102
IPTABLES
103103

104-
toggle [:save, :start]
104+
toggle [:save, :reload]
105105

106106
loop do
107107
unless (vnets = get_vrouter_vnets).empty?

0 commit comments

Comments
 (0)