summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/vyos/configsession.py6
-rw-r--r--python/vyos/defaults.py1
-rw-r--r--python/vyos/ifconfig.py30
-rwxr-xr-xsrc/conf_mode/interface-bonding.py5
-rwxr-xr-xsrc/conf_mode/interface-wireguard.py26
-rwxr-xr-xsrc/helpers/vyos-boot-config-loader.py153
6 files changed, 171 insertions, 50 deletions
diff --git a/python/vyos/configsession.py b/python/vyos/configsession.py
index acbdd3d5f..09fae78a1 100644
--- a/python/vyos/configsession.py
+++ b/python/vyos/configsession.py
@@ -145,7 +145,8 @@ class ConfigSession(object):
self.__run_command([COMMENT] + path + value)
def commit(self):
- self.__run_command([COMMIT])
+ out = self.__run_command([COMMIT])
+ return out
def discard(self):
self.__run_command([DISCARD])
@@ -157,4 +158,5 @@ class ConfigSession(object):
return config_data
def load_config(self, file_path):
- self.__run_command(LOAD_CONFIG + [file_path])
+ out = self.__run_command(LOAD_CONFIG + [file_path])
+ return out
diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py
index 85d27d60d..dedb929b4 100644
--- a/python/vyos/defaults.py
+++ b/python/vyos/defaults.py
@@ -20,6 +20,7 @@ directories = {
"config": "/opt/vyatta/etc/config",
"current": "/opt/vyatta/etc/config-migrate/current",
"migrate": "/opt/vyatta/etc/config-migrate/migrate",
+ "log": "/var/log/vyatta",
}
cfg_group = 'vyattacfg'
diff --git a/python/vyos/ifconfig.py b/python/vyos/ifconfig.py
index 0793fad39..750a7cc70 100644
--- a/python/vyos/ifconfig.py
+++ b/python/vyos/ifconfig.py
@@ -1057,6 +1057,36 @@ class BondIf(EthernetIf):
def __init__(self, ifname):
super().__init__(ifname, type='bond')
+ def remove(self):
+ """
+ Remove interface from operating system. Removing the interface
+ deconfigures all assigned IP addresses and clear possible DHCP(v6)
+ client processes.
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> i = Interface('eth0')
+ >>> i.remove()
+ """
+ # when a bond member gets deleted, all members are placed in A/D state
+ # even when they are enabled inside CLI. This will make the config
+ # and system look async.
+ slave_list = []
+ for s in self.get_slaves():
+ slave = {
+ 'ifname' : s,
+ 'state': Interface(s).state
+ }
+ slave_list.append(slave)
+
+ # remove bond master which places members in disabled state
+ super().remove()
+
+ # replicate previous interface state before bond destruction back to
+ # physical interface
+ for slave in slave_list:
+ i = Interface(slave['ifname'])
+ i.state = slave['state']
+
@property
def xmit_hash_policy(self):
"""
diff --git a/src/conf_mode/interface-bonding.py b/src/conf_mode/interface-bonding.py
index f0a33beff..ac3e1b867 100755
--- a/src/conf_mode/interface-bonding.py
+++ b/src/conf_mode/interface-bonding.py
@@ -279,11 +279,6 @@ def verify(bond):
raise ConfigError('can not enslave interface {} which already ' \
'belongs to {}'.format(intf, tmp))
- # we can not add disabled slave interfaces to our bond
- if conf.exists('interfaces ethernet ' + intf + ' disable'):
- raise ConfigError('can not enslave disabled interface {}' \
- .format(intf))
-
# can not add interfaces with an assigned address to a bond
if conf.exists('interfaces ethernet ' + intf + ' address'):
raise ConfigError('can not enslave interface {} which has an address ' \
diff --git a/src/conf_mode/interface-wireguard.py b/src/conf_mode/interface-wireguard.py
index d51a7a08d..4ae3251fe 100755
--- a/src/conf_mode/interface-wireguard.py
+++ b/src/conf_mode/interface-wireguard.py
@@ -26,12 +26,16 @@ from vyos.config import Config
from vyos import ConfigError
from vyos.ifconfig import WireGuardIf
-ifname = str(os.environ['VYOS_TAGNODE_VALUE'])
-intfc = WireGuardIf(ifname)
+try:
+ ifname = str(os.environ['VYOS_TAGNODE_VALUE'])
+ intfc = WireGuardIf(ifname)
+except KeyError:
+ print("Interface not specified")
+ sys.exit(1)
kdir = r'/config/auth/wireguard'
-def check_kmod():
+def _check_kmod():
if not os.path.exists('/sys/module/wireguard'):
sl.syslog(sl.LOG_NOTICE, "loading wirguard kmod")
if os.system('sudo modprobe wireguard') != 0:
@@ -39,6 +43,19 @@ def check_kmod():
raise ConfigError("modprobe wireguard failed")
+def _migrate_default_keys():
+ if os.path.exists('{}/private.key'.format(kdir)) and not os.path.exists('{}/default/private.key'.format(kdir)):
+ sl.syslog(sl.LOG_NOTICE, "migrate keypair to default")
+ old_umask = os.umask(0o027)
+ location = '{}/default'.format(kdir)
+ subprocess.call(['sudo mkdir -p ' + location], shell=True)
+ subprocess.call(['sudo chgrp vyattacfg ' + location], shell=True)
+ subprocess.call(['sudo chmod 750 ' + location], shell=True)
+ os.rename('{}/private.key'.format(kdir),'{}/private.key'.format(location))
+ os.rename('{}/public.key'.format(kdir),'{}/public.key'.format(location))
+ os.umask(old_umask)
+
+
def get_config():
c = Config()
if not c.exists('interfaces wireguard'):
@@ -257,7 +274,8 @@ def apply(c):
if __name__ == '__main__':
try:
- check_kmod()
+ _check_kmod()
+ _migrate_default_keys()
c = get_config()
verify(c)
apply(c)
diff --git a/src/helpers/vyos-boot-config-loader.py b/src/helpers/vyos-boot-config-loader.py
index 06c95765f..7c81a4c3c 100755
--- a/src/helpers/vyos-boot-config-loader.py
+++ b/src/helpers/vyos-boot-config-loader.py
@@ -18,41 +18,72 @@
import os
import sys
+import pwd
+import grp
import subprocess
import traceback
+from datetime import datetime
+from vyos.defaults import directories
from vyos.configsession import ConfigSession, ConfigSessionError
from vyos.configtree import ConfigTree
STATUS_FILE = '/tmp/vyos-config-status'
TRACE_FILE = '/tmp/boot-config-trace'
-session = ConfigSession(os.getpid(), 'vyos-boot-config-loader')
-env = session.get_session_env()
+CFG_GROUP = 'vyattacfg'
-default_file_name = env['vyatta_sysconfdir'] + '/config.boot.default'
-
-if len(sys.argv) < 1:
- print("Must be called with argument.")
- sys.exit(1)
+if 'log' in directories:
+ LOG_DIR = directories['log']
else:
- file_name = sys.argv[1]
+ LOG_DIR = '/var/log/vyatta'
+
+LOG_FILE = LOG_DIR + '/vyos-boot-config-loader.log'
+
+try:
+ with open('/proc/cmdline', 'r') as f:
+ cmdline = f.read()
+ if 'vyos-debug' in cmdline:
+ os.environ['VYOS_DEBUG'] = 'yes'
+except Exception as e:
+ print('{0}'.format(e))
def write_config_status(status):
- with open(STATUS_FILE, 'w') as f:
- f.write('{0}\n'.format(status))
+ try:
+ with open(STATUS_FILE, 'w') as f:
+ f.write('{0}\n'.format(status))
+ except Exception as e:
+ print('{0}'.format(e))
def trace_to_file(trace_file_name):
- with open(trace_file_name, 'w') as trace_file:
- traceback.print_exc(file=trace_file)
+ try:
+ with open(trace_file_name, 'w') as trace_file:
+ traceback.print_exc(file=trace_file)
+ except Exception as e:
+ print('{0}'.format(e))
+
+def failsafe(config_file_name):
+ fail_msg = """
+ !!!!!
+ There were errors loading the configuration
+ Please examine the errors in
+ {0}
+ and correct
+ !!!!!
+ """.format(TRACE_FILE)
+
+ print(fail_msg, file=sys.stderr)
+
+ users = [x[0] for x in pwd.getpwall()]
+ if 'vyos' in users:
+ return
-def failsafe():
try:
- with open(default_file_name, 'r') as f:
+ with open(config_file_name, 'r') as f:
config_file = f.read()
except Exception as e:
print("Catastrophic: no default config file "
- "'{0}'".format(default_file_name))
+ "'{0}'".format(config_file_name))
sys.exit(1)
config = ConfigTree(config_file)
@@ -73,29 +104,73 @@ def failsafe():
except subprocess.CalledProcessError as e:
sys.exit("{0}".format(e))
- with open('/etc/motd', 'a+') as f:
- f.write('\n\n')
- f.write('!!!!!\n')
- f.write('There were errors loading the initial configuration;\n')
- f.write('please examine the errors in {0} and correct.'
- '\n'.format(TRACE_FILE))
- f.write('!!!!!\n\n')
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print("Must specify boot config file.")
+ sys.exit(1)
+ else:
+ file_name = sys.argv[1]
-try:
- with open(file_name, 'r') as f:
- config_file = f.read()
-except Exception as e:
- write_config_status(1)
- failsafe()
- trace_to_file(TRACE_FILE)
- sys.exit("{0}".format(e))
+ # Set user and group options, so that others will be able to commit
+ # Currently, the only caller does 'sg CFG_GROUP', but that may change
+ cfg_group = grp.getgrnam(CFG_GROUP)
+ os.setgid(cfg_group.gr_gid)
-try:
- session.load_config(file_name)
- session.commit()
- write_config_status(0)
-except ConfigSessionError as e:
- write_config_status(1)
- failsafe()
- trace_to_file(TRACE_FILE)
- sys.exit(1)
+ # Need to set file permissions to 775 so that every vyattacfg group
+ # member has write access to the running config
+ os.umask(0o002)
+
+ session = ConfigSession(os.getpid(), 'vyos-boot-config-loader')
+ env = session.get_session_env()
+
+ default_file_name = env['vyatta_sysconfdir'] + '/config.boot.default'
+
+ try:
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+ except Exception:
+ write_config_status(1)
+ failsafe(default_file_name)
+ trace_to_file(TRACE_FILE)
+ sys.exit(1)
+
+ try:
+ time_begin_load = datetime.now()
+ load_out = session.load_config(file_name)
+ time_end_load = datetime.now()
+ time_begin_commit = datetime.now()
+ commit_out = session.commit()
+ time_end_commit = datetime.now()
+ write_config_status(0)
+ except ConfigSessionError:
+ # If here, there is no use doing session.discard, as we have no
+ # recoverable config environment, and will only throw an error
+ write_config_status(1)
+ failsafe(default_file_name)
+ trace_to_file(TRACE_FILE)
+ sys.exit(1)
+
+ time_elapsed_load = time_end_load - time_begin_load
+ time_elapsed_commit = time_end_commit - time_begin_commit
+
+ try:
+ if not os.path.exists(LOG_DIR):
+ os.mkdir(LOG_DIR)
+ with open(LOG_FILE, 'a') as f:
+ f.write('\n\n')
+ f.write('{0} Begin config load\n'
+ ''.format(time_begin_load))
+ f.write(load_out)
+ f.write('{0} End config load\n'
+ ''.format(time_end_load))
+ f.write('Elapsed time for config load: {0}\n'
+ ''.format(time_elapsed_load))
+ f.write('{0} Begin config commit\n'
+ ''.format(time_begin_commit))
+ f.write(commit_out)
+ f.write('{0} End config commit\n'
+ ''.format(time_end_commit))
+ f.write('Elapsed time for config commit: {0}\n'
+ ''.format(time_elapsed_commit))
+ except Exception as e:
+ print('{0}'.format(e))