summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriyEshenko <dmitriy.eshenko@vyos.io>2020-01-14 21:24:42 +0000
committerDmitriyEshenko <dmitriy.eshenko@vyos.io>2020-01-14 21:24:42 +0000
commit187d34b82f80c9c251c81cf9b96aa8d52e9f21e2 (patch)
treed73a378b2292f53465ae4021bb012ee31b7fcde8
parentf7c3e427c19a0137f76a3291c888a21239b3a0db (diff)
downloadvyos-1x-187d34b82f80c9c251c81cf9b96aa8d52e9f21e2.tar.gz
vyos-1x-187d34b82f80c9c251c81cf9b96aa8d52e9f21e2.zip
vrrp: T1884: Keep transition-script native behaviour and implement transaction-script 'stop'
-rw-r--r--interface-definitions/vrrp.xml.in8
-rw-r--r--python/vyos/keepalived.py31
-rwxr-xr-xsrc/conf_mode/vrrp.py6
-rwxr-xr-xsrc/op_mode/vrrp.py3
-rwxr-xr-xsrc/system/vrrp-script-wrapper.py49
5 files changed, 42 insertions, 55 deletions
diff --git a/interface-definitions/vrrp.xml.in b/interface-definitions/vrrp.xml.in
index 2884ef613..89d22f79f 100644
--- a/interface-definitions/vrrp.xml.in
+++ b/interface-definitions/vrrp.xml.in
@@ -197,6 +197,14 @@
</constraint>
</properties>
</leafNode>
+ <leafNode name="stop">
+ <properties>
+ <help>Script to run on VRRP state transition to stop</help>
+ <constraint>
+ <validator name="script"/>
+ </constraint>
+ </properties>
+ </leafNode>
</children>
</node>
<leafNode name="virtual-address">
diff --git a/python/vyos/keepalived.py b/python/vyos/keepalived.py
index 4114aa736..3984ca792 100644
--- a/python/vyos/keepalived.py
+++ b/python/vyos/keepalived.py
@@ -26,8 +26,6 @@ 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):
@@ -38,6 +36,15 @@ def vrrp_running():
def keepalived_running():
return vyos.util.process_running(pid_file)
+## Clear VRRP data after showing
+def remove_vrrp_data(data_file):
+ if data_file == "json" and os.path.exists(json_file):
+ os.remove(json_file)
+ elif data_file == "stats" and os.path.exists(stats_file):
+ os.remove(stats_file)
+ elif data_file == "state" and os.path.exists(state_file):
+ os.remove(state_file)
+
def force_state_data_dump():
pid = vyos.util.read_file(pid_file)
os.kill(int(pid), signal.SIGUSR1)
@@ -76,26 +83,6 @@ def decode_state(code):
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
diff --git a/src/conf_mode/vrrp.py b/src/conf_mode/vrrp.py
index d31be4cfb..1d8477769 100755
--- a/src/conf_mode/vrrp.py
+++ b/src/conf_mode/vrrp.py
@@ -37,6 +37,7 @@ config_tmpl = """
global_defs {
dynamic_interfaces
+ script_user root
}
{% for group in groups -%}
@@ -117,6 +118,10 @@ vrrp_instance {{ group.name }} {
{% if group.fault_script -%}
notify_fault "/usr/libexec/vyos/system/vrrp-script-wrapper.py --state fault --group {{ group.name }} --interface {{ group.interface }} {{ group.fault_script }}"
{% endif -%}
+
+ {% if group.stop_script -%}
+ notify_stop "/usr/libexec/vyos/system/vrrp-script-wrapper.py --state stop --group {{ group.name }} --interface {{ group.interface }} {{ group.stop_script }}"
+ {% endif -%}
}
{% endfor -%}
@@ -178,6 +183,7 @@ def get_config():
group["master_script"] = config.return_value("transition-script master")
group["backup_script"] = config.return_value("transition-script backup")
group["fault_script"] = config.return_value("transition-script fault")
+ group["stop_script"] = config.return_value("transition-script stop")
if config.exists("no-preempt"):
group["preempt"] = False
diff --git a/src/op_mode/vrrp.py b/src/op_mode/vrrp.py
index 54e1bfb57..8d1369823 100755
--- a/src/op_mode/vrrp.py
+++ b/src/op_mode/vrrp.py
@@ -32,6 +32,7 @@ def print_summary():
# Replace with inotify or similar if it proves problematic
time.sleep(0.2)
json_data = vyos.keepalived.get_json_data()
+ vyos.keepalived.remove_vrrp_data("json")
except:
print("VRRP information is not available")
sys.exit(1)
@@ -63,6 +64,7 @@ def print_statistics():
time.sleep(0.2)
output = vyos.keepalived.get_statistics()
print(output)
+ vyos.keepalived.remove_vrrp_data("stats")
except:
print("VRRP statistics are not available")
sys.exit(1)
@@ -73,6 +75,7 @@ def print_state_data():
time.sleep(0.2)
output = vyos.keepalived.get_state_data()
print(output)
+ vyos.keepalived.remove_vrrp_data("state")
except:
print("VRRP information is not available")
sys.exit(1)
diff --git a/src/system/vrrp-script-wrapper.py b/src/system/vrrp-script-wrapper.py
index ccd640128..c28ecba55 100755
--- a/src/system/vrrp-script-wrapper.py
+++ b/src/system/vrrp-script-wrapper.py
@@ -23,7 +23,6 @@ import argparse
import syslog
import vyos.util
-import vyos.keepalived
parser = argparse.ArgumentParser()
@@ -44,38 +43,22 @@ if not args.script or not args.state or not args.group \
# to pass arguments to the script
args.script = " ".join(args.script)
-# Get the old state if it exists and compare it to the current state received
-# in command line options to avoid executing scripts if no real transition occured.
-# This is necessary because keepalived does not keep persistent state data even between
-# config reloads and will cheerfully execute everything whether it's required or not.
-
-old_state = vyos.keepalived.get_old_state(args.group)
-
-if (old_state is None) or (old_state != args.state):
- exitcode = 0
-
- # Run the script and save the new state
-
- # Change the process GID to the config owners group to avoid screwing up
- # running config permissions
- os.setgid(vyos.util.get_cfg_group_id())
-
- syslog.syslog(syslog.LOG_NOTICE, 'Running transition script {0} for VRRP group {1}'.format(args.script, args.group))
- try:
- ret = subprocess.call("%s %s %s %s" % ( args.script, args.state, args.interface, args.group), shell=True)
- if ret != 0:
- syslog.syslog(syslog.LOG_ERR, "Transition script {0} failed, exit status: {1}".format(args.script, ret))
- exitcode = ret
- except Exception as e:
- syslog.syslog(syslog.LOG_ERR, "Failed to execute transition script {0}: {1}".format(args.script, e))
- exitcode = 1
-
- if exitcode == 0:
- syslog.syslog(syslog.LOG_NOTICE, "Transition script {0} executed successfully".format(args.script))
-
- vyos.keepalived.save_state(args.group, args.state)
-else:
- syslog.syslog(syslog.LOG_NOTICE, "State of the group {0} has not changed, not running transition script".format(args.group))
+exitcode = 0
+# Change the process GID to the config owners group to avoid screwing up
+# running config permissions
+os.setgid(vyos.util.get_cfg_group_id())
+syslog.syslog(syslog.LOG_NOTICE, 'Running transition script {0} for VRRP group {1}'.format(args.script, args.group))
+try:
+ ret = subprocess.call("%s %s %s %s" % ( args.script, args.state, args.interface, args.group), shell=True)
+ if ret != 0:
+ syslog.syslog(syslog.LOG_ERR, "Transition script {0} failed, exit status: {1}".format(args.script, ret))
+ exitcode = ret
+except Exception as e:
+ syslog.syslog(syslog.LOG_ERR, "Failed to execute transition script {0}: {1}".format(args.script, e))
+ exitcode = 1
+
+if exitcode == 0:
+ syslog.syslog(syslog.LOG_NOTICE, "Transition script {0} executed successfully".format(args.script))
syslog.closelog()
sys.exit(exitcode)