Page Menu
Home
VyOS Platform
Search
Configure Global Search
Log In
Files
F118309930
keepalived.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
keepalived.py
View Options
# Copyright 2018 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import
re
import
os
import
signal
import
json
import
vyos.util
pid_file
=
'/var/run/keepalived.pid'
state_file
=
'/tmp/keepalived.data'
stats_file
=
'/tmp/keepalived.stats'
json_file
=
'/tmp/keepalived.json'
state_dir
=
'/var/run/vyos/vrrp/'
def
vrrp_running
():
if
not
os
.
path
.
exists
(
vyos
.
keepalived
.
pid_file
)
\
or
not
vyos
.
util
.
process_running
(
vyos
.
keepalived
.
pid_file
):
return
False
else
:
return
True
def
keepalived_running
():
return
vyos
.
util
.
process_running
(
pid_file
)
def
force_state_data_dump
():
pid
=
vyos
.
util
.
read_file
(
pid_file
)
os
.
kill
(
int
(
pid
),
signal
.
SIGUSR1
)
def
force_stats_dump
():
pid
=
vyos
.
util
.
read_file
(
pid_file
)
os
.
kill
(
int
(
pid
),
signal
.
SIGUSR2
)
def
force_json_dump
():
pid
=
vyos
.
util
.
read_file
(
pid_file
)
os
.
kill
(
int
(
pid
),
signal
.
SIGRTMIN
+
2
)
def
get_json_data
():
with
open
(
json_file
,
'r'
)
as
f
:
j
=
json
.
load
(
f
)
return
j
def
get_statistics
():
return
vyos
.
util
.
read_file
(
stats_file
)
def
get_state_data
():
return
vyos
.
util
.
read_file
(
state_file
)
def
decode_state
(
code
):
state
=
None
if
code
==
0
:
state
=
"INIT"
elif
code
==
1
:
state
=
"BACKUP"
elif
code
==
2
:
state
=
"MASTER"
elif
code
==
3
:
state
=
"FAULT"
else
:
state
=
"UNKNOWN"
return
state
## The functions are mainly for transition script wrappers
## to compensate for the fact that keepalived doesn't keep persistent
## state between reloads.
def
get_old_state
(
group
):
file
=
os
.
path
.
join
(
state_dir
,
"{0}.state"
.
format
(
group
))
if
os
.
path
.
exists
(
file
):
with
open
(
file
,
'r'
)
as
f
:
data
=
f
.
read
()
.
strip
()
return
data
else
:
return
None
def
save_state
(
group
,
state
):
if
not
os
.
path
.
exists
(
state_dir
):
os
.
makedirs
(
state_dir
)
file
=
os
.
path
.
join
(
state_dir
,
"{0}.state"
.
format
(
group
))
with
open
(
file
,
'w'
)
as
f
:
f
.
write
(
state
)
## These functions are for the old, and hopefully obsolete plaintext
## (non machine-readable) data format introduced by Vyatta back in the days
## They are kept here just in case, if JSON output option turns out or becomes
## insufficient.
def
read_state_data
():
with
open
(
state_file
,
'r'
)
as
f
:
lines
=
f
.
readlines
()
return
lines
def
parse_keepalived_data
(
data_lines
):
vrrp_groups
=
{}
# Scratch variable
group_name
=
None
# Sadly there is no explicit end marker in that format, so we have
# only two states, one before the first VRRP instance is encountered
# and one after an instance/"group" was encountered
# We'll set group_name once the first group is encountered,
# and assume we are inside a group if it's set afterwards
#
# It may not be necessary since the keywords found inside groups and before
# the VRRP Topology section seem to have no intersection,
# but better safe than sorry.
for
line
in
data_lines
:
if
re
.
match
(
r'^\s*VRRP Instance'
,
line
,
re
.
IGNORECASE
):
# Example: "VRRP Instance = Foo"
name
=
re
.
match
(
r'^\s*VRRP Instance\s+=\s+(.*)$'
,
line
,
re
.
IGNORECASE
)
.
groups
()[
0
]
.
strip
()
group_name
=
name
vrrp_groups
[
name
]
=
{}
elif
re
.
match
(
r'^\s*State'
,
line
,
re
.
IGNORECASE
)
and
group_name
:
# Example: " State = MASTER"
group_state
=
re
.
match
(
r'^\s*State\s+=\s+(.*)$'
,
line
,
re
.
IGNORECASE
)
.
groups
()[
0
]
.
strip
()
vrrp_groups
[
group_name
][
"state"
]
=
group_state
elif
re
.
match
(
r'^\s*Last transition'
,
line
,
re
.
IGNORECASE
)
and
group_name
:
# Example: " Last transition = 1532043820 (Thu Jul 19 23:43:40 2018)"
trans_time
=
re
.
match
(
r'^\s*Last transition\s+=\s+(\d+)\s'
,
line
,
re
.
IGNORECASE
)
.
groups
()[
0
]
vrrp_groups
[
group_name
][
"last_transition"
]
=
trans_time
elif
re
.
match
(
r'^\s*Interface'
,
line
,
re
.
IGNORECASE
)
and
group_name
:
# Example: " Interface = eth0.30"
interface
=
re
.
match
(
r'\s*Interface\s+=\s+(.*)$'
,
line
,
re
.
IGNORECASE
)
.
groups
()[
0
]
.
strip
()
vrrp_groups
[
group_name
][
"interface"
]
=
interface
elif
re
.
match
(
r'^\s*Virtual Router ID'
,
line
,
re
.
IGNORECASE
)
and
group_name
:
# Example: " Virtual Router ID = 14"
vrid
=
re
.
match
(
r'^\s*Virtual Router ID\s+=\s+(.*)$'
,
line
,
re
.
IGNORECASE
)
.
groups
()[
0
]
.
strip
()
vrrp_groups
[
group_name
][
"vrid"
]
=
vrid
elif
re
.
match
(
r'^\s*------< Interfaces'
,
line
,
re
.
IGNORECASE
):
# Interfaces section appears to always be present,
# and there's nothing of interest for us below that section,
# so we use it as an end of input marker
break
return
vrrp_groups
File Metadata
Details
Attached
Mime Type
text/x-script.python
Expires
Sat, Oct 17, 12:53 AM (1 d, 12 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4354565
Default Alt Text
keepalived.py (5 KB)
Attached To
Mode
rVYOSONEX vyos-1x
Attached
Detach File
Event Timeline
Log In to Comment