summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--interface-definitions/include/interface-mtu-1200-9000.xml.i13
-rw-r--r--interface-definitions/interfaces-vxlan.xml.in2
-rw-r--r--interface-definitions/snmp.xml.in24
-rw-r--r--interface-definitions/vrrp.xml.in8
-rw-r--r--op-mode-definitions/pppoe-server.xml30
-rw-r--r--python/vyos/defaults.py2
-rw-r--r--python/vyos/keepalived.py31
-rw-r--r--python/vyos/systemversions.py28
-rw-r--r--schema/interface_definition.rnc17
-rw-r--r--schema/interface_definition.rng18
-rwxr-xr-xscripts/build-command-templates2
-rwxr-xr-xscripts/build-component-versions47
-rwxr-xr-xsrc/conf_mode/interfaces-vxlan.py8
-rwxr-xr-xsrc/conf_mode/ipsec-settings.py3
-rwxr-xr-xsrc/conf_mode/system-syslog.py13
-rwxr-xr-xsrc/conf_mode/vrrp.py6
-rwxr-xr-xsrc/op_mode/powerctrl.py38
-rwxr-xr-xsrc/op_mode/vrrp.py3
-rwxr-xr-xsrc/system/vrrp-script-wrapper.py49
20 files changed, 263 insertions, 87 deletions
diff --git a/Makefile b/Makefile
index 61e603612..d05a0adbe 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
TMPL_DIR := templates-cfg
OP_TMPL_DIR := templates-op
BUILD_DIR := build
+DATA_DIR := data
CFLAGS :=
src = $(wildcard interface-definitions/*.xml.in)
@@ -77,8 +78,13 @@ op_mode_definitions:
rm -f $(OP_TMPL_DIR)/reset/vpn/node.def
rm -f $(OP_TMPL_DIR)/show/system/node.def
+.PHONY: component_versions
+.ONESHELL:
+component_versions: $(BUILD_DIR) $(obj)
+ $(CURDIR)/scripts/build-component-versions $(BUILD_DIR)/interface-definitions $(DATA_DIR)
+
.PHONY: all
-all: clean interface_definitions op_mode_definitions
+all: clean interface_definitions op_mode_definitions component_versions
.PHONY: clean
clean:
diff --git a/interface-definitions/include/interface-mtu-1200-9000.xml.i b/interface-definitions/include/interface-mtu-1200-9000.xml.i
new file mode 100644
index 000000000..336845b77
--- /dev/null
+++ b/interface-definitions/include/interface-mtu-1200-9000.xml.i
@@ -0,0 +1,13 @@
+<leafNode name="mtu">
+ <properties>
+ <help>Maximum Transmission Unit (MTU)</help>
+ <valueHelp>
+ <format>1200-9000</format>
+ <description>Maximum Transmission Unit</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1200-9000"/>
+ </constraint>
+ <constraintErrorMessage>MTU must be between 1200 and 9000</constraintErrorMessage>
+ </properties>
+</leafNode>
diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in
index ceb75cb34..7d86e1847 100644
--- a/interface-definitions/interfaces-vxlan.xml.in
+++ b/interface-definitions/interfaces-vxlan.xml.in
@@ -57,7 +57,7 @@
</completionHelp>
</properties>
</leafNode>
- #include <include/interface-mtu-1450-9000.xml.i>
+ #include <include/interface-mtu-1200-9000.xml.i>
<leafNode name="remote">
<properties>
<help>Remote address of VXLAN tunnel</help>
diff --git a/interface-definitions/snmp.xml.in b/interface-definitions/snmp.xml.in
index 91f1b8d71..4c6a993b2 100644
--- a/interface-definitions/snmp.xml.in
+++ b/interface-definitions/snmp.xml.in
@@ -139,6 +139,14 @@
<leafNode name="trap-source">
<properties>
<help>SNMP trap source address</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>IPv4 address</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address</description>
+ </valueHelp>
<constraint>
<validator name="ipv4-address"/>
<validator name="ipv6-address"/>
@@ -148,6 +156,14 @@
<tagNode name="trap-target">
<properties>
<help>Address of trap target</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>IPv4 address</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address</description>
+ </valueHelp>
<constraint>
<validator name="ipv4-address"/>
<validator name="ipv6-address"/>
@@ -585,6 +601,10 @@
<tagNode name="extension-name">
<properties>
<help>Extension name</help>
+ <constraint>
+ <regex>^[a-z0-9\.\-\_]+</regex>
+ </constraint>
+ <constraintErrorMessage>Script extension contains invalid characters</constraintErrorMessage>
</properties>
<children>
<leafNode name="script">
@@ -593,6 +613,10 @@
<completionHelp>
<script>ls /config/user-data</script>
</completionHelp>
+ <constraint>
+ <regex>^[a-z0-9\.\-\_\/]+</regex>
+ </constraint>
+ <constraintErrorMessage>Script extension contains invalid characters</constraintErrorMessage>
</properties>
</leafNode>
</children>
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/op-mode-definitions/pppoe-server.xml b/op-mode-definitions/pppoe-server.xml
index 13a4570e8..0293c9502 100644
--- a/op-mode-definitions/pppoe-server.xml
+++ b/op-mode-definitions/pppoe-server.xml
@@ -71,4 +71,34 @@
</node>
</children>
</node>
+ <node name="set">
+ <children>
+ <node name="pppoe-server">
+ <properties>
+ <help>Set PPPoE server maintenance mode</help>
+ </properties>
+ <children>
+ <node name="maintenance-mode">
+ <properties>
+ <help>Set PPPoE server maintenance mode</help>
+ </properties>
+ <children>
+ <leafNode name="enable">
+ <properties>
+ <help>Deny new connections and stop to serve pppoe after disconnect last session</help>
+ </properties>
+ <command>/usr/bin/accel-cmd shutdown soft</command>
+ </leafNode>
+ <leafNode name="cancel">
+ <properties>
+ <help>Cancel maintenance mode</help>
+ </properties>
+ <command>/usr/bin/accel-cmd shutdown cancel</command>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
</interfaceDefinition>
diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py
index dedb929b4..a2ad142bc 100644
--- a/python/vyos/defaults.py
+++ b/python/vyos/defaults.py
@@ -29,6 +29,8 @@ cfg_vintage = 'vyatta'
commit_lock = '/opt/vyatta/config/.lock'
+version_file = '/usr/share/vyos/component-versions.json'
+
https_data = {
'listen_addresses' : { '*': ['_'] }
}
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/python/vyos/systemversions.py b/python/vyos/systemversions.py
index 9b3f4f413..5c4deca29 100644
--- a/python/vyos/systemversions.py
+++ b/python/vyos/systemversions.py
@@ -16,12 +16,15 @@
import os
import re
import sys
+import json
+
import vyos.defaults
def get_system_versions():
"""
- Get component versions from running system; critical failure if
- unable to read migration directory.
+ Get component versions from running system: read vyatta directory
+ structure for versions, then read vyos JSON file. It is a critical
+ error if either migration directory or JSON file is unreadable.
"""
system_versions = {}
@@ -36,4 +39,25 @@ def get_system_versions():
pair = info.split('@')
system_versions[pair[0]] = int(pair[1])
+ version_dict = {}
+ path = vyos.defaults.version_file
+
+ if os.path.isfile(path):
+ with open(path, 'r') as f:
+ try:
+ version_dict = json.load(f)
+ except ValueError as err:
+ print(f"\nValue error in {path}: {err}")
+ sys.exit(1)
+
+ for k, v in version_dict.items():
+ if not isinstance(v, int):
+ print(f"\nType error in {path}; expecting Dict[str, int]")
+ sys.exit(1)
+ existing = system_versions.get(k)
+ if existing is None:
+ system_versions[k] = v
+ elif v > existing:
+ system_versions[k] = v
+
return system_versions
diff --git a/schema/interface_definition.rnc b/schema/interface_definition.rnc
index 02175fec8..0ce8226cd 100644
--- a/schema/interface_definition.rnc
+++ b/schema/interface_definition.rnc
@@ -24,9 +24,16 @@
# Interface definition starts with interfaceDefinition tag that may contain node tags
start = element interfaceDefinition
{
+ syntaxVersion*,
node*
}
+# interfaceDefinition may contain syntax version attribute lists.
+syntaxVersion = element syntaxVersion
+{
+ (componentAttr & versionAttr)
+}
+
# node tag may contain node, leafNode, or tagNode tags
# Those are intermediate configuration nodes that may only contain
# other nodes and must not have values
@@ -97,6 +104,16 @@ properties = element properties
(element keepChildOrder { empty })?
}
+componentAttr = attribute component
+{
+ text
+}
+
+versionAttr = attribute version
+{
+ text
+}
+
# All nodes must have "name" attribute
nodeNameAttr = attribute name
{
diff --git a/schema/interface_definition.rng b/schema/interface_definition.rng
index 195ef27f4..bfd8d376f 100644
--- a/schema/interface_definition.rng
+++ b/schema/interface_definition.rng
@@ -29,10 +29,22 @@
<start>
<element name="interfaceDefinition">
<zeroOrMore>
+ <ref name="syntaxVersion"/>
+ </zeroOrMore>
+ <zeroOrMore>
<ref name="node"/>
</zeroOrMore>
</element>
</start>
+ <!-- interfaceDefinition may contain syntax version attribute lists. -->
+ <define name="syntaxVersion">
+ <element name="syntaxVersion">
+ <interleave>
+ <ref name="componentAttr"/>
+ <ref name="versionAttr"/>
+ </interleave>
+ </element>
+ </define>
<!--
node tag may contain node, leafNode, or tagNode tags
Those are intermediate configuration nodes that may only contain
@@ -184,6 +196,12 @@
</interleave>
</element>
</define>
+ <define name="componentAttr">
+ <attribute name="component"/>
+ </define>
+ <define name="versionAttr">
+ <attribute name="version"/>
+ </define>
<!-- All nodes must have "name" attribute -->
<define name="nodeNameAttr">
<attribute name="name"/>
diff --git a/scripts/build-command-templates b/scripts/build-command-templates
index 4fcdb8ade..dbf4ad9c5 100755
--- a/scripts/build-command-templates
+++ b/scripts/build-command-templates
@@ -295,4 +295,6 @@ root = xml.getroot()
nodes = root.iterfind("*")
for n in nodes:
+ if n.tag == "syntaxVersion":
+ continue
process_node(n, [output_dir])
diff --git a/scripts/build-component-versions b/scripts/build-component-versions
new file mode 100755
index 000000000..5362dbdd4
--- /dev/null
+++ b/scripts/build-component-versions
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+
+import sys
+import os
+import argparse
+import json
+
+from lxml import etree as ET
+
+parser = argparse.ArgumentParser()
+parser.add_argument('INPUT_DIR', type=str,
+ help="Directory containing XML interface definition files")
+parser.add_argument('OUTPUT_DIR', type=str,
+ help="Output directory for JSON file")
+
+args = parser.parse_args()
+
+input_dir = args.INPUT_DIR
+output_dir = args.OUTPUT_DIR
+
+version_dict = {}
+
+for filename in os.listdir(input_dir):
+ filepath = os.path.join(input_dir, filename)
+ print(filepath)
+ try:
+ xml = ET.parse(filepath)
+ except Exception as e:
+ print("Failed to load interface definition file {0}".format(filename))
+ print(e)
+ sys.exit(1)
+
+ root = xml.getroot()
+ version_data = root.iterfind("syntaxVersion")
+ for ver in version_data:
+ component = ver.get("component")
+ version = int(ver.get("version"))
+
+ v = version_dict.get(component)
+ if v is None:
+ version_dict[component] = version
+ elif version > v:
+ version_dict[component] = version
+
+out_file = os.path.join(output_dir, 'component-versions.json')
+with open(out_file, 'w') as f:
+ json.dump(version_dict, f, indent=4, sort_keys=True)
diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py
index 7f1ac6c31..efdc21f89 100755
--- a/src/conf_mode/interfaces-vxlan.py
+++ b/src/conf_mode/interfaces-vxlan.py
@@ -189,13 +189,13 @@ def apply(vxlan):
# configure ARP cache timeout in milliseconds
v.set_arp_cache_tmo(vxlan['ip_arp_cache_tmo'])
# configure ARP filter configuration
- v.set_arp_filter(bond['ip_disable_arp_filter'])
+ v.set_arp_filter(vxlan['ip_disable_arp_filter'])
# configure ARP accept
- v.set_arp_accept(bond['ip_enable_arp_accept'])
+ v.set_arp_accept(vxlan['ip_enable_arp_accept'])
# configure ARP announce
- v.set_arp_announce(bond['ip_enable_arp_announce'])
+ v.set_arp_announce(vxlan['ip_enable_arp_announce'])
# configure ARP ignore
- v.set_arp_ignore(bond['ip_enable_arp_ignore'])
+ v.set_arp_ignore(vxlan['ip_enable_arp_ignore'])
# Enable proxy-arp on this interface
v.set_proxy_arp(vxlan['ip_proxy_arp'])
diff --git a/src/conf_mode/ipsec-settings.py b/src/conf_mode/ipsec-settings.py
index aab3e9734..e80c6caf0 100755
--- a/src/conf_mode/ipsec-settings.py
+++ b/src/conf_mode/ipsec-settings.py
@@ -248,7 +248,8 @@ def generate(data):
write_ipsec_ra_conn(data)
append_ipsec_conf(data)
else:
- remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_ra_conn_file)
+ if os.path.exists(ipsec_ra_conn_file):
+ remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_ra_conn_file)
remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_secrets_flie)
remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_conf_flie)
diff --git a/src/conf_mode/system-syslog.py b/src/conf_mode/system-syslog.py
index 15533afab..2d47cc061 100755
--- a/src/conf_mode/system-syslog.py
+++ b/src/conf_mode/system-syslog.py
@@ -19,6 +19,7 @@
import sys
import os
import re
+import subprocess
import jinja2
from vyos.config import Config
@@ -313,15 +314,11 @@ def verify(c):
def apply(c):
- if not c and os.path.exists('/var/run/rsyslogd.pid'):
- os.system("sudo systemctl stop syslog.socket")
- os.system("sudo systemctl stop rsyslog")
- else:
- if not os.path.exists('/var/run/rsyslogd.pid'):
- os.system("sudo systemctl start rsyslog >/dev/null")
- else:
- os.system("sudo systemctl restart rsyslog >/dev/null")
+ if not c:
+ subprocess.call(['sudo', 'systemctl', 'stop', 'syslog'])
+ return 0
+ subprocess.call(['sudo', 'systemctl', 'restart', 'syslog'])
if __name__ == '__main__':
try:
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/powerctrl.py b/src/op_mode/powerctrl.py
index a6188ec74..54fc12be3 100755
--- a/src/op_mode/powerctrl.py
+++ b/src/op_mode/powerctrl.py
@@ -24,6 +24,7 @@ from datetime import datetime, timedelta, time as type_time, date as type_date
from subprocess import check_output, CalledProcessError, STDOUT
from vyos.util import ask_yes_no
+systemd_sched_file = "/run/systemd/shutdown/scheduled"
def parse_time(s):
try:
@@ -45,33 +46,40 @@ def parse_date(s):
def get_shutdown_status():
try:
- output = check_output(["/bin/systemctl", "status", "systemd-shutdownd.service"]).decode()
- return output
+ if os.path.exists(systemd_sched_file):
+ # Get scheduled from systemd file
+ with open(systemd_sched_file, 'r') as f:
+ data = f.read().rstrip('\n')
+ r_data = {}
+ for line in data.splitlines():
+ tmp_split = line.split("=")
+ if tmp_split[0] == "USEC":
+ # Convert USEC to human readable format
+ r_data['DATETIME'] = datetime.utcfromtimestamp(int(tmp_split[1])/1000000).strftime('%Y-%m-%d %H:%M:%S')
+ else:
+ r_data[tmp_split[0]] = tmp_split[1]
+ return r_data
+ return None
except CalledProcessError:
return None
def check_shutdown():
output = get_shutdown_status()
- if output:
- r = re.findall(r'Status: \"(.*)\"\n', output)
- if r:
- # When available, that line is like
- # Status: "Shutting down at Thu 1970-01-01 00:00:00 UTC (poweroff)..."
- print(r[0])
- else:
- # Sometimes status string is not available immediately
- # after service startup
- print("Poweroff or reboot is scheduled")
+ if output and 'MODE' in output:
+ if output['MODE'] == 'reboot':
+ print("Reboot is scheduled", output['DATETIME'])
+ elif output['MODE'] == 'poweroff':
+ print("Poweroff is scheduled", output['DATETIME'])
else:
- print("Poweroff or reboot is not scheduled")
+ print("Reboot or poweroff is not scheduled")
def cancel_shutdown():
output = get_shutdown_status()
- if output:
+ if output and 'MODE' in output:
try:
timenow = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
cmd = check_output(["/sbin/shutdown","-c","--no-wall"])
- message = "Scheduled reboot or poweroff has been cancelled %s" % timenow
+ message = "Scheduled %s has been cancelled %s" % (output['MODE'], timenow)
os.system("wall %s" % message)
except CalledProcessError as e:
sys.exit("Could not cancel a reboot or poweroff: %s" % e)
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)