summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-04-07 08:27:36 +0200
committerGitHub <noreply@github.com>2020-04-07 08:27:36 +0200
commit09ad28b28c9ebd9308cfe9048686b3b0ef9cfd9c (patch)
tree6e7b0971ecd8859cff864b3ebb37f86f8ba288f5
parente0f13b79a669e7fc8cadac8757b2f5fbbf51dc99 (diff)
parent7256810914e6664bf92041dcd7c3daf649ce0001 (diff)
downloadvyos-1x-09ad28b28c9ebd9308cfe9048686b3b0ef9cfd9c.tar.gz
vyos-1x-09ad28b28c9ebd9308cfe9048686b3b0ef9cfd9c.zip
Merge pull request #307 from thomas-mangin/T2226
util: T2226: convert all call to use vyos.util.{popen, cmd, run}
-rw-r--r--python/vyos/authutils.py8
-rw-r--r--python/vyos/ifconfig/ethernet.py4
-rw-r--r--python/vyos/ifconfig/wireguard.py1
-rw-r--r--python/vyos/remote.py29
-rw-r--r--python/vyos/util.py72
-rwxr-xr-xsrc/completion/list_dumpable_interfaces.py8
-rwxr-xr-xsrc/completion/list_local.py6
-rwxr-xr-xsrc/conf_mode/accel_l2tp.py24
-rwxr-xr-xsrc/conf_mode/arp.py7
-rwxr-xr-xsrc/conf_mode/bcast_relay.py5
-rwxr-xr-xsrc/conf_mode/dhcp_relay.py5
-rwxr-xr-xsrc/conf_mode/dhcp_server.py6
-rwxr-xr-xsrc/conf_mode/dhcpv6_relay.py6
-rwxr-xr-xsrc/conf_mode/dhcpv6_server.py6
-rwxr-xr-xsrc/conf_mode/dns_forwarding.py5
-rwxr-xr-xsrc/conf_mode/dynamic_dns.py6
-rwxr-xr-xsrc/conf_mode/firewall_options.py28
-rwxr-xr-xsrc/conf_mode/flow_accounting_conf.py37
-rwxr-xr-xsrc/conf_mode/host_name.py19
-rwxr-xr-xsrc/conf_mode/http-api.py12
-rwxr-xr-xsrc/conf_mode/https.py6
-rwxr-xr-xsrc/conf_mode/igmp_proxy.py6
-rwxr-xr-xsrc/conf_mode/intel_qat.py24
-rwxr-xr-xsrc/conf_mode/interfaces-bonding.py4
-rwxr-xr-xsrc/conf_mode/interfaces-l2tpv3.py3
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py38
-rwxr-xr-xsrc/conf_mode/interfaces-pppoe.py8
-rwxr-xr-xsrc/conf_mode/interfaces-wireguard.py24
-rwxr-xr-xsrc/conf_mode/interfaces-wireless.py77
-rwxr-xr-xsrc/conf_mode/interfaces-wirelessmodem.py11
-rwxr-xr-xsrc/conf_mode/ipsec-settings.py9
-rwxr-xr-xsrc/conf_mode/le_cert.py28
-rwxr-xr-xsrc/conf_mode/lldp.py6
-rwxr-xr-xsrc/conf_mode/mdns_repeater.py6
-rwxr-xr-xsrc/conf_mode/ntp.py6
-rwxr-xr-xsrc/conf_mode/protocols_bfd.py11
-rwxr-xr-xsrc/conf_mode/protocols_igmp.py4
-rwxr-xr-xsrc/conf_mode/protocols_mpls.py6
-rwxr-xr-xsrc/conf_mode/protocols_pim.py6
-rwxr-xr-xsrc/conf_mode/salt-minion.py6
-rwxr-xr-xsrc/conf_mode/service-ipoe.py16
-rwxr-xr-xsrc/conf_mode/service-pppoe.py16
-rwxr-xr-xsrc/conf_mode/service-router-advert.py6
-rwxr-xr-xsrc/conf_mode/snmp.py18
-rwxr-xr-xsrc/conf_mode/ssh.py6
-rwxr-xr-xsrc/conf_mode/system-ip.py4
-rwxr-xr-xsrc/conf_mode/system-ipv6.py4
-rwxr-xr-xsrc/conf_mode/system-login.py45
-rwxr-xr-xsrc/conf_mode/system-options.py5
-rwxr-xr-xsrc/conf_mode/system-syslog.py8
-rwxr-xr-xsrc/conf_mode/system-timezone.py6
-rwxr-xr-xsrc/conf_mode/tftp_server.py6
-rwxr-xr-xsrc/conf_mode/vpn-pptp.py17
-rwxr-xr-xsrc/conf_mode/vpn_sstp.py53
-rwxr-xr-xsrc/conf_mode/vrf.py10
-rwxr-xr-xsrc/conf_mode/vrrp.py8
-rwxr-xr-xsrc/conf_mode/vyos_cert.py30
-rwxr-xr-xsrc/etc/vmware-tools/scripts/resume-vm-default.d/ether-resume.py6
-rwxr-xr-xsrc/helpers/run-config-migration.py10
-rwxr-xr-xsrc/helpers/validate-value.py4
-rwxr-xr-xsrc/helpers/vyos-boot-config-loader.py9
-rwxr-xr-xsrc/helpers/vyos-bridge-sync.py14
-rwxr-xr-xsrc/helpers/vyos-load-config.py14
-rwxr-xr-xsrc/helpers/vyos-merge-config.py10
-rwxr-xr-xsrc/migration-scripts/system/12-to-1313
-rwxr-xr-xsrc/op_mode/clear_conntrack.py6
-rwxr-xr-xsrc/op_mode/connect_disconnect.py9
-rwxr-xr-xsrc/op_mode/dns_forwarding_reset.py6
-rwxr-xr-xsrc/op_mode/dns_forwarding_statistics.py6
-rwxr-xr-xsrc/op_mode/dynamic_dns.py6
-rwxr-xr-xsrc/op_mode/flow_accounting_op.py46
-rwxr-xr-xsrc/op_mode/format_disk.py17
-rwxr-xr-xsrc/op_mode/generate_ssh_server_key.py10
-rwxr-xr-xsrc/op_mode/lldp_op.py8
-rwxr-xr-xsrc/op_mode/powerctrl.py54
-rwxr-xr-xsrc/op_mode/reset_openvpn.py38
-rwxr-xr-xsrc/op_mode/reset_vpn.py45
-rwxr-xr-xsrc/op_mode/restart_dhcp_relay.py6
-rwxr-xr-xsrc/op_mode/restart_frr.py11
-rwxr-xr-xsrc/op_mode/show_acceleration.py31
-rwxr-xr-xsrc/op_mode/show_dhcp.py7
-rwxr-xr-xsrc/op_mode/show_dhcpv6.py6
-rwxr-xr-xsrc/op_mode/show_vpn_ra.py18
-rwxr-xr-xsrc/op_mode/show_vrf.py8
-rwxr-xr-xsrc/op_mode/show_wireless.py12
-rwxr-xr-xsrc/op_mode/snmp.py3
-rwxr-xr-xsrc/op_mode/snmp_ifmib.py33
-rwxr-xr-xsrc/op_mode/system_integrity.py5
-rwxr-xr-xsrc/op_mode/version.py15
-rwxr-xr-xsrc/op_mode/wireguard.py16
-rwxr-xr-xsrc/system/keepalived-fifo.py14
-rwxr-xr-xsrc/validators/timezone8
92 files changed, 653 insertions, 712 deletions
diff --git a/python/vyos/authutils.py b/python/vyos/authutils.py
index 234294649..90a46ffb4 100644
--- a/python/vyos/authutils.py
+++ b/python/vyos/authutils.py
@@ -15,16 +15,14 @@
import re
-from subprocess import Popen, PIPE, STDOUT
+from vyos.util import cmd
def make_password_hash(password):
""" Makes a password hash for /etc/shadow using mkpasswd """
- mkpasswd = Popen(['mkpasswd', '--method=sha-512', '--stdin'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
- hash = mkpasswd.communicate(input=password.encode(), timeout=5)[0].decode().strip()
-
- return hash
+ mkpassword = 'mkpasswd --method=sha-512 --stdin'
+ return cmd(mkpassword, input=password.encode(), timeout=5)
def split_ssh_public_key(key_string, defaultname=""):
""" Splits an SSH public key into its components """
diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py
index c18d2e72f..291b326bf 100644
--- a/python/vyos/ifconfig/ethernet.py
+++ b/python/vyos/ifconfig/ethernet.py
@@ -18,7 +18,7 @@ import re
from vyos.ifconfig.interface import Interface
from vyos.ifconfig.vlan import VLAN
-from vyos.util import popen
+from vyos.util import run
from vyos.validate import *
@@ -45,7 +45,7 @@ class EthernetIf(Interface):
@staticmethod
def feature(ifname, option, value):
- out, code = popen(f'/sbin/ethtool -K {ifname} {option} {value}','ifconfig')
+ run(f'/sbin/ethtool -K {ifname} {option} {value}','ifconfig')
return False
_command_set = {**Interface._command_set, **{
diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py
index def5ab7c5..e2b8a5924 100644
--- a/python/vyos/ifconfig/wireguard.py
+++ b/python/vyos/ifconfig/wireguard.py
@@ -16,7 +16,6 @@
import os
import time
-import subprocess
from datetime import timedelta
from vyos.config import Config
diff --git a/python/vyos/remote.py b/python/vyos/remote.py
index f8a21f068..f0bf41cd4 100644
--- a/python/vyos/remote.py
+++ b/python/vyos/remote.py
@@ -17,7 +17,8 @@ import sys
import os
import re
import fileinput
-import subprocess
+
+from vyos.util import cmd, DEVNULL
def check_and_add_host_key(host_name):
@@ -33,10 +34,8 @@ def check_and_add_host_key(host_name):
keyscan_cmd = 'ssh-keyscan -t rsa {} 2>/dev/null'.format(host_name)
try:
- host_key = subprocess.check_output(keyscan_cmd, shell=True,
- stderr=subprocess.DEVNULL,
- universal_newlines=True)
- except subprocess.CalledProcessError as err:
+ host_key = cmd(keyscan_cmd, stderr=DEVNULL, universal_newlines=True)
+ except OSError:
sys.exit("Can not get RSA host key")
# libssh2 (jessie; stretch) does not recognize ec host keys, and curl
@@ -64,10 +63,8 @@ def check_and_add_host_key(host_name):
fingerprint_cmd = 'ssh-keygen -lf /dev/stdin <<< "{}"'.format(host_key)
try:
- fingerprint = subprocess.check_output(fingerprint_cmd, shell=True,
- stderr=subprocess.DEVNULL,
- universal_newlines=True)
- except subprocess.CalledProcessError as err:
+ fingerprint = cmd(fingerprint_cmd, stderr=DEVNULL, universal_newlines=True)
+ except OSError:
sys.exit("Can not get RSA host key fingerprint.")
print("RSA host key fingerprint is {}".format(fingerprint.split()[1]))
@@ -128,9 +125,8 @@ def get_remote_config(remote_file):
# Try header first, and look for 'OK' or 'Moved' codes:
curl_cmd = 'curl {0} -q -I {1}'.format(redirect_opt, remote_file)
try:
- curl_output = subprocess.check_output(curl_cmd, shell=True,
- universal_newlines=True)
- except subprocess.CalledProcessError:
+ curl_output = cmd(curl_cmd, shell=True, universal_newlines=True)
+ except OSError:
sys.exit(1)
return_vals = re.findall(r'^HTTP\/\d+\.?\d\s+(\d+)\s+(.*)$',
@@ -146,9 +142,6 @@ def get_remote_config(remote_file):
curl_cmd = 'curl {0} -# {1}'.format(redirect_opt, remote_file)
try:
- config_file = subprocess.check_output(curl_cmd, shell=True,
- universal_newlines=True)
- except subprocess.CalledProcessError:
- config_file = None
-
- return config_file
+ return cmd(curl_cmd, universal_newlines=True)
+ except OSError:
+ return None
diff --git a/python/vyos/util.py b/python/vyos/util.py
index c8ab43c11..fa2b4dd99 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -16,7 +16,7 @@
import os
import re
import sys
-from subprocess import Popen, PIPE, STDOUT
+from subprocess import Popen, PIPE, STDOUT, DEVNULL
# debugging
@@ -33,36 +33,65 @@ def debug_msg(message, section=''):
# commands
-
-def popen(command, section=''):
- p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True)
- tmp = p.communicate()[0].strip()
+# popen does not raise
+# it returns the output of the command and the error code
+def popen(command, section='', shell=None, input=None, timeout=None, env=None, universal_newlines=None, stdout=PIPE, stderr=STDOUT, decode=None):
+ use_shell = shell
+ if shell is None:
+ use_shell = True if ' ' in command else False
+ p = Popen(
+ command,
+ stdout=stdout, stderr=stderr,
+ env=env, shell=use_shell,
+ universal_newlines=universal_newlines,
+ )
+ tmp = p.communicate(input, timeout)[0].strip()
debug_msg(f"cmd '{command}'", section)
- decoded = tmp.decode()
+ decoded = tmp.decode(decode) if decode else tmp.decode()
if decoded:
debug_msg(f"returned:\n{decoded}", section)
return decoded, p.returncode
-
-def cmd(command, section=''):
- decoded, code = popen(command, section)
+# run does not raise
+# it returns the error code
+def run(command, section='', shell=None, input=None, timeout=None, env=None, universal_newlines=None, stdout=PIPE, stderr=STDOUT, decode=None):
+ _, code = popen(
+ command, section,
+ stdout=stdout, stderr=stderr,
+ input=input, timeout=timeout,
+ env=env, shell=shell,
+ universal_newlines=universal_newlines,
+ decode=decode,
+ )
+ return code
+
+# cmd does raise
+# it returns the output
+def cmd(command, section='', shell=None, input=None, timeout=None, env=None, universal_newlines=None, stdout=PIPE, stderr=STDOUT, decode=None, raising=None, message=''):
+ decoded, code = popen(
+ command, section,
+ stdout=stdout, stderr=stderr,
+ input=input, timeout=timeout,
+ env=env, shell=shell,
+ universal_newlines=universal_newlines,
+ decode=decode,
+ )
if code != 0:
- # error code can be recovered with .errno
- raise OSError(code, f'{command}\nreturned: {decoded}')
+ feedback = message + '\n' if message else ''
+ feedback += f'failed to run command: {command}\n'
+ feedback += f'returned: {decoded}\n'
+ feedback += f'exit code: {code}'
+ if raising is None:
+ # error code can be recovered with .errno
+ raise OSError(code, feedback)
+ else:
+ raise raising(feedback)
return decoded
# file manipulation
-
-def subprocess_cmd(command):
- """ execute arbitrary command via Popen """
- from subprocess import Popen, PIPE
- p = Popen(command, stdout=PIPE, shell=True)
- p.communicate()
-
-
def read_file(path):
""" Read a file to string """
with open(path, 'r') as f:
@@ -224,12 +253,11 @@ def commit_in_progress():
# Since this will be used in scripts that modify the config outside of the CLI
# framework, those knowingly have root permissions.
# For everything else, we add a safeguard.
- from subprocess import check_output
from psutil import process_iter, NoSuchProcess
from vyos.defaults import commit_lock
- id = check_output(['/usr/bin/id', '-u']).decode().strip()
- if id != '0':
+ idu = cmd('/usr/bin/id -u')
+ if idu != '0':
raise OSError("This functions needs root permissions to return correct results")
for proc in process_iter():
diff --git a/src/completion/list_dumpable_interfaces.py b/src/completion/list_dumpable_interfaces.py
index 53ee89633..101c92fbe 100755
--- a/src/completion/list_dumpable_interfaces.py
+++ b/src/completion/list_dumpable_interfaces.py
@@ -3,12 +3,10 @@
# Extract the list of interfaces available for traffic dumps from tcpdump -D
import re
-import subprocess
-if __name__ == '__main__':
- out = subprocess.check_output(['/usr/sbin/tcpdump', '-D']).decode().strip()
- out = out.split("\n")
+from vyos.util import cmd
+if __name__ == '__main__':
+ out = cmd('/usr/sbin/tcpdump -D').split('\n')
intfs = " ".join(map(lambda s: re.search(r'\d+\.(\S+)\s', s).group(1), out))
-
print(intfs)
diff --git a/src/completion/list_local.py b/src/completion/list_local.py
index ddb65c05c..40cc95f1e 100755
--- a/src/completion/list_local.py
+++ b/src/completion/list_local.py
@@ -2,7 +2,8 @@
import json
import argparse
-import subprocess
+
+from vyos.util import cmd
# [{"ifindex":1,"ifname":"lo","flags":["LOOPBACK","UP","LOWER_UP"],"mtu":65536,"qdisc":"noqueue","operstate":"UNKNOWN","group":"default","txqlen":1000,"link_type":"loopback","address":"00:00:00:00:00:00","broadcast":"00:00:00:00:00:00","addr_info":[{"family":"inet","local":"127.0.0.1","prefixlen":8,"scope":"host","label":"lo","valid_life_time":4294967295,"preferred_life_time":4294967295},{"family":"inet6","local":"::1","prefixlen":128,"scope":"host","valid_life_time":4294967295,"preferred_life_time":4294967295}]},{"ifindex":2,"ifname":"eth0","flags":["BROADCAST","MULTICAST","UP","LOWER_UP"],"mtu":1500,"qdisc":"pfifo_fast","operstate":"UP","group":"default","txqlen":1000,"link_type":"ether","address":"08:00:27:fa:12:53","broadcast":"ff:ff:ff:ff:ff:ff","addr_info":[{"family":"inet","local":"10.0.2.15","prefixlen":24,"broadcast":"10.0.2.255","scope":"global","label":"eth0","valid_life_time":4294967295,"preferred_life_time":4294967295},{"family":"inet6","local":"fe80::a00:27ff:fefa:1253","prefixlen":64,"scope":"link","valid_life_time":4294967295,"preferred_life_time":4294967295}]},{"ifindex":3,"ifname":"eth1","flags":["BROADCAST","MULTICAST","UP","LOWER_UP"],"mtu":1500,"qdisc":"pfifo_fast","operstate":"UP","group":"default","txqlen":1000,"link_type":"ether","address":"08:00:27:0d:25:dc","broadcast":"ff:ff:ff:ff:ff:ff","addr_info":[{"family":"inet6","local":"fe80::a00:27ff:fe0d:25dc","prefixlen":64,"scope":"link","valid_life_time":4294967295,"preferred_life_time":4294967295}]},{"ifindex":4,"ifname":"eth2","flags":["BROADCAST","MULTICAST","UP","LOWER_UP"],"mtu":1500,"qdisc":"pfifo_fast","operstate":"UP","group":"default","txqlen":1000,"link_type":"ether","address":"08:00:27:68:d0:b1","broadcast":"ff:ff:ff:ff:ff:ff","addr_info":[{"family":"inet6","local":"fe80::a00:27ff:fe68:d0b1","prefixlen":64,"scope":"link","valid_life_time":4294967295,"preferred_life_time":4294967295}]},{"ifindex":5,"ifname":"eth3","flags":["BROADCAST","MULTICAST","UP","LOWER_UP"],"mtu":1500,"qdisc":"pfifo_fast","operstate":"UP","group":"default","txqlen":1000,"link_type":"ether","address":"08:00:27:f0:17:c5","broadcast":"ff:ff:ff:ff:ff:ff","addr_info":[{"family":"inet6","local":"fe80::a00:27ff:fef0:17c5","prefixlen":64,"scope":"link","valid_life_time":4294967295,"preferred_life_time":4294967295}]}]
@@ -10,8 +11,7 @@ if __name__ == '__main__':
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
- cmd = 'ip -j address show'
- out = subprocess.check_output(cmd.split()).decode().strip()
+ out = cmd('ip -j address show')
data = json.loads(out)
diff --git a/src/conf_mode/accel_l2tp.py b/src/conf_mode/accel_l2tp.py
index 77e1ee874..4ca5a858a 100755
--- a/src/conf_mode/accel_l2tp.py
+++ b/src/conf_mode/accel_l2tp.py
@@ -17,7 +17,7 @@
import sys
import os
import re
-import subprocess
+import jinja2
import socket
import time
@@ -26,6 +26,8 @@ from jinja2 import FileSystemLoader, Environment
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
pidfile = r'/var/run/accel_l2tp.pid'
l2tp_cnf_dir = r'/etc/accel-ppp/l2tp'
@@ -61,17 +63,10 @@ def chk_con():
break
-def accel_cmd(cmd=''):
- if not cmd:
- return None
- try:
- ret = subprocess.check_output(
- ['/usr/bin/accel-cmd', '-p', '2004', cmd]).decode().strip()
- return ret
- except:
- return 1
+def _accel_cmd(command):
+ return run(f'/usr/bin/accel-cmd -p 2004 {command}')
-###
+###
# inline helper functions end
###
@@ -375,21 +370,20 @@ def generate(c):
def apply(c):
if c == None:
if os.path.exists(pidfile):
- accel_cmd('shutdown hard')
+ _accel_cmd('shutdown hard')
if os.path.exists(pidfile):
os.remove(pidfile)
return None
if not os.path.exists(pidfile):
- ret = subprocess.call(
- ['/usr/sbin/accel-pppd', '-c', l2tp_conf, '-p', pidfile, '-d'])
+ ret = run(f'/usr/sbin/accel-pppd -c {l2tp_conf} -p {pidfile} -d')
chk_con()
if ret != 0 and os.path.exists(pidfile):
os.remove(pidfile)
raise ConfigError('accel-pppd failed to start')
else:
# if gw ip changes, only restart doesn't work
- accel_cmd('restart')
+ _accel_cmd('restart')
if __name__ == '__main__':
diff --git a/src/conf_mode/arp.py b/src/conf_mode/arp.py
index aeca08432..3daa892d7 100755
--- a/src/conf_mode/arp.py
+++ b/src/conf_mode/arp.py
@@ -20,9 +20,9 @@ import sys
import os
import re
import syslog as sl
-import subprocess
from vyos.config import Config
+from vyos.util import run
from vyos import ConfigError
arp_cmd = '/usr/sbin/arp'
@@ -82,11 +82,12 @@ def generate(c):
def apply(c):
for ip_addr in c['remove']:
sl.syslog(sl.LOG_NOTICE, "arp -d " + ip_addr)
- subprocess.call([arp_cmd + ' -d ' + ip_addr + ' >/dev/null 2>&1'], shell=True)
+ run(f'{arp_cmd} -d {ip_addr} >/dev/null 2>&1')
for ip_addr in c['update']:
sl.syslog(sl.LOG_NOTICE, "arp -s " + ip_addr + " " + c['update'][ip_addr])
- subprocess.call([arp_cmd + ' -s ' + ip_addr + ' ' + c['update'][ip_addr] ], shell=True)
+ updated = c['update'][ip_addr]
+ run(f'{arp_cmd} -s {ip_addr} {updated}')
if __name__ == '__main__':
diff --git a/src/conf_mode/bcast_relay.py b/src/conf_mode/bcast_relay.py
index 96576ddd4..f6d90776c 100755
--- a/src/conf_mode/bcast_relay.py
+++ b/src/conf_mode/bcast_relay.py
@@ -24,6 +24,7 @@ from jinja2 import FileSystemLoader, Environment
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
config_file = r'/etc/default/udp-broadcast-relay'
@@ -154,7 +155,7 @@ def generate(relay):
def apply(relay):
# first stop all running services
- os.system('sudo systemctl stop udp-broadcast-relay@{1..99}')
+ run('sudo systemctl stop udp-broadcast-relay@{1..99}')
if (relay is None) or relay['disabled']:
return None
@@ -164,7 +165,7 @@ def apply(relay):
# Don't start individual instance when it's disabled
if r['disabled']:
continue
- os.system('sudo systemctl start udp-broadcast-relay@{0}'.format(r['id']))
+ run('sudo systemctl start udp-broadcast-relay@{0}'.format(r['id']))
return None
diff --git a/src/conf_mode/dhcp_relay.py b/src/conf_mode/dhcp_relay.py
index 6f8d66e7b..1d6d4c6e3 100755
--- a/src/conf_mode/dhcp_relay.py
+++ b/src/conf_mode/dhcp_relay.py
@@ -22,6 +22,7 @@ from sys import exit
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
config_file = r'/etc/default/isc-dhcp-relay'
@@ -112,10 +113,10 @@ def generate(relay):
def apply(relay):
if relay is not None:
- os.system('sudo systemctl restart isc-dhcp-relay.service')
+ run('sudo systemctl restart isc-dhcp-relay.service')
else:
# DHCP relay support is removed in the commit
- os.system('sudo systemctl stop isc-dhcp-relay.service')
+ run('sudo systemctl stop isc-dhcp-relay.service')
os.unlink(config_file)
return None
diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py
index 3d75414f5..69aebe2f4 100755
--- a/src/conf_mode/dhcp_server.py
+++ b/src/conf_mode/dhcp_server.py
@@ -26,6 +26,8 @@ from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos.validate import is_subnet_connected
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/dhcp/dhcpd.conf'
lease_file = r'/config/dhcpd.leases'
@@ -626,7 +628,7 @@ def generate(dhcp):
def apply(dhcp):
if (dhcp is None) or dhcp['disabled']:
# DHCP server is removed in the commit
- os.system('sudo systemctl stop isc-dhcpv4-server.service')
+ run('sudo systemctl stop isc-dhcpv4-server.service')
if os.path.exists(config_file):
os.unlink(config_file)
if os.path.exists(daemon_config_file):
@@ -636,7 +638,7 @@ def apply(dhcp):
if not os.path.exists(lease_file):
os.mknod(lease_file)
- os.system('sudo systemctl restart isc-dhcpv4-server.service')
+ run('sudo systemctl restart isc-dhcpv4-server.service')
return None
diff --git a/src/conf_mode/dhcpv6_relay.py b/src/conf_mode/dhcpv6_relay.py
index d942daf37..a67deb6c7 100755
--- a/src/conf_mode/dhcpv6_relay.py
+++ b/src/conf_mode/dhcpv6_relay.py
@@ -23,6 +23,8 @@ from jinja2 import FileSystemLoader, Environment
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/default/isc-dhcpv6-relay'
@@ -98,10 +100,10 @@ def generate(relay):
def apply(relay):
if relay is not None:
- os.system('sudo systemctl restart isc-dhcpv6-relay.service')
+ run('sudo systemctl restart isc-dhcpv6-relay.service')
else:
# DHCPv6 relay support is removed in the commit
- os.system('sudo systemctl stop isc-dhcpv6-relay.service')
+ run('sudo systemctl stop isc-dhcpv6-relay.service')
os.unlink(config_file)
return None
diff --git a/src/conf_mode/dhcpv6_server.py b/src/conf_mode/dhcpv6_server.py
index 10b40baa4..003e80915 100755
--- a/src/conf_mode/dhcpv6_server.py
+++ b/src/conf_mode/dhcpv6_server.py
@@ -25,6 +25,8 @@ from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos.validate import is_subnet_connected
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/dhcp/dhcpdv6.conf'
lease_file = r'/config/dhcpdv6.leases'
@@ -362,7 +364,7 @@ def generate(dhcpv6):
def apply(dhcpv6):
if (dhcpv6 is None) or dhcpv6['disabled']:
# DHCP server is removed in the commit
- os.system('sudo systemctl stop isc-dhcpv6-server.service')
+ run('sudo systemctl stop isc-dhcpv6-server.service')
if os.path.exists(config_file):
os.unlink(config_file)
if os.path.exists(daemon_config_file):
@@ -372,7 +374,7 @@ def apply(dhcpv6):
if not os.path.exists(lease_file):
os.mknod(lease_file)
- os.system('sudo systemctl restart isc-dhcpv6-server.service')
+ run('sudo systemctl restart isc-dhcpv6-server.service')
return None
diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py
index bbb69cdf7..5dc599425 100755
--- a/src/conf_mode/dns_forwarding.py
+++ b/src/conf_mode/dns_forwarding.py
@@ -26,6 +26,7 @@ from vyos.defaults import directories as vyos_data_dir
from vyos.hostsd_client import Client as hostsd_client
from vyos.util import wait_for_commit_lock
from vyos import ConfigError
+from vyos.util import run
parser = argparse.ArgumentParser()
parser.add_argument("--dhclient", action="store_true",
@@ -166,11 +167,11 @@ def generate(dns):
def apply(dns):
if dns is None:
# DNS forwarding is removed in the commit
- os.system("systemctl stop pdns-recursor")
+ run("systemctl stop pdns-recursor")
if os.path.isfile(config_file):
os.unlink(config_file)
else:
- os.system("systemctl restart pdns-recursor")
+ run("systemctl restart pdns-recursor")
if __name__ == '__main__':
args = parser.parse_args()
diff --git a/src/conf_mode/dynamic_dns.py b/src/conf_mode/dynamic_dns.py
index 56ce4fedc..b9163f7b3 100755
--- a/src/conf_mode/dynamic_dns.py
+++ b/src/conf_mode/dynamic_dns.py
@@ -24,6 +24,8 @@ from stat import S_IRUSR, S_IWUSR
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/ddclient/ddclient.conf'
cache_file = r'/var/cache/ddclient/ddclient.cache'
@@ -255,11 +257,11 @@ def apply(dyndns):
os.unlink('/etc/ddclient.conf')
if dyndns['deleted']:
- os.system('/etc/init.d/ddclient stop')
+ run('/etc/init.d/ddclient stop')
if os.path.exists(dyndns['pid_file']):
os.unlink(dyndns['pid_file'])
else:
- os.system('/etc/init.d/ddclient restart')
+ run('/etc/init.d/ddclient restart')
return None
diff --git a/src/conf_mode/firewall_options.py b/src/conf_mode/firewall_options.py
index 2be80cdbf..90f004bc4 100755
--- a/src/conf_mode/firewall_options.py
+++ b/src/conf_mode/firewall_options.py
@@ -21,6 +21,8 @@ import copy
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import run
+
default_config_data = {
'intf_opts': [],
@@ -85,19 +87,19 @@ def apply(tcp):
target = 'VYOS_FW_OPTIONS'
# always cleanup iptables
- os.system('iptables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target))
- os.system('iptables --table mangle --flush {} >&/dev/null'.format(target))
- os.system('iptables --table mangle --delete-chain {} >&/dev/null'.format(target))
+ run('iptables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target))
+ run('iptables --table mangle --flush {} >&/dev/null'.format(target))
+ run('iptables --table mangle --delete-chain {} >&/dev/null'.format(target))
# always cleanup ip6tables
- os.system('ip6tables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target))
- os.system('ip6tables --table mangle --flush {} >&/dev/null'.format(target))
- os.system('ip6tables --table mangle --delete-chain {} >&/dev/null'.format(target))
+ run('ip6tables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target))
+ run('ip6tables --table mangle --flush {} >&/dev/null'.format(target))
+ run('ip6tables --table mangle --delete-chain {} >&/dev/null'.format(target))
# Setup new iptables rules
if tcp['new_chain4']:
- os.system('iptables --table mangle --new-chain {} >&/dev/null'.format(target))
- os.system('iptables --table mangle --append FORWARD --jump {} >&/dev/null'.format(target))
+ run('iptables --table mangle --new-chain {} >&/dev/null'.format(target))
+ run('iptables --table mangle --append FORWARD --jump {} >&/dev/null'.format(target))
for opts in tcp['intf_opts']:
intf = opts['intf']
@@ -109,13 +111,13 @@ def apply(tcp):
# adjust TCP MSS per interface
if mss:
- os.system('iptables --table mangle --append {} --out-interface {} --protocol tcp ' \
+ run('iptables --table mangle --append {} --out-interface {} --protocol tcp ' \
'--tcp-flags SYN,RST SYN --jump TCPMSS --set-mss {} >&/dev/null'.format(target, intf, mss))
# Setup new ip6tables rules
if tcp['new_chain6']:
- os.system('ip6tables --table mangle --new-chain {} >&/dev/null'.format(target))
- os.system('ip6tables --table mangle --append FORWARD --jump {} >&/dev/null'.format(target))
+ run('ip6tables --table mangle --new-chain {} >&/dev/null'.format(target))
+ run('ip6tables --table mangle --append FORWARD --jump {} >&/dev/null'.format(target))
for opts in tcp['intf_opts']:
intf = opts['intf']
@@ -127,8 +129,8 @@ def apply(tcp):
# adjust TCP MSS per interface
if mss:
- os.system('ip6tables --table mangle --append {} --out-interface {} --protocol tcp ' \
- '--tcp-flags SYN,RST SYN --jump TCPMSS --set-mss {} >&/dev/null'.format(target, intf, mss))
+ run('ip6tables --table mangle --append {} --out-interface {} --protocol tcp '
+ '--tcp-flags SYN,RST SYN --jump TCPMSS --set-mss {} >&/dev/null'.format(target, intf, mss))
return None
diff --git a/src/conf_mode/flow_accounting_conf.py b/src/conf_mode/flow_accounting_conf.py
index b040c8b64..1008f3fae 100755
--- a/src/conf_mode/flow_accounting_conf.py
+++ b/src/conf_mode/flow_accounting_conf.py
@@ -16,7 +16,7 @@
import os
import re
-import subprocess
+import ipaddress
from ipaddress import ip_address
from jinja2 import FileSystemLoader, Environment
@@ -26,6 +26,8 @@ from vyos.ifconfig import Interface
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import cmd
+
# default values
default_sflow_server_port = 6343
@@ -80,11 +82,7 @@ def _iptables_get_nflog():
for iptables_variant in ['iptables', 'ip6tables']:
# run iptables, save output and split it by lines
iptables_command = "sudo {0} -t {1} -S {2}".format(iptables_variant, iptables_nflog_table, iptables_nflog_chain)
- process = subprocess.Popen(iptables_command, stdout=subprocess.PIPE, shell=True, universal_newlines=True)
- stdout, stderr = process.communicate()
- if not process.returncode == 0:
- print("Failed to get flows list: command \"{}\" returned exit code: {}\nError: {}".format(command, process.returncode, stderr))
- exit(1)
+ cmd(iptables_command, universal_newlines=True, message='Failed to get flows list')
iptables_out = stdout.splitlines()
# parse each line and add information to list
@@ -113,10 +111,17 @@ def _iptables_config(configured_ifaces):
# compare current active list with configured one and delete excessive interfaces, add missed
active_nflog_ifaces = []
for rule in active_nflog_rules:
- if rule['interface'] not in configured_ifaces:
- iptable_commands.append("sudo {0} -t {1} -D {2}".format(rule['iptables_variant'], rule['table'], rule['rule_definition']))
+ iptables = rule['iptables_variant']
+ interface = rule['interface']
+ if interface not in configured_ifaces:
+ table = rule['table']
+ rule = rule['rule_definition']
+ iptable_commands.append(f'sudo {iptables} -t {table} -D {rule}')
else:
- active_nflog_ifaces.append({ 'iface': rule['interface'], 'iptables_variant': rule['iptables_variant'] })
+ active_nflog_ifaces.append({
+ 'iface': interface,
+ 'iptables_variant': iptables,
+ })
# do not create new rules for already configured interfaces
for iface in active_nflog_ifaces:
@@ -125,14 +130,14 @@ def _iptables_config(configured_ifaces):
# create missed rules
for iface_extended in configured_ifaces_extended:
- rule_definition = "{0} -i {1} -m comment --comment FLOW_ACCOUNTING_RULE -j NFLOG --nflog-group 2 --nflog-size {2} --nflog-threshold 100".format(iptables_nflog_chain, iface_extended['iface'], default_captured_packet_size)
- iptable_commands.append("sudo {0} -t {1} -I {2}".format(iface_extended['iptables_variant'], iptables_nflog_table, rule_definition))
+ iface = iface_extended['iface']
+ iptables = iface_extended['iptables_variant']
+ rule_definition = f'{iptables_nflog_chain} -i {iface} -m comment --comment FLOW_ACCOUNTING_RULE -j NFLOG --nflog-group 2 --nflog-size {default_captured_packet_size} --nflog-threshold 100'
+ iptable_commands.append(f'sudo {iptables} -t {iptables_nflog_table} -I {rule_definition}')
# change iptables
for command in iptable_commands:
- return_code = subprocess.call(command.split(' '))
- if not return_code == 0:
- raise ConfigError("Failed to run command: {}\nExit code {}".format(command, return_code))
+ cmd(command, raising=ConfigError)
def get_config():
@@ -351,9 +356,7 @@ def apply(config):
command = '/usr/bin/sudo /bin/systemctl restart uacctd'
# run command to start or stop flow-accounting
- return_code = subprocess.call(command.split(' '))
- if not return_code == 0:
- raise ConfigError("Failed to start/stop flow-accounting: command {} returned exit code {}".format(command, return_code))
+ cmd(command, raising=ConfigError, message='Failed to start/stop flow-accounting')
# configure iptables rules for defined interfaces
if config['interfaces']:
diff --git a/src/conf_mode/host_name.py b/src/conf_mode/host_name.py
index 47cf232e9..690d1e030 100755
--- a/src/conf_mode/host_name.py
+++ b/src/conf_mode/host_name.py
@@ -25,7 +25,6 @@ import re
import sys
import copy
import glob
-import subprocess
import argparse
import jinja2
@@ -34,6 +33,7 @@ import vyos.hostsd_client
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import cmd, run
default_config_data = {
@@ -156,21 +156,22 @@ def apply(config):
# rsyslog runs into a race condition at boot time with systemd
# restart rsyslog only if the hostname changed.
- hostname_old = subprocess.check_output(['hostnamectl', '--static']).decode().strip()
-
- os.system("hostnamectl set-hostname --static {0}".format(hostname_new))
+ hostname_old = cmd('hostnamectl --static')
+ cmd(f'hostnamectl set-hostname --static {hostname_new}')
# Restart services that use the hostname
if hostname_new != hostname_old:
- os.system("systemctl restart rsyslog.service")
+ run("systemctl restart rsyslog.service")
# If SNMP is running, restart it too
- if os.system("pgrep snmpd > /dev/null") == 0:
- os.system("systemctl restart snmpd.service")
+ ret = run("pgrep snmpd > /dev/null")
+ if ret == 0:
+ run("systemctl restart snmpd.service")
# restart pdns if it is used
- if os.system("/usr/bin/rec_control ping >/dev/null 2>&1") == 0:
- os.system("/etc/init.d/pdns-recursor restart >/dev/null")
+ ret = run('/usr/bin/rec_control ping >/dev/null 2>&1')
+ if ret == 0:
+ run('/etc/init.d/pdns-recursor restart >/dev/null')
return None
diff --git a/src/conf_mode/http-api.py b/src/conf_mode/http-api.py
index 0c2e029e9..91b8aa34b 100755
--- a/src/conf_mode/http-api.py
+++ b/src/conf_mode/http-api.py
@@ -18,13 +18,13 @@
import sys
import os
-import subprocess
import json
from copy import deepcopy
import vyos.defaults
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import cmd, run
config_file = '/etc/vyos/http-api.conf'
@@ -91,16 +91,12 @@ def generate(http_api):
def apply(http_api):
if http_api is not None:
- os.system('sudo systemctl restart vyos-http-api.service')
+ run('sudo systemctl restart vyos-http-api.service')
else:
- os.system('sudo systemctl stop vyos-http-api.service')
+ run('sudo systemctl stop vyos-http-api.service')
for dep in dependencies:
- cmd = '{0}/{1}'.format(vyos_conf_scripts_dir, dep)
- try:
- subprocess.check_call(cmd, shell=True)
- except subprocess.CalledProcessError as err:
- raise ConfigError("{}.".format(err))
+ cmd(f'{vyos_conf_scripts_dir}/{dep}', raising=ConfigError)
if __name__ == '__main__':
try:
diff --git a/src/conf_mode/https.py b/src/conf_mode/https.py
index 83a5f3602..e46f1a4e7 100755
--- a/src/conf_mode/https.py
+++ b/src/conf_mode/https.py
@@ -26,6 +26,8 @@ import vyos.certbot_util
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = '/etc/nginx/sites-available/default'
@@ -144,9 +146,9 @@ def generate(https):
def apply(https):
if https is not None:
- os.system('sudo systemctl restart nginx.service')
+ run('sudo systemctl restart nginx.service')
else:
- os.system('sudo systemctl stop nginx.service')
+ run('sudo systemctl stop nginx.service')
if __name__ == '__main__':
try:
diff --git a/src/conf_mode/igmp_proxy.py b/src/conf_mode/igmp_proxy.py
index aa46f2c4e..abe473530 100755
--- a/src/conf_mode/igmp_proxy.py
+++ b/src/conf_mode/igmp_proxy.py
@@ -24,6 +24,8 @@ from netifaces import interfaces
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/igmpproxy.conf'
@@ -129,11 +131,11 @@ def generate(igmp_proxy):
def apply(igmp_proxy):
if igmp_proxy is None or igmp_proxy['disable']:
# IGMP Proxy support is removed in the commit
- os.system('sudo systemctl stop igmpproxy.service')
+ run('sudo systemctl stop igmpproxy.service')
if os.path.exists(config_file):
os.unlink(config_file)
else:
- os.system('systemctl restart igmpproxy.service')
+ run('systemctl restart igmpproxy.service')
return None
diff --git a/src/conf_mode/intel_qat.py b/src/conf_mode/intel_qat.py
index a1abd5e81..cc7d4a915 100755
--- a/src/conf_mode/intel_qat.py
+++ b/src/conf_mode/intel_qat.py
@@ -19,10 +19,10 @@
import sys
import os
import re
-import subprocess
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import popen, run
# Define for recovering
gl_ipsec_conf = None
@@ -49,13 +49,10 @@ def get_config():
# Control configured VPN service which can use QAT
def vpn_control(action):
+ # XXX: Should these commands report failure
if action == 'restore' and gl_ipsec_conf:
- ret = subprocess.Popen(['sudo', 'ipsec', 'start'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
- return
-
- ret = subprocess.Popen(['sudo', 'ipsec', action], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
+ return run('sudo ipsec start')
+ return run(f'sudo ipsec {action}')
def verify(c):
# Check if QAT service installed
@@ -66,10 +63,9 @@ def verify(c):
return
# Check if QAT device exist
- ret = subprocess.Popen(['sudo', 'lspci', '-nn'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
+ output, err = popen('sudo lspci -nn', decode='utf-8')
if not err:
- data = re.findall('(8086:19e2)|(8086:37c8)|(8086:0435)|(8086:6f54)', output.decode("utf-8"))
+ data = re.findall('(8086:19e2)|(8086:37c8)|(8086:0435)|(8086:6f54)', output)
#If QAT devices found
if not data:
print("\t No QAT acceleration device found")
@@ -82,17 +78,13 @@ def apply(c):
# Disable QAT service
if c['qat_conf'] == None:
- ret = subprocess.Popen(['sudo', '/etc/init.d/vyos-qat-utilities', 'stop'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
+ run('sudo /etc/init.d/vyos-qat-utilities stop')
if c['ipsec_conf']:
vpn_control('start')
-
return
# Run qat init.d script
- ret = subprocess.Popen(['sudo', '/etc/init.d/vyos-qat-utilities', 'start'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
-
+ run('sudo /etc/init.d/vyos-qat-utilities start')
if c['ipsec_conf']:
# Recovery VPN service
vpn_control('start')
diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py
index cc119b91a..19f43f725 100755
--- a/src/conf_mode/interfaces-bonding.py
+++ b/src/conf_mode/interfaces-bonding.py
@@ -25,6 +25,8 @@ from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config
from vyos.configdict import list_diff, vlan_to_dict
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import run
+
default_config_data = {
'address': [],
@@ -90,7 +92,7 @@ def get_config():
if not os.path.isfile('/sys/class/net/bonding_masters'):
import syslog
syslog.syslog(syslog.LOG_NOTICE, "loading bonding kernel module")
- if os.system('modprobe bonding max_bonds=0 miimon=250') != 0:
+ if run('modprobe bonding max_bonds=0 miimon=250') != 0:
syslog.syslog(syslog.LOG_NOTICE, "failed loading bonding kernel module")
raise ConfigError("failed loading bonding kernel module")
diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py
index af1d3f482..4b5fc8306 100755
--- a/src/conf_mode/interfaces-l2tpv3.py
+++ b/src/conf_mode/interfaces-l2tpv3.py
@@ -22,6 +22,7 @@ from copy import deepcopy
from vyos.config import Config
from vyos.ifconfig import L2TPv3If, Interface
from vyos import ConfigError
+from vyos.util import run
from netifaces import interfaces
default_config_data = {
@@ -50,7 +51,7 @@ def check_kmod():
modules = ['l2tp_eth', 'l2tp_netlink', 'l2tp_ip', 'l2tp_ip6']
for module in modules:
if not os.path.exists(f'/sys/module/{module}'):
- if os.system(f'modprobe {module}') != 0:
+ if run(f'modprobe {module}') != 0:
raise ConfigError(f'Loading Kernel module {module} failed')
def get_config():
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index faaee9ac0..1fe1143cd 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -25,14 +25,13 @@ from grp import getgrnam
from ipaddress import ip_address,ip_network,IPv4Interface
from netifaces import interfaces
from pwd import getpwnam
-from subprocess import Popen, PIPE
from time import sleep
from shutil import rmtree
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos.ifconfig import VTunIf
-from vyos.util import process_running
+from vyos.util import process_running, cmd
from vyos.validate import is_addr_assigned
from vyos import ConfigError
@@ -96,9 +95,6 @@ default_config_data = {
'gid': group,
}
-def subprocess_cmd(command):
- p = Popen(command, stdout=PIPE, shell=True)
- p.communicate()
def get_config_name(intf):
cfg_file = r'/opt/vyatta/etc/openvpn/openvpn-{}.conf'.format(intf)
@@ -744,12 +740,12 @@ def apply(openvpn):
# service as the configuration is not re-read. Stop daemon only if it's
# running - it could have died or killed by someone evil
if process_running(pidfile):
- cmd = 'start-stop-daemon'
- cmd += ' --stop '
- cmd += ' --quiet'
- cmd += ' --oknodo'
- cmd += ' --pidfile ' + pidfile
- subprocess_cmd(cmd)
+ command = 'start-stop-daemon'
+ command += ' --stop '
+ command += ' --quiet'
+ command += ' --oknodo'
+ command += ' --pidfile ' + pidfile
+ cmd(command)
# cleanup old PID file
if os.path.isfile(pidfile):
@@ -780,19 +776,19 @@ def apply(openvpn):
# No matching OpenVPN process running - maybe it got killed or none
# existed - nevertheless, spawn new OpenVPN process
- cmd = 'start-stop-daemon'
- cmd += ' --start '
- cmd += ' --quiet'
- cmd += ' --oknodo'
- cmd += ' --pidfile ' + pidfile
- cmd += ' --exec /usr/sbin/openvpn'
+ command = 'start-stop-daemon'
+ command += ' --start '
+ command += ' --quiet'
+ command += ' --oknodo'
+ command += ' --pidfile ' + pidfile
+ command += ' --exec /usr/sbin/openvpn'
# now pass arguments to openvpn binary
- cmd += ' --'
- cmd += ' --daemon openvpn-' + openvpn['intf']
- cmd += ' --config ' + get_config_name(openvpn['intf'])
+ command += ' --'
+ command += ' --daemon openvpn-' + openvpn['intf']
+ command += ' --config ' + get_config_name(openvpn['intf'])
# execute assembled command
- subprocess_cmd(cmd)
+ cmd(command)
# better late then sorry ... but we can only set interface alias after
# OpenVPN has been launched and created the interface
diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py
index a396af4ea..407547175 100755
--- a/src/conf_mode/interfaces-pppoe.py
+++ b/src/conf_mode/interfaces-pppoe.py
@@ -24,7 +24,7 @@ from netifaces import interfaces
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos.ifconfig import Interface
-from vyos.util import chown_file, chmod_x, subprocess_cmd
+from vyos.util import chown_file, chmod_x, cmd
from vyos import ConfigError
default_config_data = {
@@ -182,8 +182,7 @@ def generate(pppoe):
os.mkdir(dirname)
# Always hang-up PPPoE connection prior generating new configuration file
- cmd = f'systemctl stop ppp@{intf}.service'
- subprocess_cmd(cmd)
+ cmd(f'systemctl stop ppp@{intf}.service')
if pppoe['deleted']:
# Delete PPP configuration files
@@ -238,8 +237,7 @@ def apply(pppoe):
if not pppoe['disable']:
# "dial" PPPoE connection
intf = pppoe['intf']
- cmd = f'systemctl start ppp@{intf}.service'
- subprocess_cmd(cmd)
+ cmd(f'systemctl start ppp@{intf}.service')
# make logfile owned by root / vyattacfg
chown_file(pppoe['logfile'], 'root', 'vyattacfg')
diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py
index 5c0c07dc4..4fa0dd8c0 100755
--- a/src/conf_mode/interfaces-wireguard.py
+++ b/src/conf_mode/interfaces-wireguard.py
@@ -17,7 +17,6 @@
import sys
import os
import re
-import subprocess
from copy import deepcopy
from netifaces import interfaces
@@ -25,27 +24,26 @@ from netifaces import interfaces
from vyos import ConfigError
from vyos.config import Config
from vyos.configdict import list_diff
+from vyos.util import run
from vyos.ifconfig import WireGuardIf
kdir = r'/config/auth/wireguard'
def _check_kmod():
if not os.path.exists('/sys/module/wireguard'):
- if os.system('modprobe wireguard') != 0:
+ if run('modprobe wireguard') != 0:
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)):
+ if os.path.exists(f'{kdir}/private.key') and not os.path.exists(f'{kdir}/default/private.key'):
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))
+ location = f'{kdir}/default'
+ run(f'sudo mkdir -p {location}')
+ run(f'sudo chgrp vyattacfg {location}')
+ run(f'sudo chmod 750 {location}')
+ os.rename(f'{kdir}/private.key', f'{location}/private.key')
+ os.rename(f'{kdir}/public.key', f'{location}/public.key')
os.umask(old_umask)
@@ -208,8 +206,8 @@ def apply(c):
if re.search("DEVTYPE=wireguard", buf, re.I | re.M):
wg_intf = re.sub("INTERFACE=", "", re.search(
"INTERFACE=.*", buf, re.I | re.M).group(0))
- subprocess.call(
- ['ip l d dev ' + wg_intf + ' >/dev/null'], shell=True)
+ # XXX: we are ignoring any errors here
+ run(f'ip l d dev {wg_intf} >/dev/null')
return None
# init wg class
diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py
index da8470f7e..188d0ee22 100755
--- a/src/conf_mode/interfaces-wireless.py
+++ b/src/conf_mode/interfaces-wireless.py
@@ -21,7 +21,6 @@ from re import findall
from copy import deepcopy
from jinja2 import FileSystemLoader, Environment
-from subprocess import Popen, PIPE
from netifaces import interfaces
from netaddr import EUI, mac_unix_expanded
@@ -30,7 +29,7 @@ from vyos.configdict import list_diff, vlan_to_dict
from vyos.defaults import directories as vyos_data_dir
from vyos.ifconfig import WiFiIf
from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config
-from vyos.util import process_running, chmod_x, chown_file
+from vyos.util import process_running, chmod_x, chown_file, run
from vyos import ConfigError
user = 'root'
@@ -152,9 +151,6 @@ def get_wpa_suppl_config_name(intf):
cfg_file = cfg_dir + r'/{}.cfg'.format(intf)
return cfg_file
-def subprocess_cmd(command):
- p = Popen(command, stdout=PIPE, shell=True)
- p.communicate()
def get_config():
wifi = deepcopy(default_config_data)
@@ -631,22 +627,22 @@ def generate(wifi):
# always stop hostapd service first before reconfiguring it
pidfile = get_pid('hostapd', wifi['intf'])
if process_running(pidfile):
- cmd = 'start-stop-daemon'
- cmd += ' --stop '
- cmd += ' --quiet'
- cmd += ' --oknodo'
- cmd += ' --pidfile ' + pidfile
- subprocess_cmd(cmd)
+ command = 'start-stop-daemon'
+ command += ' --stop '
+ command += ' --quiet'
+ command += ' --oknodo'
+ command += ' --pidfile ' + pidfile
+ run(command)
# always stop wpa_supplicant service first before reconfiguring it
pidfile = get_pid('wpa_supplicant', wifi['intf'])
if process_running(pidfile):
- cmd = 'start-stop-daemon'
- cmd += ' --stop '
- cmd += ' --quiet'
- cmd += ' --oknodo'
- cmd += ' --pidfile ' + pidfile
- subprocess_cmd(cmd)
+ command = 'start-stop-daemon'
+ command += ' --stop '
+ command += ' --quiet'
+ command += ' --oknodo'
+ command += ' --pidfile ' + pidfile
+ run(command)
# Delete config files if interface is removed
if wifi['deleted']:
@@ -807,37 +803,38 @@ def apply(wifi):
# Physical interface is now configured. Proceed by starting hostapd or
# wpa_supplicant daemon. When type is monitor we can just skip this.
if wifi['op_mode'] == 'ap':
- cmd = 'start-stop-daemon'
- cmd += ' --start '
- cmd += ' --quiet'
- cmd += ' --oknodo'
- cmd += ' --pidfile ' + get_pid('hostapd', wifi['intf'])
- cmd += ' --exec /usr/sbin/hostapd'
+ command = 'start-stop-daemon'
+ command += ' --start '
+ command += ' --quiet'
+ command += ' --oknodo'
+ command += ' --pidfile ' + get_pid('hostapd', wifi['intf'])
+ command += ' --exec /usr/sbin/hostapd'
# now pass arguments to hostapd binary
- cmd += ' -- '
- cmd += ' -B'
- cmd += ' -P ' + get_pid('hostapd', wifi['intf'])
- cmd += ' ' + get_conf_file('hostapd', wifi['intf'])
+ command += ' -- '
+ command += ' -B'
+ command += ' -P ' + get_pid('hostapd', wifi['intf'])
+ command += ' ' + get_conf_file('hostapd', wifi['intf'])
# execute assembled command
- subprocess_cmd(cmd)
+ run(command)
elif wifi['op_mode'] == 'station':
- cmd = 'start-stop-daemon'
- cmd += ' --start '
- cmd += ' --quiet'
- cmd += ' --oknodo'
- cmd += ' --pidfile ' + get_pid('hostapd', wifi['intf'])
- cmd += ' --exec /sbin/wpa_supplicant'
+ command = 'start-stop-daemon'
+ command += ' --start '
+ command += ' --quiet'
+ command += ' --oknodo'
+ command += ' --pidfile ' + get_pid('hostapd', wifi['intf'])
+ command += ' --exec /sbin/wpa_supplicant'
# now pass arguments to hostapd binary
- cmd += ' -- '
- cmd += ' -s -B -D nl80211'
- cmd += ' -P ' + get_pid('wpa_supplicant', wifi['intf'])
- cmd += ' -i ' + wifi['intf']
- cmd += ' -c ' + get_conf_file('wpa_supplicant', wifi['intf'])
+ command += ' -- '
+ command += ' -s -B -D nl80211'
+ command += ' -P ' + get_pid('wpa_supplicant', wifi['intf'])
+ command += ' -i ' + wifi['intf']
+ command += ' -c ' + \
+ get_conf_file('wpa_supplicant', wifi['intf'])
# execute assembled command
- subprocess_cmd(cmd)
+ run(command)
return None
diff --git a/src/conf_mode/interfaces-wirelessmodem.py b/src/conf_mode/interfaces-wirelessmodem.py
index da33d54e4..5e10cfce7 100755
--- a/src/conf_mode/interfaces-wirelessmodem.py
+++ b/src/conf_mode/interfaces-wirelessmodem.py
@@ -23,7 +23,7 @@ from netifaces import interfaces
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
-from vyos.util import chown_file, chmod_x, subprocess_cmd
+from vyos.util import chown_file, chmod_x, cmd, run
from vyos import ConfigError
default_config_data = {
@@ -48,7 +48,7 @@ def check_kmod():
modules = ['option', 'usb_wwan', 'usbserial']
for module in modules:
if not os.path.exists(f'/sys/module/{module}'):
- if os.system(f'modprobe {module}') != 0:
+ if run(f'modprobe {module}') != 0:
raise ConfigError(f'Loading Kernel module {module} failed')
def get_config():
@@ -156,8 +156,7 @@ def generate(wwan):
os.mkdir(dirname)
# Always hang-up WWAN connection prior generating new configuration file
- cmd = f'systemctl stop ppp@{intf}.service'
- subprocess_cmd(cmd)
+ cmd(f'systemctl stop ppp@{intf}.service')
if wwan['deleted']:
# Delete PPP configuration files
@@ -211,9 +210,7 @@ def apply(wwan):
if not wwan['disable']:
# "dial" WWAN connection
intf = wwan['intf']
- cmd = f'systemctl start ppp@{intf}.service'
- subprocess_cmd(cmd)
-
+ cmd(f'systemctl start ppp@{intf}.service')
# make logfile owned by root / vyattacfg
chown_file(wwan['logfile'], 'root', 'vyattacfg')
diff --git a/src/conf_mode/ipsec-settings.py b/src/conf_mode/ipsec-settings.py
index 90b6b0d57..c2f5c8e07 100755
--- a/src/conf_mode/ipsec-settings.py
+++ b/src/conf_mode/ipsec-settings.py
@@ -24,6 +24,7 @@ from sys import exit
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
ra_conn_name = "remote-access"
charon_conf_file = "/etc/strongswan.d/charon.conf"
@@ -98,7 +99,7 @@ def get_config():
### Remove config from file by delimiter
def remove_confs(delim_begin, delim_end, conf_file):
- os.system("sed -i '/"+delim_begin+"/,/"+delim_end+"/d' "+conf_file)
+ run("sed -i '/"+delim_begin+"/,/"+delim_end+"/d' "+conf_file)
### Checking certificate storage and notice if certificate not in /config directory
@@ -111,7 +112,7 @@ def check_cert_file_store(cert_name, file_path, dts_path):
else:
### Cpy file to /etc/ipsec.d/certs/ /etc/ipsec.d/cacerts/
# todo make check
- ret = os.system('cp -f '+file_path+' '+dts_path)
+ ret = run('cp -f '+file_path+' '+dts_path)
if ret:
raise ConfigError("L2TP VPN configuration error: Cannot copy "+file_path)
@@ -192,12 +193,12 @@ def generate(data):
remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_conf_flie)
def restart_ipsec():
- os.system('ipsec restart >&/dev/null')
+ run('ipsec restart >&/dev/null')
# counter for apply swanctl config
counter = 10
while counter <= 10:
if os.path.exists(charon_pidfile):
- os.system('swanctl -q >&/dev/null')
+ run('swanctl -q >&/dev/null')
break
counter -=1
sleep(1)
diff --git a/src/conf_mode/le_cert.py b/src/conf_mode/le_cert.py
index c657098e1..a4dbecbaa 100755
--- a/src/conf_mode/le_cert.py
+++ b/src/conf_mode/le_cert.py
@@ -18,11 +18,12 @@
import sys
import os
-import subprocess
import vyos.defaults
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import cmd, run
+
vyos_conf_scripts_dir = vyos.defaults.directories['conf_mode']
@@ -45,9 +46,9 @@ def request_certbot(cert):
certbot_cmd = 'certbot certonly -n --nginx --agree-tos --no-eff-email --expand {0} {1}'.format(email_flag, domain_flag)
- completed = subprocess.run(certbot_cmd, shell=True)
-
- return completed.returncode
+ cmd(certbot_cmd,
+ raising=ConfigError,
+ message="The certbot request failed for the specified domains.")
def get_config():
conf = Config()
@@ -84,28 +85,21 @@ def generate(cert):
# certbot will attempt to reload nginx, even with 'certonly';
# start nginx if not active
- ret = os.system('systemctl is-active --quiet nginx.ervice')
+ ret = run('systemctl is-active --quiet nginx.ervice')
if ret:
- os.system('sudo systemctl start nginx.service')
+ run('sudo systemctl start nginx.service')
- ret = request_certbot(cert)
- if ret:
- raise ConfigError("The certbot request failed for the"
- " specified domains.")
+ request_certbot(cert)
def apply(cert):
if cert is not None:
- os.system('sudo systemctl restart certbot.timer')
+ run('sudo systemctl restart certbot.timer')
else:
- os.system('sudo systemctl stop certbot.timer')
+ run('sudo systemctl stop certbot.timer')
return None
for dep in dependencies:
- cmd = '{0}/{1}'.format(vyos_conf_scripts_dir, dep)
- try:
- subprocess.check_call(cmd, shell=True)
- except subprocess.CalledProcessError as err:
- raise ConfigError(str(err))
+ cmd(f'{vyos_conf_scripts_dir}/{dep}', raising=ConfigError)
if __name__ == '__main__':
try:
diff --git a/src/conf_mode/lldp.py b/src/conf_mode/lldp.py
index 4e3dfc0b6..c090bba83 100755
--- a/src/conf_mode/lldp.py
+++ b/src/conf_mode/lldp.py
@@ -26,6 +26,8 @@ from vyos.validate import is_addr_assigned,is_loopback_addr
from vyos.defaults import directories as vyos_data_dir
from vyos.version import get_version_data
from vyos import ConfigError
+from vyos.util import run
+
config_file = "/etc/default/lldpd"
vyos_config_file = "/etc/lldpd.d/01-vyos.conf"
@@ -239,10 +241,10 @@ def generate(lldp):
def apply(lldp):
if lldp:
# start/restart lldp service
- os.system('sudo systemctl restart lldpd.service')
+ run('sudo systemctl restart lldpd.service')
else:
# LLDP service has been terminated
- os.system('sudo systemctl stop lldpd.service')
+ run('sudo systemctl stop lldpd.service')
os.unlink(config_file)
os.unlink(vyos_config_file)
diff --git a/src/conf_mode/mdns_repeater.py b/src/conf_mode/mdns_repeater.py
index f738cc6a6..2bccd9153 100755
--- a/src/conf_mode/mdns_repeater.py
+++ b/src/conf_mode/mdns_repeater.py
@@ -24,6 +24,8 @@ from netifaces import ifaddresses, AF_INET
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/default/mdns-repeater'
@@ -94,11 +96,11 @@ def generate(mdns):
def apply(mdns):
if (mdns is None) or mdns['disabled']:
- os.system('sudo systemctl stop mdns-repeater')
+ run('sudo systemctl stop mdns-repeater')
if os.path.exists(config_file):
os.unlink(config_file)
else:
- os.system('sudo systemctl restart mdns-repeater')
+ run('sudo systemctl restart mdns-repeater')
return None
diff --git a/src/conf_mode/ntp.py b/src/conf_mode/ntp.py
index 0f635556b..998022a8c 100755
--- a/src/conf_mode/ntp.py
+++ b/src/conf_mode/ntp.py
@@ -24,6 +24,8 @@ from sys import exit
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/ntp.conf'
@@ -112,10 +114,10 @@ def generate(ntp):
def apply(ntp):
if ntp is not None:
- os.system('sudo systemctl restart ntp.service')
+ run('sudo systemctl restart ntp.service')
else:
# NTP support is removed in the commit
- os.system('sudo systemctl stop ntp.service')
+ run('sudo systemctl stop ntp.service')
os.unlink(config_file)
return None
diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py
index 9940c80c5..52a9e54c2 100755
--- a/src/conf_mode/protocols_bfd.py
+++ b/src/conf_mode/protocols_bfd.py
@@ -24,6 +24,8 @@ from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos.validate import is_ipv6_link_local, is_ipv6
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/tmp/bfd.frr'
@@ -205,7 +207,16 @@ def apply(bfd):
if bfd is None:
return None
+<<<<<<< HEAD
os.system(f'vtysh -d bfdd -f {config_file}')
+=======
+ tmpl = jinja2.Template(config_tmpl)
+ config_text = tmpl.render(bfd)
+ with open(config_file, 'w') as f:
+ f.write(config_text)
+
+ run("sudo vtysh -d bfdd -f " + config_file)
+>>>>>>> util: T2226: covert most calls from os.system to util
if os.path.exists(config_file):
os.remove(config_file)
diff --git a/src/conf_mode/protocols_igmp.py b/src/conf_mode/protocols_igmp.py
index 0148b5dac..6e819a15a 100755
--- a/src/conf_mode/protocols_igmp.py
+++ b/src/conf_mode/protocols_igmp.py
@@ -23,6 +23,8 @@ from sys import exit
from vyos import ConfigError
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
+from vyos.util import run
+
config_file = r'/tmp/igmp.frr'
@@ -103,7 +105,7 @@ def apply(igmp):
return None
if os.path.exists(config_file):
- os.system("sudo vtysh -d pimd -f " + config_file)
+ run("sudo vtysh -d pimd -f " + config_file)
os.remove(config_file)
return None
diff --git a/src/conf_mode/protocols_mpls.py b/src/conf_mode/protocols_mpls.py
index 514fe5efb..6e5d08397 100755
--- a/src/conf_mode/protocols_mpls.py
+++ b/src/conf_mode/protocols_mpls.py
@@ -21,11 +21,13 @@ from jinja2 import FileSystemLoader, Environment
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/tmp/ldpd.frr'
def sysctl(name, value):
- os.system('sysctl -wq {}={}'.format(name, value))
+ run('sysctl -wq {}={}'.format(name, value))
def get_config():
conf = Config()
@@ -160,7 +162,7 @@ def apply(mpls):
operate_mpls_on_intfc(diactive_ifaces, 0)
if os.path.exists(config_file):
- os.system("sudo vtysh -d ldpd -f " + config_file)
+ run("sudo vtysh -d ldpd -f " + config_file)
os.remove(config_file)
return None
diff --git a/src/conf_mode/protocols_pim.py b/src/conf_mode/protocols_pim.py
index 7b360d62c..0e22d3a6b 100755
--- a/src/conf_mode/protocols_pim.py
+++ b/src/conf_mode/protocols_pim.py
@@ -23,6 +23,8 @@ from sys import exit
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/tmp/pimd.frr'
@@ -130,7 +132,11 @@ def apply(pim):
return None
if os.path.exists(config_file):
+<<<<<<< HEAD
os.system("vtysh -d pimd -f " + config_file)
+=======
+ run("sudo vtysh -d pimd -f " + config_file)
+>>>>>>> util: T2226: covert most calls from os.system to util
os.remove(config_file)
return None
diff --git a/src/conf_mode/salt-minion.py b/src/conf_mode/salt-minion.py
index bc1767454..bd1d44bc8 100755
--- a/src/conf_mode/salt-minion.py
+++ b/src/conf_mode/salt-minion.py
@@ -26,6 +26,8 @@ from urllib3 import PoolManager
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/salt/minion'
@@ -124,10 +126,10 @@ def generate(salt):
def apply(salt):
if salt is not None:
- os.system("sudo systemctl restart salt-minion")
+ run("sudo systemctl restart salt-minion")
else:
# Salt access is removed in the commit
- os.system("sudo systemctl stop salt-minion")
+ run("sudo systemctl stop salt-minion")
os.unlink(config_file)
return None
diff --git a/src/conf_mode/service-ipoe.py b/src/conf_mode/service-ipoe.py
index dd9616a62..5bd4aea2e 100755
--- a/src/conf_mode/service-ipoe.py
+++ b/src/conf_mode/service-ipoe.py
@@ -16,7 +16,6 @@
import os
import re
-import subprocess
from jinja2 import FileSystemLoader, Environment
from socket import socket, AF_INET, SOCK_STREAM
@@ -26,6 +25,7 @@ from time import sleep
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
ipoe_cnf_dir = r'/etc/accel-ppp/ipoe'
ipoe_cnf = ipoe_cnf_dir + r'/ipoe.config'
@@ -64,15 +64,8 @@ def _chk_con():
break
-def _accel_cmd(cmd=''):
- if not cmd:
- return None
- try:
- ret = subprocess.check_output(
- ['/usr/bin/accel-cmd', '-p', cmd_port, cmd]).decode().strip()
- return ret
- except:
- return 1
+def _accel_cmd(command):
+ return run('/usr/bin/accel-cmd -p {cmd_port} {command}')
##### Inline functions end ####
@@ -306,8 +299,7 @@ def apply(c):
return None
if not os.path.exists(pidfile):
- ret = subprocess.call(
- ['/usr/sbin/accel-pppd', '-c', ipoe_cnf, '-p', pidfile, '-d'])
+ ret = run(f'/usr/sbin/accel-pppd -c {ipoe_cnf} -p {pidfile} -d')
_chk_con()
if ret != 0 and os.path.exists(pidfile):
os.remove(pidfile)
diff --git a/src/conf_mode/service-pppoe.py b/src/conf_mode/service-pppoe.py
index afcc5ba99..d3fc82406 100755
--- a/src/conf_mode/service-pppoe.py
+++ b/src/conf_mode/service-pppoe.py
@@ -16,7 +16,6 @@
import os
import re
-import subprocess
from jinja2 import FileSystemLoader, Environment
from socket import socket, AF_INET, SOCK_STREAM
@@ -26,6 +25,7 @@ from time import sleep
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
pidfile = r'/var/run/accel_pppoe.pid'
pppoe_cnf_dir = r'/etc/accel-ppp/pppoe'
@@ -57,15 +57,8 @@ def _chk_con():
raise("failed to start pppoe server")
-def _accel_cmd(cmd=''):
- if not cmd:
- return None
- try:
- ret = subprocess.check_output(
- ['/usr/bin/accel-cmd', cmd]).decode().strip()
- return ret
- except:
- return 1
+def _accel_cmd(command):
+ return run(f'/usr/bin/accel-cmd {command}')
def get_config():
@@ -426,8 +419,7 @@ def apply(c):
return None
if not os.path.exists(pidfile):
- ret = subprocess.call(
- ['/usr/sbin/accel-pppd', '-c', pppoe_conf, '-p', pidfile, '-d'])
+ ret = run(f'/usr/sbin/accel-pppd -c {pppoe_conf} -p {pidfile} -d')
_chk_con()
if ret != 0 and os.path.exists(pidfile):
os.remove(pidfile)
diff --git a/src/conf_mode/service-router-advert.py b/src/conf_mode/service-router-advert.py
index 38c5cb2dc..0173b7242 100755
--- a/src/conf_mode/service-router-advert.py
+++ b/src/conf_mode/service-router-advert.py
@@ -23,6 +23,8 @@ from sys import exit
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/radvd.conf'
@@ -156,13 +158,13 @@ def generate(rtradv):
def apply(rtradv):
if not rtradv['interfaces']:
# bail out early - looks like removal from running config
- os.system('systemctl stop radvd.service')
+ run('systemctl stop radvd.service')
if os.path.exists(config_file):
os.unlink(config_file)
return None
- os.system('systemctl restart radvd.service')
+ run('systemctl restart radvd.service')
return None
if __name__ == '__main__':
diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py
index ed8c1d7e1..414236c88 100755
--- a/src/conf_mode/snmp.py
+++ b/src/conf_mode/snmp.py
@@ -27,6 +27,8 @@ from vyos.defaults import directories as vyos_data_dir
from vyos.validate import is_ipv4, is_addr_assigned
from vyos.version import get_version_data
from vyos import ConfigError
+from vyos.util import run
+
config_file_client = r'/etc/snmp/snmp.conf'
config_file_daemon = r'/etc/snmp/snmpd.conf'
@@ -507,7 +509,7 @@ def generate(snmp):
#
# As we are manipulating the snmpd user database we have to stop it first!
# This is even save if service is going to be removed
- os.system("systemctl stop snmpd.service")
+ run('systemctl stop snmpd.service')
config_files = [config_file_client, config_file_daemon, config_file_access,
config_file_user]
for file in config_files:
@@ -552,7 +554,7 @@ def apply(snmp):
return None
# start SNMP daemon
- os.system("systemctl restart snmpd.service")
+ run("systemctl restart snmpd.service")
# Passwords are not available immediately in the configuration file,
# after daemon startup - we wait until they have been processed by
@@ -593,15 +595,15 @@ def apply(snmp):
# Now update the running configuration
#
- # Currently when executing os.system() the environment does not
+ # Currently when executing run() the environment does not
# have the vyos_libexec_dir variable set, see Phabricator T685.
- os.system('/opt/vyatta/sbin/my_set service snmp v3 user "{0}" auth encrypted-key "{1}" > /dev/null'.format(cfg['user'], cfg['auth_pw']))
- os.system('/opt/vyatta/sbin/my_set service snmp v3 user "{0}" privacy encrypted-key "{1}" > /dev/null'.format(cfg['user'], cfg['priv_pw']))
- os.system('/opt/vyatta/sbin/my_delete service snmp v3 user "{0}" auth plaintext-key > /dev/null'.format(cfg['user']))
- os.system('/opt/vyatta/sbin/my_delete service snmp v3 user "{0}" privacy plaintext-key > /dev/null'.format(cfg['user']))
+ run('/opt/vyatta/sbin/my_set service snmp v3 user "{0}" auth encrypted-key "{1}" > /dev/null'.format(cfg['user'], cfg['auth_pw']))
+ run('/opt/vyatta/sbin/my_set service snmp v3 user "{0}" privacy encrypted-key "{1}" > /dev/null'.format(cfg['user'], cfg['priv_pw']))
+ run('/opt/vyatta/sbin/my_delete service snmp v3 user "{0}" auth plaintext-key > /dev/null'.format(cfg['user']))
+ run('/opt/vyatta/sbin/my_delete service snmp v3 user "{0}" privacy plaintext-key > /dev/null'.format(cfg['user']))
# Enable AgentX in FRR
- os.system('vtysh -c "configure terminal" -c "agentx" >/dev/null')
+ run('vtysh -c "configure terminal" -c "agentx" >/dev/null')
return None
diff --git a/src/conf_mode/ssh.py b/src/conf_mode/ssh.py
index 014045796..a85dcd7f2 100755
--- a/src/conf_mode/ssh.py
+++ b/src/conf_mode/ssh.py
@@ -21,6 +21,8 @@ from sys import exit
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/ssh/sshd_config'
@@ -131,10 +133,10 @@ def generate(ssh):
def apply(ssh):
if ssh is not None and 'port' in ssh.keys():
- os.system("sudo systemctl restart ssh.service")
+ run("sudo systemctl restart ssh.service")
else:
# SSH access is removed in the commit
- os.system("sudo systemctl stop ssh.service")
+ run("sudo systemctl stop ssh.service")
if os.path.isfile(config_file):
os.unlink(config_file)
diff --git a/src/conf_mode/system-ip.py b/src/conf_mode/system-ip.py
index 335507411..66f563939 100755
--- a/src/conf_mode/system-ip.py
+++ b/src/conf_mode/system-ip.py
@@ -20,6 +20,8 @@ from sys import exit
from copy import deepcopy
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import run
+
default_config_data = {
'arp_table': 8192,
@@ -29,7 +31,7 @@ default_config_data = {
}
def sysctl(name, value):
- os.system('sysctl -wq {}={}'.format(name, value))
+ run('sysctl -wq {}={}'.format(name, value))
def get_config():
ip_opt = deepcopy(default_config_data)
diff --git a/src/conf_mode/system-ipv6.py b/src/conf_mode/system-ipv6.py
index bd28ec357..4e3de6fe9 100755
--- a/src/conf_mode/system-ipv6.py
+++ b/src/conf_mode/system-ipv6.py
@@ -21,6 +21,8 @@ from sys import exit
from copy import deepcopy
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import run
+
ipv6_disable_file = '/etc/modprobe.d/vyos_disable_ipv6.conf'
@@ -35,7 +37,7 @@ default_config_data = {
}
def sysctl(name, value):
- os.system('sysctl -wq {}={}'.format(name, value))
+ run('sysctl -wq {}={}'.format(name, value))
def get_config():
ip_opt = deepcopy(default_config_data)
diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py
index 7acb0a9a2..7c99fce39 100755
--- a/src/conf_mode/system-login.py
+++ b/src/conf_mode/system-login.py
@@ -20,13 +20,13 @@ from jinja2 import FileSystemLoader, Environment
from psutil import users
from pwd import getpwall, getpwnam
from stat import S_IRUSR, S_IWUSR, S_IRWXU, S_IRGRP, S_IXGRP
-from subprocess import Popen, PIPE, STDOUT
from sys import exit
from vyos.config import Config
from vyos.configdict import list_diff
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import cmd, run
radius_config_file = "/etc/pam_radius_auth.conf"
@@ -52,10 +52,7 @@ def get_local_users():
def get_crypt_pw(password):
- command = '/usr/bin/mkpasswd --method=sha-512 {}'.format(password)
- p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True)
- tmp = p.communicate()[0].strip()
- return tmp.decode()
+ return cmd(f'/usr/bin/mkpasswd --method=sha-512 {password}')
def get_config():
@@ -210,8 +207,8 @@ def generate(login):
# remove old plaintext password
# and set new encrypted password
- os.system("vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set system login user '{}' authentication plaintext-password '' >/dev/null".format(user['name']))
- os.system("vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set system login user '{}' authentication encrypted-password '{}' >/dev/null".format(user['name'], user['password_encrypted']))
+ run("vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set system login user '{}' authentication plaintext-password '' >/dev/null".format(user['name']))
+ run("vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set system login user '{}' authentication encrypted-password '{}' >/dev/null".format(user['name'], user['password_encrypted']))
if len(login['radius_server']) > 0:
# Prepare Jinja2 template loader from files
@@ -238,27 +235,27 @@ def apply(login):
for user in login['add_users']:
# make new user using vyatta shell and make home directory (-m),
# default group of 100 (users)
- cmd = "useradd -m -N"
+ command = "useradd -m -N"
# check if user already exists:
if user['name'] in get_local_users():
# update existing account
- cmd = "usermod"
+ command = "usermod"
# we need to use '' quotes when passing formatted data to the shell
# else it will not work as some data parts are lost in translation
- cmd += " -p '{}'".format(user['password_encrypted'])
- cmd += " -s /bin/vbash"
+ command += " -p '{}'".format(user['password_encrypted'])
+ command += " -s /bin/vbash"
if user['full_name']:
- cmd += " -c '{}'".format(user['full_name'])
+ command += " -c '{}'".format(user['full_name'])
if user['home_dir']:
- cmd += " -d '{}'".format(user['home_dir'])
+ command += " -d '{}'".format(user['home_dir'])
- cmd += " -G frrvty,vyattacfg,sudo,adm,dip,disk"
- cmd += " {}".format(user['name'])
+ command += " -G frrvty,vyattacfg,sudo,adm,dip,disk"
+ command += " {}".format(user['name'])
try:
- os.system(cmd)
+ run(command)
uid = getpwnam(user['name']).pw_uid
gid = getpwnam(user['name']).pw_gid
@@ -298,10 +295,10 @@ def apply(login):
# Logout user if he is logged in
if user in list(set([tmp[0] for tmp in users()])):
print('{} is logged in, forcing logout'.format(user))
- os.system('pkill -HUP -u {}'.format(user))
+ run('pkill -HUP -u {}'.format(user))
# Remove user account but leave home directory to be safe
- os.system('userdel -r {} 2>/dev/null'.format(user))
+ run('userdel -r {} 2>/dev/null'.format(user))
except Exception as e:
raise ConfigError('Deleting user "{}" raised an exception: {}'.format(user, e))
@@ -312,10 +309,10 @@ def apply(login):
if len(login['radius_server']) > 0:
try:
# Enable RADIUS in PAM
- os.system("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --enable radius")
+ run("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --enable radius")
# Make NSS system aware of RADIUS, too
- cmd = "sed -i -e \'/\smapname/b\' \
+ command = "sed -i -e \'/\smapname/b\' \
-e \'/^passwd:/s/\s\s*/&mapuid /\' \
-e \'/^passwd:.*#/s/#.*/mapname &/\' \
-e \'/^passwd:[^#]*$/s/$/ mapname &/\' \
@@ -323,7 +320,7 @@ def apply(login):
-e \'/^group:[^#]*$/s/: */&mapname /\' \
/etc/nsswitch.conf"
- os.system(cmd)
+ run(command)
except Exception as e:
raise ConfigError('RADIUS configuration failed: {}'.format(e))
@@ -331,15 +328,15 @@ def apply(login):
else:
try:
# Disable RADIUS in PAM
- os.system("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --remove radius")
+ run("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --remove radius")
- cmd = "sed -i -e \'/^passwd:.*mapuid[ \t]/s/mapuid[ \t]//\' \
+ command = "sed -i -e \'/^passwd:.*mapuid[ \t]/s/mapuid[ \t]//\' \
-e \'/^passwd:.*[ \t]mapname/s/[ \t]mapname//\' \
-e \'/^group:.*[ \t]mapname/s/[ \t]mapname//\' \
-e \'s/[ \t]*$//\' \
/etc/nsswitch.conf"
- os.system(cmd)
+ run(command)
except Exception as e:
raise ConfigError('Removing RADIUS configuration failed'.format(e))
diff --git a/src/conf_mode/system-options.py b/src/conf_mode/system-options.py
index a893e98b3..063a82463 100755
--- a/src/conf_mode/system-options.py
+++ b/src/conf_mode/system-options.py
@@ -20,6 +20,7 @@ from sys import exit
from copy import deepcopy
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import run
systemd_ctrl_alt_del = '/lib/systemd/system/ctrl-alt-del.target'
@@ -51,9 +52,9 @@ def generate(opt):
def apply(opt):
# Beep action
if opt['beep_if_fully_booted']:
- os.system('systemctl enable vyos-beep.service >/dev/null 2>&1')
+ run('systemctl enable vyos-beep.service >/dev/null 2>&1')
else:
- os.system('systemctl disable vyos-beep.service >/dev/null 2>&1')
+ run('systemctl disable vyos-beep.service >/dev/null 2>&1')
# Ctrl-Alt-Delete action
if opt['ctrl_alt_del'] == 'ignore':
diff --git a/src/conf_mode/system-syslog.py b/src/conf_mode/system-syslog.py
index 8c0a6629c..25b9b5bed 100755
--- a/src/conf_mode/system-syslog.py
+++ b/src/conf_mode/system-syslog.py
@@ -22,8 +22,8 @@ from sys import exit
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
-from vyos.util import subprocess_cmd
from vyos import ConfigError
+from vyos.util import run
def get_config():
c = Config()
@@ -253,10 +253,8 @@ def verify(c):
def apply(c):
if not c:
- subprocess_cmd('systemctl stop syslog')
- return None
-
- subprocess_cmd('systemctl restart syslog')
+ return run('systemctl stop syslog')
+ return run('systemctl restart syslog')
if __name__ == '__main__':
try:
diff --git a/src/conf_mode/system-timezone.py b/src/conf_mode/system-timezone.py
index d715bd27e..2f8dc9e89 100755
--- a/src/conf_mode/system-timezone.py
+++ b/src/conf_mode/system-timezone.py
@@ -20,6 +20,8 @@ import os
from copy import deepcopy
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import run
+
default_config_data = {
'name': 'UTC'
@@ -40,9 +42,7 @@ def generate(tz):
pass
def apply(tz):
- cmd = '/usr/bin/timedatectl set-timezone {}'.format(tz['name'])
- os.system(cmd)
- pass
+ run('/usr/bin/timedatectl set-timezone {}'.format(tz['name']))
if __name__ == '__main__':
try:
diff --git a/src/conf_mode/tftp_server.py b/src/conf_mode/tftp_server.py
index fe2da8455..df8155084 100755
--- a/src/conf_mode/tftp_server.py
+++ b/src/conf_mode/tftp_server.py
@@ -27,6 +27,8 @@ from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos.validate import is_ipv4, is_addr_assigned
from vyos import ConfigError
+from vyos.util import run
+
config_file = r'/etc/default/tftpd'
@@ -113,7 +115,7 @@ def generate(tftpd):
def apply(tftpd):
# stop all services first - then we will decide
- os.system('systemctl stop tftpd@{0..20}')
+ run('systemctl stop tftpd@{0..20}')
# bail out early - e.g. service deletion
if tftpd is None:
@@ -138,7 +140,7 @@ def apply(tftpd):
idx = 0
for listen in tftpd['listen']:
- os.system('systemctl restart tftpd@{0}.service'.format(idx))
+ run('systemctl restart tftpd@{0}.service'.format(idx))
idx = idx + 1
return None
diff --git a/src/conf_mode/vpn-pptp.py b/src/conf_mode/vpn-pptp.py
index b1204a505..45b2c4b40 100755
--- a/src/conf_mode/vpn-pptp.py
+++ b/src/conf_mode/vpn-pptp.py
@@ -16,7 +16,6 @@
import os
import re
-import subprocess
from jinja2 import FileSystemLoader, Environment
from socket import socket, AF_INET, SOCK_STREAM
@@ -26,6 +25,7 @@ from time import sleep
from vyos.config import Config
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
pidfile = r'/var/run/accel_pptp.pid'
pptp_cnf_dir = r'/etc/accel-ppp/pptp'
@@ -50,17 +50,9 @@ def _chk_con():
raise("failed to start pptp server")
break
-# chap_secrets file if auth mode local
-def _accel_cmd(cmd=''):
- if not cmd:
- return None
- try:
- ret = subprocess.check_output(
- ['/usr/bin/accel-cmd', '-p', '2003', cmd]).decode().strip()
- return ret
- except:
- return 1
+def _accel_cmd(command):
+ return run('/usr/bin/accel-cmd -p 2003 {command}')
###
# inline helper functions end
@@ -256,8 +248,7 @@ def apply(c):
return None
if not os.path.exists(pidfile):
- ret = subprocess.call(
- ['/usr/sbin/accel-pppd', '-c', pptp_conf, '-p', pidfile, '-d'])
+ ret = run(f'/usr/sbin/accel-pppd -c {pptp_conf} -p {pidfile} -d')
_chk_con()
if ret != 0 and os.path.exists(pidfile):
os.remove(pidfile)
diff --git a/src/conf_mode/vpn_sstp.py b/src/conf_mode/vpn_sstp.py
index 66b1822df..ca0844c50 100755
--- a/src/conf_mode/vpn_sstp.py
+++ b/src/conf_mode/vpn_sstp.py
@@ -18,16 +18,16 @@ import os
from time import sleep
from sys import exit
-from subprocess import check_output
from socket import socket, AF_INET, SOCK_STREAM
from copy import deepcopy
from stat import S_IRUSR, S_IWUSR, S_IRGRP
from jinja2 import FileSystemLoader, Environment
from vyos.config import Config
-from vyos.defaults import directories as vyos_data_dir
-from vyos.util import process_running, subprocess_cmd
from vyos import ConfigError
+from vyos.defaults import directories as vyos_data_dir
+from vyos.util import process_running
+from vyos.util import process_running, cmd, run
pidfile = r'/var/run/accel_sstp.pid'
sstp_cnf_dir = r'/etc/accel-ppp/sstp'
@@ -53,16 +53,9 @@ def chk_con():
raise("failed to start sstp server")
break
-def accel_cmd(cmd):
- if not cmd:
- return None
-
- try:
- ret = check_output(['/usr/bin/accel-cmd', '-p', '2005', cmd])
- return ret.decode().strip()
- except:
- return 1
+def _accel_cmd(command):
+ return run(f'/usr/bin/accel-cmd -p 2005 {command}')
default_config_data = {
'local_users' : [],
@@ -363,12 +356,12 @@ def generate(sstp):
def apply(sstp):
if sstp is None:
if process_running(pidfile):
- cmd = 'start-stop-daemon'
- cmd += ' --stop '
- cmd += ' --quiet'
- cmd += ' --oknodo'
- cmd += ' --pidfile ' + pidfile
- subprocess_cmd(cmd)
+ command = 'start-stop-daemon'
+ command += ' --stop '
+ command += ' --quiet'
+ command += ' --oknodo'
+ command += ' --pidfile ' + pidfile
+ cmd(command)
if os.path.exists(pidfile):
os.remove(pidfile)
@@ -379,23 +372,23 @@ def apply(sstp):
if os.path.exists(pidfile):
os.remove(pidfile)
- cmd = 'start-stop-daemon'
- cmd += ' --start '
- cmd += ' --quiet'
- cmd += ' --oknodo'
- cmd += ' --pidfile ' + pidfile
- cmd += ' --exec /usr/sbin/accel-pppd'
+ command = 'start-stop-daemon'
+ command += ' --start '
+ command += ' --quiet'
+ command += ' --oknodo'
+ command += ' --pidfile ' + pidfile
+ command += ' --exec /usr/sbin/accel-pppd'
# now pass arguments to accel-pppd binary
- cmd += ' --'
- cmd += ' -c ' + sstp_conf
- cmd += ' -p ' + pidfile
- cmd += ' -d'
- subprocess_cmd(cmd)
+ command += ' --'
+ command += ' -c ' + sstp_conf
+ command += ' -p ' + pidfile
+ command += ' -d'
+ cmd(command)
chk_con()
else:
- accel_cmd('restart')
+ _accel_cmd('restart')
if __name__ == '__main__':
diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py
index 8cf4b72ae..07466f3aa 100755
--- a/src/conf_mode/vrf.py
+++ b/src/conf_mode/vrf.py
@@ -20,13 +20,12 @@ from sys import exit
from copy import deepcopy
from jinja2 import FileSystemLoader, Environment
from json import loads
-from subprocess import check_output, CalledProcessError
from vyos.config import Config
from vyos.configdict import list_diff
from vyos.defaults import directories as vyos_data_dir
from vyos.ifconfig import Interface
-from vyos.util import read_file
+from vyos.util import read_file, cmd
from vyos import ConfigError
config_file = r'/etc/iproute2/rt_tables.d/vyos-vrf.conf'
@@ -40,14 +39,11 @@ default_config_data = {
}
def _cmd(command):
- try:
- check_output(command.split())
- except CalledProcessError as e:
- raise ConfigError(f'Error changing VRF: {e}')
+ cmd(command, raising=ConfigError, message='Error changing VRF')
def list_rules():
command = 'ip -j -4 rule show'
- answer = loads(check_output(command.split()).decode())
+ answer = loads(cmd(command))
return [_ for _ in answer if _]
def vrf_interfaces(c, match):
diff --git a/src/conf_mode/vrrp.py b/src/conf_mode/vrrp.py
index 8683faca7..d3e3710d1 100755
--- a/src/conf_mode/vrrp.py
+++ b/src/conf_mode/vrrp.py
@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
-import subprocess
from sys import exit
from ipaddress import ip_address, ip_interface, IPv4Interface, IPv6Interface, IPv4Address, IPv6Address
@@ -28,6 +27,7 @@ import vyos.keepalived
from vyos.defaults import directories as vyos_data_dir
from vyos import ConfigError
+from vyos.util import run
daemon_file = "/etc/default/keepalived"
config_file = "/etc/keepalived/keepalived.conf"
@@ -242,17 +242,17 @@ def apply(data):
if not vyos.keepalived.vrrp_running():
print("Starting the VRRP process")
- ret = subprocess.call("sudo systemctl restart keepalived.service", shell=True)
+ ret = run("sudo systemctl restart keepalived.service")
else:
print("Reloading the VRRP process")
- ret = subprocess.call("sudo systemctl reload keepalived.service", shell=True)
+ ret = run("sudo systemctl reload keepalived.service")
if ret != 0:
raise ConfigError("keepalived failed to start")
else:
# VRRP is removed in the commit
print("Stopping the VRRP process")
- subprocess.call("sudo systemctl stop keepalived.service", shell=True)
+ run("sudo systemctl stop keepalived.service")
os.unlink(config_file)
return None
diff --git a/src/conf_mode/vyos_cert.py b/src/conf_mode/vyos_cert.py
index 4a44573ca..8b8953cb7 100755
--- a/src/conf_mode/vyos_cert.py
+++ b/src/conf_mode/vyos_cert.py
@@ -18,7 +18,6 @@
import sys
import os
-import subprocess
import tempfile
import pathlib
import ssl
@@ -26,6 +25,7 @@ import ssl
import vyos.defaults
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import cmd
vyos_conf_scripts_dir = vyos.defaults.directories['conf_mode']
@@ -49,16 +49,16 @@ def status_self_signed(cert_data):
# check if certificate is 1/2 past lifetime, with openssl -checkend
end_days = int(cert_data['lifetime'])
end_seconds = int(0.5*60*60*24*end_days)
- checkend_cmd = ('openssl x509 -checkend {end} -noout -in {crt}'
- ''.format(end=end_seconds, **cert_data))
+ checkend_cmd = 'openssl x509 -checkend {end} -noout -in {crt}'.format(end=end_seconds, **cert_data)
try:
- subprocess.check_call(checkend_cmd, shell=True)
+ cmd(checkend_cmd, message='Called process error')
return True
- except subprocess.CalledProcessError as err:
- if err.returncode == 1:
+ except OSError as err:
+ if err.errno == 1:
return False
- else:
- print("Called process error: {}.".format(err))
+ print(err)
+ # XXX: This seems wrong to continue on failure
+ # implicitely returning None
def generate_self_signed(cert_data):
san_config = None
@@ -86,9 +86,10 @@ def generate_self_signed(cert_data):
''.format(**cert_data))
try:
- subprocess.check_call(openssl_req_cmd, shell=True)
- except subprocess.CalledProcessError as err:
- print("Called process error: {}.".format(err))
+ cmd(openssl_req_cmd, message='Called process error')
+ except OSError as err:
+ print(err)
+ # XXX: seems wrong to ignore the failure
os.chmod('{key}'.format(**cert_data), 0o400)
@@ -126,11 +127,8 @@ def generate(vyos_cert):
def apply(vyos_cert):
for dep in dependencies:
- cmd = '{0}/{1}'.format(vyos_conf_scripts_dir, dep)
- try:
- subprocess.check_call(cmd, shell=True)
- except subprocess.CalledProcessError as err:
- raise ConfigError("{}.".format(err))
+ command = '{0}/{1}'.format(vyos_conf_scripts_dir, dep)
+ cmd(command, raising=ConfigError)
if __name__ == '__main__':
try:
diff --git a/src/etc/vmware-tools/scripts/resume-vm-default.d/ether-resume.py b/src/etc/vmware-tools/scripts/resume-vm-default.d/ether-resume.py
index f8f790bf1..dc751c45c 100755
--- a/src/etc/vmware-tools/scripts/resume-vm-default.d/ether-resume.py
+++ b/src/etc/vmware-tools/scripts/resume-vm-default.d/ether-resume.py
@@ -15,11 +15,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
-import subprocess
import syslog as sl
from vyos.config import Config
from vyos import ConfigError
+from vyos.util import run
def get_config():
@@ -45,7 +45,7 @@ def apply(config):
# bring the interface up
cmd = ["ip", "link", "set", "dev", intf, "up"]
sl.syslog(sl.LOG_NOTICE, " ".join(cmd))
- subprocess.call(cmd)
+ run(cmd)
# add configured addresses to interface
for addr in addresses:
@@ -54,7 +54,7 @@ def apply(config):
else:
cmd = ["ip", "address", "add", addr, "dev", intf]
sl.syslog(sl.LOG_NOTICE, " ".join(cmd))
- subprocess.call(cmd)
+ run(cmd)
if __name__ == '__main__':
diff --git a/src/helpers/run-config-migration.py b/src/helpers/run-config-migration.py
index 3c06e38f8..cc7166c22 100755
--- a/src/helpers/run-config-migration.py
+++ b/src/helpers/run-config-migration.py
@@ -19,7 +19,8 @@ import os
import sys
import argparse
import datetime
-import subprocess
+
+from vyos.util import cmd
from vyos.migrator import Migrator, VirtualMigrator
def main():
@@ -61,12 +62,7 @@ def main():
'{0:%Y-%m-%d-%H%M%S}'.format(datetime.datetime.now()),
'pre-migration'])
- try:
- subprocess.check_call(['cp', '-p', config_file_name,
- backup_file_name])
- except subprocess.CalledProcessError as err:
- print("Called process error: {}.".format(err))
- sys.exit(1)
+ cmd(f'cp -p {config_file_name} {backup_file_name}')
if not virtual:
virtual_migration = VirtualMigrator(config_file_name)
diff --git a/src/helpers/validate-value.py b/src/helpers/validate-value.py
index 36f996d38..fab6ca81e 100755
--- a/src/helpers/validate-value.py
+++ b/src/helpers/validate-value.py
@@ -5,6 +5,8 @@ import os
import sys
import argparse
+from vyos.util import run
+
parser = argparse.ArgumentParser()
parser.add_argument('--regex', action='append')
parser.add_argument('--exec', action='append')
@@ -31,7 +33,7 @@ try:
cmd = "{0} {1}".format(cmd, args.value)
if debug:
print(cmd)
- res = os.system(cmd)
+ res = run(cmd)
if res == 0:
sys.exit(0)
except Exception as exn:
diff --git a/src/helpers/vyos-boot-config-loader.py b/src/helpers/vyos-boot-config-loader.py
index 58483fe50..c5bf22f10 100755
--- a/src/helpers/vyos-boot-config-loader.py
+++ b/src/helpers/vyos-boot-config-loader.py
@@ -20,13 +20,13 @@ 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
+from vyos.util import cmd
STATUS_FILE = '/tmp/vyos-config-status'
TRACE_FILE = '/tmp/boot-config-trace'
@@ -102,12 +102,7 @@ def failsafe(config_file_name):
'authentication',
'encrypted-password'])
- cmd = ("useradd -s /bin/bash -G 'users,sudo' -m -N -p '{0}' "
- "vyos".format(passwd))
- try:
- subprocess.check_call(cmd, shell=True)
- except subprocess.CalledProcessError as e:
- sys.exit("{0}".format(e))
+ cmd(f"useradd -s /bin/bash -G 'users,sudo' -m -N -p '{passwd}' vyos")
if __name__ == '__main__':
if len(sys.argv) < 2:
diff --git a/src/helpers/vyos-bridge-sync.py b/src/helpers/vyos-bridge-sync.py
index 495eb5d40..097d28d85 100755
--- a/src/helpers/vyos-bridge-sync.py
+++ b/src/helpers/vyos-bridge-sync.py
@@ -21,16 +21,12 @@
# to the bridge automatically once it's available
import argparse
-import subprocess
-
from sys import exit
from time import sleep
+
from vyos.config import Config
+from vyos.util import cmd, run
-def subprocess_cmd(command):
- process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=True)
- proc_stdout = process.communicate()[0].strip()
- pass
if __name__ == '__main__':
parser = argparse.ArgumentParser()
@@ -45,9 +41,11 @@ if __name__ == '__main__':
for bridge in conf.list_nodes('interfaces bridge'):
for member_if in conf.list_nodes('interfaces bridge {} member interface'.format(bridge)):
if args.interface == member_if:
- cmd = 'brctl addif "{}" "{}"'.format(bridge, args.interface)
+ command = 'brctl addif "{}" "{}"'.format(bridge, args.interface)
# let interfaces etc. settle - especially required for OpenVPN bridged interfaces
sleep(4)
- subprocess_cmd(cmd)
+ # XXX: This is ignoring any issue, should be cmd but kept as it
+ # XXX: during the migration to not cause any regression
+ run(command)
exit(0)
diff --git a/src/helpers/vyos-load-config.py b/src/helpers/vyos-load-config.py
index 693529c23..a9fa15778 100755
--- a/src/helpers/vyos-load-config.py
+++ b/src/helpers/vyos-load-config.py
@@ -30,25 +30,19 @@ import vyos.remote
from vyos.config import Config, VyOSError
from vyos.migrator import Migrator, VirtualMigrator, MigratorError
-system_config_file = 'config.boot'
-
class LoadConfig(Config):
"""A subclass for calling 'loadFile'.
This does not belong in config.py, and only has a single caller.
"""
- def load_config(self, file_path):
- cmd = [self._cli_shell_api, 'loadFile', file_path]
- self._run(cmd)
+ def load_config(self, path):
+ return self._run(['/bin/cli-shell-api','loadFile',path])
-if len(sys.argv) > 1:
- file_name = sys.argv[1]
-else:
- file_name = system_config_file
+file_name = sys.argv[1] if len(sys.argv) > 1 else 'config.boot'
configdir = vyos.defaults.directories['config']
-
protocols = ['scp', 'sftp', 'http', 'https', 'ftp', 'tftp']
+
if any(x in file_name for x in protocols):
config_file = vyos.remote.get_remote_config(file_name)
if not config_file:
diff --git a/src/helpers/vyos-merge-config.py b/src/helpers/vyos-merge-config.py
index 10a5ea4bc..6546c03e3 100755
--- a/src/helpers/vyos-merge-config.py
+++ b/src/helpers/vyos-merge-config.py
@@ -17,13 +17,13 @@
import sys
import os
-import subprocess
import tempfile
import vyos.defaults
import vyos.remote
from vyos.config import Config
from vyos.configtree import ConfigTree
from vyos.migrator import Migrator, VirtualMigrator
+from vyos.util import cmd
if (len(sys.argv) < 2):
@@ -100,12 +100,10 @@ if path:
add_cmds = [ cmd for cmd in add_cmds if path in cmd ]
for cmd in add_cmds:
- cmd = "/opt/vyatta/sbin/my_" + cmd
-
try:
- subprocess.check_call(cmd, shell=True)
- except subprocess.CalledProcessError as err:
- print("Called process error: {}.".format(err))
+ cmd(f'/opt/vyatta/sbin/my_{cmd}', message='Called process error')
+ except OSError as err:
+ print(err)
if effective_config.session_changed():
print("Merge complete. Use 'commit' to make changes effective.")
diff --git a/src/migration-scripts/system/12-to-13 b/src/migration-scripts/system/12-to-13
index 5f7413d46..5b068f4fc 100755
--- a/src/migration-scripts/system/12-to-13
+++ b/src/migration-scripts/system/12-to-13
@@ -12,12 +12,8 @@ import re
import sys
from vyos.configtree import ConfigTree
-from subprocess import Popen, PIPE, STDOUT
+from vyos.util import cmd
-def _cmd(cmd):
- p = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True)
- tmp = p.communicate()[0].strip()
- return tmp.decode()
if (len(sys.argv) < 1):
print("Must specify file name!")
@@ -37,8 +33,11 @@ else:
tz = config.return_value(tz_base)
# retrieve all valid timezones
- tz_data = _cmd('find /usr/share/zoneinfo/posix -type f -or -type l | sed -e s:/usr/share/zoneinfo/posix/::')
- tz_data = tz_data.split('\n')
+ try:
+ tz_datas = cmd('find /usr/share/zoneinfo/posix -type f -or -type l | sed -e s:/usr/share/zoneinfo/posix/::')
+ except OSError:
+ tz_datas = ''
+ tz_data = tz_datas.split('\n')
if re.match(r'[Ll][Oo][Ss].+', tz):
tz = 'America/Los_Angeles'
diff --git a/src/op_mode/clear_conntrack.py b/src/op_mode/clear_conntrack.py
index 0e52b9086..423694187 100755
--- a/src/op_mode/clear_conntrack.py
+++ b/src/op_mode/clear_conntrack.py
@@ -14,13 +14,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import subprocess
import sys
from vyos.util import ask_yes_no
+from vyos.util import cmd, DEVNULL
if not ask_yes_no("This will clear all currently tracked and expected connections. Continue?"):
sys.exit(1)
else:
- subprocess.check_call(['/usr/sbin/conntrack -F'], shell=True, stderr=subprocess.DEVNULL)
- subprocess.check_call(['/usr/sbin/conntrack -F expect'], shell=True, stderr=subprocess.DEVNULL)
+ cmd('/usr/sbin/conntrack -F', stderr=DEVNULL)
+ cmd('/usr/sbin/conntrack -F expect', stderr=DEVNULL)
diff --git a/src/op_mode/connect_disconnect.py b/src/op_mode/connect_disconnect.py
index a22615096..192fd80ec 100755
--- a/src/op_mode/connect_disconnect.py
+++ b/src/op_mode/connect_disconnect.py
@@ -21,6 +21,9 @@ from sys import exit
from psutil import process_iter
from time import strftime, localtime, time
+from vyos.util import run
+
+
PPP_LOGFILE = '/var/log/vyatta/ppp_{}.log'
def check_interface(interface):
@@ -56,8 +59,7 @@ def connect(interface):
tm = strftime("%a %d %b %Y %I:%M:%S %p %Z", localtime(time()))
with open(PPP_LOGFILE.format(interface), 'a') as f:
f.write('{}: user {} started PPP daemon for {} by connect command\n'.format(tm, user, interface))
- cmd = 'umask 0; setsid sh -c "nohup /usr/sbin/pppd call {0} > /tmp/{0}.log 2>&1 &"'.format(interface)
- os.system(cmd)
+ run('umask 0; setsid sh -c "nohup /usr/sbin/pppd call {0} > /tmp/{0}.log 2>&1 &"'.format(interface))
def disconnect(interface):
@@ -75,8 +77,7 @@ def disconnect(interface):
tm = strftime("%a %d %b %Y %I:%M:%S %p %Z", localtime(time()))
with open(PPP_LOGFILE.format(interface), 'a') as f:
f.write('{}: user {} stopped PPP daemon for {} by disconnect command\n'.format(tm, user, interface))
- cmd = '/usr/bin/poff "{}"'.format(interface)
- os.system(cmd)
+ run('/usr/bin/poff "{}"'.format(interface))
def main():
parser = argparse.ArgumentParser()
diff --git a/src/op_mode/dns_forwarding_reset.py b/src/op_mode/dns_forwarding_reset.py
index da4fba3a2..93c2444b9 100755
--- a/src/op_mode/dns_forwarding_reset.py
+++ b/src/op_mode/dns_forwarding_reset.py
@@ -25,6 +25,8 @@ import sys
import argparse
import vyos.config
+from vyos.util import run
+
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--all", action="store_true", help="Reset all cache")
@@ -40,10 +42,10 @@ if __name__ == '__main__':
sys.exit(0)
if args.all:
- os.system("rec_control wipe-cache \'.$\'")
+ run("rec_control wipe-cache \'.$\'")
sys.exit(1)
elif args.domain:
- os.system("rec_control wipe-cache \'{0}$\'".format(args.domain))
+ run("rec_control wipe-cache \'{0}$\'".format(args.domain))
else:
parser.print_help()
sys.exit(1)
diff --git a/src/op_mode/dns_forwarding_statistics.py b/src/op_mode/dns_forwarding_statistics.py
index f626244a8..c400a72cd 100755
--- a/src/op_mode/dns_forwarding_statistics.py
+++ b/src/op_mode/dns_forwarding_statistics.py
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
-import subprocess
import jinja2
import sys
from vyos.config import Config
+from vyos.config import cmd
PDNS_CMD='/usr/bin/rec_control'
@@ -26,8 +26,8 @@ if __name__ == '__main__':
data = {}
- data['cache_entries'] = subprocess.check_output([PDNS_CMD, 'get cache-entries']).decode()
- data['cache_size'] = "{0:.2f}".format( int(subprocess.check_output([PDNS_CMD, 'get cache-bytes']).decode()) / 1024 )
+ data['cache_entries'] = cmd(f'{PDNS_CMD} get cache-entries')
+ data['cache_size'] = "{0:.2f}".format( int(cmd(f'{PDNS_CMD} get cache-bytes')) / 1024 )
tmpl = jinja2.Template(OUT_TMPL_SRC)
print(tmpl.render(data))
diff --git a/src/op_mode/dynamic_dns.py b/src/op_mode/dynamic_dns.py
index 0d457e247..d991848ad 100755
--- a/src/op_mode/dynamic_dns.py
+++ b/src/op_mode/dynamic_dns.py
@@ -21,6 +21,8 @@ import sys
import time
from vyos.config import Config
+from vyos.util import run
+
cache_file = r'/var/cache/ddclient/ddclient.cache'
@@ -84,9 +86,9 @@ def show_status():
def update_ddns():
- os.system('systemctl stop ddclient')
+ run('systemctl stop ddclient')
os.remove(cache_file)
- os.system('systemctl start ddclient')
+ run('systemctl start ddclient')
def main():
diff --git a/src/op_mode/flow_accounting_op.py b/src/op_mode/flow_accounting_op.py
index a39eaf871..7f3ad7476 100755
--- a/src/op_mode/flow_accounting_op.py
+++ b/src/op_mode/flow_accounting_op.py
@@ -19,10 +19,11 @@ import sys
import argparse
import re
import ipaddress
-import subprocess
import os.path
from tabulate import tabulate
+from vyos.util import cmd, run
+
# some default values
uacctd_pidfile = '/var/run/uacctd.pid'
uacctd_pipefile = '/tmp/uacctd.pipe'
@@ -69,26 +70,16 @@ def _is_host(host):
# check if flow-accounting running
def _uacctd_running():
- command = "/usr/bin/sudo /bin/systemctl status uacctd > /dev/null"
- return_code = subprocess.call(command, shell=True)
- if not return_code == 0:
- return False
-
- # return True if all checks were passed
- return True
+ command = '/usr/bin/sudo /bin/systemctl status uacctd > /dev/null'
+ return run(command) == 0
# get list of interfaces
def _get_ifaces_dict():
# run command to get ifaces list
- command = "/bin/ip link show"
- process = subprocess.Popen(command.split(' '), stdout=subprocess.PIPE, universal_newlines=True)
- stdout, stderr = process.communicate()
- if not process.returncode == 0:
- print("Failed to get interfaces list: command \"{}\" returned exit code: {}".format(command, process.returncode))
- sys.exit(1)
+ out = cmd('/bin/ip link show', universal_newlines=True)
# read output
- ifaces_out = stdout.splitlines()
+ ifaces_out = out.splitlines()
# make a dictionary with interfaces and indexes
ifaces_dict = {}
@@ -103,15 +94,12 @@ def _get_ifaces_dict():
# get list of flows
def _get_flows_list():
# run command to get flows list
- command = "/usr/bin/pmacct -s -O json -T flows -p {}".format(uacctd_pipefile)
- process = subprocess.Popen(command.split(' '), stdout=subprocess.PIPE, universal_newlines=True)
- stdout, stderr = process.communicate()
- if not process.returncode == 0:
- print("Failed to get flows list: command \"{}\" returned exit code: {}\nError: {}".format(command, process.returncode, stderr))
- sys.exit(1)
+ out = cmd(f'/usr/bin/pmacct -s -O json -T flows -p {uacctd_pipefile}',
+ universal_newlines=True,
+ message='Failed to get flows list')
# read output
- flows_out = stdout.splitlines()
+ flows_out = out.splitlines()
# make a list with flows
flows_list = []
@@ -208,21 +196,15 @@ if not _uacctd_running():
# restart pmacct daemon
if cmd_args.action == 'restart':
# run command to restart flow-accounting
- command = '/usr/bin/sudo /bin/systemctl restart uacctd'
- return_code = subprocess.call(command.split(' '))
- if not return_code == 0:
- print("Failed to restart flow-accounting: command \"{}\" returned exit code: {}".format(command, return_code))
- sys.exit(1)
+ cmd('/usr/bin/sudo /bin/systemctl restart uacctd',
+ message='Failed to restart flow-accounting')
# clear in-memory collected flows
if cmd_args.action == 'clear':
_check_imt()
# run command to clear flows
- command = "/usr/bin/pmacct -e -p {}".format(uacctd_pipefile)
- return_code = subprocess.call(command.split(' '))
- if not return_code == 0:
- print("Failed to clear flows: command \"{}\" returned exit code: {}".format(command, return_code))
- sys.exit(1)
+ cmd(f'/usr/bin/pmacct -e -p {uacctd_pipefile}',
+ message='Failed to clear flows')
# show table with flows
if cmd_args.action == 'show':
diff --git a/src/op_mode/format_disk.py b/src/op_mode/format_disk.py
index 5a3b250ee..9d3797f17 100755
--- a/src/op_mode/format_disk.py
+++ b/src/op_mode/format_disk.py
@@ -17,13 +17,12 @@
import argparse
import os
import re
-import subprocess
import sys
from datetime import datetime
from time import sleep
from vyos.util import is_admin, ask_yes_no
-
+from vyos.util import run, cmd, DEVNULL
def list_disks():
disks = set()
@@ -37,10 +36,7 @@ def list_disks():
def is_busy(disk: str):
"""Check if given disk device is busy by re-reading it's partition table"""
-
- cmd = 'sudo blockdev --rereadpt /dev/{}'.format(disk)
- status = subprocess.call([cmd], shell=True, stderr=subprocess.DEVNULL)
- return status != 0
+ return run(f'sudo blockdev --rereadpt /dev/{disk}', stderr=DEVNULL) != 0
def backup_partitions(disk: str):
@@ -49,8 +45,7 @@ def backup_partitions(disk: str):
device_path = '/dev/' + disk
backup_ts = datetime.now().strftime('%Y-%m-%d-%H:%M')
backup_file = '/var/tmp/backup_{}.{}'.format(disk, backup_ts)
- cmd = 'sudo /sbin/sfdisk -d {} > {}'.format(device_path, backup_file)
- subprocess.check_call([cmd], shell=True)
+ cmd(f'sudo /sbin/sfdisk -d {device_path} > {backup_file}')
def list_partitions(disk: str):
@@ -68,13 +63,11 @@ def list_partitions(disk: str):
def delete_partition(disk: str, partition_idx: int):
- cmd = 'sudo /sbin/parted /dev/{} rm {}'.format(disk, partition_idx)
- subprocess.check_call([cmd], shell=True)
+ cmd(f'sudo /sbin/parted /dev/{disk} rm {partition_idx}')
def format_disk_like(target: str, proto: str):
- cmd = 'sudo /sbin/sfdisk -d /dev/{} | sudo /sbin/sfdisk --force /dev/{}'.format(proto, target)
- subprocess.check_call([cmd], shell=True)
+ cmd(f'sudo /sbin/sfdisk -d /dev/{proto} | sudo /sbin/sfdisk --force /dev/{target}')
if __name__ == '__main__':
diff --git a/src/op_mode/generate_ssh_server_key.py b/src/op_mode/generate_ssh_server_key.py
index f205919b8..f65d383c0 100755
--- a/src/op_mode/generate_ssh_server_key.py
+++ b/src/op_mode/generate_ssh_server_key.py
@@ -14,14 +14,14 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import subprocess
import sys
from vyos.util import ask_yes_no
+from vyos.util import cmd
if not ask_yes_no('Do you really want to remove the existing SSH host keys?'):
sys.exit(0)
-else:
- subprocess.check_call(['sudo rm -v /etc/ssh/ssh_host_*'], shell=True)
- subprocess.check_call(['sudo dpkg-reconfigure openssh-server'], shell=True)
- subprocess.check_call(['sudo systemctl restart ssh'], shell=True)
+
+cmd('sudo rm -v /etc/ssh/ssh_host_*')
+cmd('sudo dpkg-reconfigure openssh-server')
+cmd('sudo systemctl restart ssh')
diff --git a/src/op_mode/lldp_op.py b/src/op_mode/lldp_op.py
index 4d8fdbc99..c8a5543b6 100755
--- a/src/op_mode/lldp_op.py
+++ b/src/op_mode/lldp_op.py
@@ -20,9 +20,10 @@ import jinja2
from xml.dom import minidom
from sys import exit
-from subprocess import Popen, PIPE, STDOUT
from tabulate import tabulate
+from vyos.util import popen
+
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--all", action="store_true", help="Show LLDP neighbors on all interfaces")
parser.add_argument("-i", "--interface", action="store", help="Show LLDP neighbors on specific interface")
@@ -40,9 +41,8 @@ Device ID Local Proto Cap Platform Port ID
def _get_neighbors():
command = '/usr/sbin/lldpcli -f xml show neighbors'
- p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True)
- tmp = p.communicate()[0].strip()
- return tmp.decode()
+ out,_ = popen(command)
+ return out
def extract_neighbor(neighbor):
"""
diff --git a/src/op_mode/powerctrl.py b/src/op_mode/powerctrl.py
index 54fc12be3..772bb8198 100755
--- a/src/op_mode/powerctrl.py
+++ b/src/op_mode/powerctrl.py
@@ -17,12 +17,11 @@
import os
import sys
import argparse
-import subprocess
import re
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
+from vyos.util import cmd, run
systemd_sched_file = "/run/systemd/shutdown/scheduled"
@@ -45,23 +44,20 @@ def parse_date(s):
return None
def get_shutdown_status():
- try:
- 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
+ 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
def check_shutdown():
output = get_shutdown_status()
@@ -76,13 +72,13 @@ def check_shutdown():
def cancel_shutdown():
output = get_shutdown_status()
if output and 'MODE' in output:
+ timenow = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
try:
- timenow = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- cmd = check_output(["/sbin/shutdown","-c","--no-wall"])
- message = "Scheduled %s has been cancelled %s" % (output['MODE'], timenow)
- os.system("wall %s" % message)
- except CalledProcessError as e:
+ cmd('/sbin/shutdown -c --no-wall')
+ except OSError as e:
sys.exit("Could not cancel a reboot or poweroff: %s" % e)
+ message = "Scheduled %s has been cancelled %s" % (output['MODE'], timenow)
+ run(f'wall {message}')
else:
print("Reboot or poweroff is not scheduled")
@@ -99,14 +95,14 @@ def execute_shutdown(time, reboot = True, ask=True):
chk_vyatta_based_reboots()
###
- cmd = check_output(["/sbin/shutdown",action,"now"],stderr=STDOUT)
- print(cmd.decode().split(",",1)[0])
+ out = cmd(f'/sbin/shutdown {action} now')
+ print(out.split(",",1)[0])
return
elif len(time) == 1:
# Assume the argument is just time
ts = parse_time(time[0])
if ts:
- cmd = check_output(["/sbin/shutdown", action, time[0]], stderr=STDOUT)
+ cmd(f'/sbin/shutdown {action} {time[0]}')
else:
sys.exit("Invalid time \"{0}\". The valid format is HH:MM".format(time[0]))
elif len(time) == 2:
@@ -117,7 +113,7 @@ def execute_shutdown(time, reboot = True, ask=True):
t = datetime.combine(ds, ts)
td = t - datetime.now()
t2 = 1 + int(td.total_seconds())//60 # Get total minutes
- cmd = check_output(["/sbin/shutdown", action, str(t2)], stderr=STDOUT)
+ cmd('/sbin/shutdown {action} {t2}')
else:
if not ts:
sys.exit("Invalid time \"{0}\". The valid format is HH:MM".format(time[0]))
@@ -136,7 +132,7 @@ def chk_vyatta_based_reboots():
if os.path.exists(f):
jid = open(f).read().strip()
if jid != 0:
- subprocess.call(['sudo', 'atrm', jid])
+ run(f'sudo atrm {jid}')
os.remove(f)
def main():
diff --git a/src/op_mode/reset_openvpn.py b/src/op_mode/reset_openvpn.py
index 4c29fbbba..618cad5ea 100755
--- a/src/op_mode/reset_openvpn.py
+++ b/src/op_mode/reset_openvpn.py
@@ -17,10 +17,9 @@
import sys
import os
-from subprocess import Popen, PIPE
from time import sleep
from netifaces import interfaces
-from vyos.util import process_running
+from vyos.util import process_running, cmd
def get_config_name(intf):
cfg_file = r'/opt/vyatta/etc/openvpn/openvpn-{}.conf'.format(intf)
@@ -30,9 +29,6 @@ def get_pid_file(intf):
pid_file = r'/var/run/openvpn/{}.pid'.format(intf)
return pid_file
-def subprocess_cmd(command):
- p = Popen(command, stdout=PIPE, shell=True)
- p.communicate()
if __name__ == '__main__':
if (len(sys.argv) < 1):
@@ -43,12 +39,12 @@ if __name__ == '__main__':
if os.path.isfile(get_config_name(interface)):
pidfile = '/var/run/openvpn/{}.pid'.format(interface)
if process_running(pidfile):
- cmd = 'start-stop-daemon'
- cmd += ' --stop'
- cmd += ' --oknodo'
- cmd += ' --quiet'
- cmd += ' --pidfile ' + pidfile
- subprocess_cmd(cmd)
+ command = 'start-stop-daemon'
+ command += ' --stop'
+ command += ' --oknodo'
+ command += ' --quiet'
+ command += ' --pidfile ' + pidfile
+ cmd(command)
# When stopping OpenVPN we need to wait for the 'old' interface to
# vanish from the Kernel, if it is not gone, OpenVPN will report:
@@ -57,18 +53,18 @@ if __name__ == '__main__':
sleep(0.250) # 250ms
# re-start OpenVPN process
- cmd = 'start-stop-daemon'
- cmd += ' --start'
- cmd += ' --oknodo'
- cmd += ' --quiet'
- cmd += ' --pidfile ' + get_pid_file(interface)
- cmd += ' --exec /usr/sbin/openvpn'
+ command = 'start-stop-daemon'
+ command += ' --start'
+ command += ' --oknodo'
+ command += ' --quiet'
+ command += ' --pidfile ' + get_pid_file(interface)
+ command += ' --exec /usr/sbin/openvpn'
# now pass arguments to openvpn binary
- cmd += ' --'
- cmd += ' --daemon openvpn-' + interface
- cmd += ' --config ' + get_config_name(interface)
+ command += ' --'
+ command += ' --daemon openvpn-' + interface
+ command += ' --config ' + get_config_name(interface)
- subprocess_cmd(cmd)
+ cmd(command)
else:
print("OpenVPN interface {} does not exist!".format(interface))
sys.exit(1)
diff --git a/src/op_mode/reset_vpn.py b/src/op_mode/reset_vpn.py
index 52677b58d..b47212f88 100755
--- a/src/op_mode/reset_vpn.py
+++ b/src/op_mode/reset_vpn.py
@@ -16,52 +16,53 @@
# import os
import sys
-import subprocess
import argparse
#import re
-pptp_cmd = ["/usr/bin/accel-cmd", "-p 2003"]
-l2tp_cmd = ["/usr/bin/accel-cmd", "-p 2004"]
+from vyos.util import run, DEVNULL
+
+pptp_base = '/usr/bin/accel-cmd -p 2003 terminate {} {}'
+l2tp_base = '/usr/bin/accel-cmd -p 2004 terminate {} {}'
def terminate_sessions(username='', interface='', protocol=''):
if username:
if username == "all_users":
if protocol == "pptp":
- pptp_cmd.append("terminate all")
- subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ pptp_cmd = pptp_base.format('all','')
+ run(pptp_cmd, stdout=DEVNULL, stderr=DEVNULL)
return
elif protocol == "l2tp":
- l2tp_cmd.append("terminate all")
- subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ l2tp_cmd = l2tp_base.format('all', '')
+ run(l2tp_cmd, stdout=DEVNULL, stderr=DEVNULL)
return
else:
- pptp_cmd.append("terminate all")
- subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- l2tp_cmd.append("terminate all")
- subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ pptp_cmd = pptp_base.format('all', '')
+ run(pptp_cmd, stdout=DEVNULL, stderr=DEVNULL)
+ l2tp_cmd = l2tp_base.format('all', '')
+ run(l2tp_cmd, stdout=DEVNULL, stderr=DEVNULL)
return
if protocol == "pptp":
- pptp_cmd.append("terminate username {0}".format(username))
- subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ pptp_cmd = pptp_base.format('username', username)
+ run(pptp_cmd, stdout=DEVNULL, stderr=DEVNULL)
return
elif protocol == "l2tp":
- l2tp_cmd.append("terminate username {0}".format(username))
- subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ l2tp_cmd = l2tp_base.format('username', username)
+ run(l2tp_cmd, stdout=DEVNULL, stderr=DEVNULL)
return
else:
- pptp_cmd.append("terminate username {0}".format(username))
- subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ pptp_cmd = pptp_base.format('username', username)
+ run(pptp_cmd, stdout=DEVNULL, stderr=DEVNULL)
l2tp_cmd.append("terminate username {0}".format(username))
- subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ run(l2tp_cmd, stdout=DEVNULL, stderr=DEVNULL)
return
# rewrite `terminate by interface` if pptp will have pptp%d interface naming
if interface:
- pptp_cmd.append("terminate if {0}".format(interface))
- subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- l2tp_cmd.append("terminate if {0}".format(interface))
- subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ pptp_cmd = pptp_base.format('if', interface)
+ run(pptp_cmd, stdout=DEVNULL, stderr=DEVNULL)
+ l2tp_cmd = l2tp_base.format('if', interface)
+ run(l2tp_cmd, stdout=DEVNULL, stderr=DEVNULL)
def main():
diff --git a/src/op_mode/restart_dhcp_relay.py b/src/op_mode/restart_dhcp_relay.py
index ab02d1eb3..057b4dcd8 100755
--- a/src/op_mode/restart_dhcp_relay.py
+++ b/src/op_mode/restart_dhcp_relay.py
@@ -23,6 +23,8 @@ import argparse
import os
import vyos.config
+from vyos.util import run
+
parser = argparse.ArgumentParser()
parser.add_argument("--ipv4", action="store_true", help="Restart IPv4 DHCP relay")
@@ -37,7 +39,7 @@ if __name__ == '__main__':
if not c.exists_effective('service dhcp-relay'):
print("DHCP relay service not configured")
else:
- os.system('sudo systemctl restart isc-dhcp-relay.service')
+ run('sudo systemctl restart isc-dhcp-relay.service')
sys.exit(0)
elif args.ipv6:
@@ -45,7 +47,7 @@ if __name__ == '__main__':
if not c.exists_effective('service dhcpv6-relay'):
print("DHCPv6 relay service not configured")
else:
- os.system('sudo systemctl restart isc-dhcpv6-relay.service')
+ run('sudo systemctl restart isc-dhcpv6-relay.service')
sys.exit(0)
else:
diff --git a/src/op_mode/restart_frr.py b/src/op_mode/restart_frr.py
index da6407e23..6304e72db 100755
--- a/src/op_mode/restart_frr.py
+++ b/src/op_mode/restart_frr.py
@@ -17,12 +17,13 @@
import sys
import argparse
-import subprocess
import logging
from logging.handlers import SysLogHandler
from pathlib import Path
import psutil
+from vyos.util import run
+
# some default values
watchfrr = '/usr/lib/frr/watchfrr.sh'
vtysh = '/usr/bin/vtysh'
@@ -86,7 +87,7 @@ def _write_config():
Path(frrconfig_tmp).mkdir(parents=False, exist_ok=True)
# save frr.conf to it
command = "{} -n -w --config_dir {} 2> /dev/null".format(vtysh, frrconfig_tmp)
- return_code = subprocess.call(command, shell=True)
+ return_code = run(command)
if not return_code == 0:
logger.error("Failed to save active config: \"{}\" returned exit code: {}".format(command, return_code))
return False
@@ -108,7 +109,7 @@ def _cleanup():
# check if daemon is running
def _daemon_check(daemon):
command = "{} print_status {}".format(watchfrr, daemon)
- return_code = subprocess.call(command, shell=True)
+ return_code = run(command)
if not return_code == 0:
logger.error("Daemon \"{}\" is not running".format(daemon))
return False
@@ -119,7 +120,7 @@ def _daemon_check(daemon):
# restart daemon
def _daemon_restart(daemon):
command = "{} restart {}".format(watchfrr, daemon)
- return_code = subprocess.call(command, shell=True)
+ return_code = run(command)
if not return_code == 0:
logger.error("Failed to restart daemon \"{}\"".format(daemon))
return False
@@ -135,7 +136,7 @@ def _reload_config(daemon):
else:
command = "{} -n -b --config_dir {} 2> /dev/null".format(vtysh, frrconfig_tmp)
- return_code = subprocess.call(command, shell=True)
+ return_code = run(command)
if not return_code == 0:
logger.error("Failed to reinstall configuration")
return False
diff --git a/src/op_mode/show_acceleration.py b/src/op_mode/show_acceleration.py
index 3ba0e85dd..05d3d8906 100755
--- a/src/op_mode/show_acceleration.py
+++ b/src/op_mode/show_acceleration.py
@@ -19,14 +19,15 @@ import sys
import os
import re
import argparse
-import subprocess
+
from vyos.config import Config
+from vyos.util import popen, run
+
def detect_qat_dev():
- ret = subprocess.Popen(['sudo', 'lspci', '-nn'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
+ output, err = popen('sudo lspci -nn', decode='utf-8')
if not err:
- data = re.findall('(8086:19e2)|(8086:37c8)|(8086:0435)|(8086:6f54)', output.decode("utf-8"))
+ data = re.findall('(8086:19e2)|(8086:37c8)|(8086:0435)|(8086:6f54)', output)
#If QAT devices found
if data:
return
@@ -42,15 +43,12 @@ def show_qat_status():
sys.exit(1)
# Show QAT service
- os.system('sudo /etc/init.d/vyos-qat-utilities status')
+ run('sudo /etc/init.d/vyos-qat-utilities status')
# Return QAT devices
def get_qat_devices():
- ret = subprocess.Popen(['sudo', '/etc/init.d/vyos-qat-utilities', 'status'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
+ data_st, err = popen('sudo /etc/init.d/vyos-qat-utilities status', decode='utf-8')
if not err:
- #print(output)
- data_st = output.decode("utf-8")
elm_lst = re.findall('qat_dev\d', data_st)
print('\n'.join(elm_lst))
@@ -58,11 +56,10 @@ def get_qat_devices():
def get_qat_proc_path(qat_dev):
q_type = ""
q_bsf = ""
- ret = subprocess.Popen(['sudo', '/etc/init.d/vyos-qat-utilities', 'status'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
+ output, err = popen('sudo /etc/init.d/vyos-qat-utilities status', decode='utf-8')
if not err:
# Parse QAT service output
- data_st = output.decode("utf-8").split("\n")
+ data_st = output.split("\n")
for elm_str in range(len(data_st)):
if re.search(qat_dev, data_st[elm_str]):
elm_list = data_st[elm_str].split(", ")
@@ -97,22 +94,22 @@ args = parser.parse_args()
if args.hw:
detect_qat_dev()
# Show availible Intel QAT devices
- os.system('sudo lspci -nn | egrep -e \'8086:37c8|8086:19e2|8086:0435|8086:6f54\'')
+ run('sudo lspci -nn | egrep -e \'8086:37c8|8086:19e2|8086:0435|8086:6f54\'')
elif args.flow and args.dev:
check_qat_if_conf()
- os.system('sudo cat '+get_qat_proc_path(args.dev)+"fw_counters")
+ run('sudo cat '+get_qat_proc_path(args.dev)+"fw_counters")
elif args.interrupts:
check_qat_if_conf()
# Delete _dev from args.dev
- os.system('sudo cat /proc/interrupts | grep qat')
+ run('sudo cat /proc/interrupts | grep qat')
elif args.status:
check_qat_if_conf()
show_qat_status()
elif args.conf and args.dev:
check_qat_if_conf()
- os.system('sudo cat '+get_qat_proc_path(args.dev)+"dev_cfg")
+ run('sudo cat '+get_qat_proc_path(args.dev)+"dev_cfg")
elif args.dev_list:
get_qat_devices()
else:
parser.print_help()
- sys.exit(1) \ No newline at end of file
+ sys.exit(1)
diff --git a/src/op_mode/show_dhcp.py b/src/op_mode/show_dhcp.py
index f801ba753..4e3e08263 100755
--- a/src/op_mode/show_dhcp.py
+++ b/src/op_mode/show_dhcp.py
@@ -24,9 +24,12 @@ import collections
import os
from datetime import datetime
-from vyos.config import Config
from isc_dhcp_leases import Lease, IscDhcpLeases
+from vyos.config import Config
+from vyos.util import run
+
+
lease_file = "/config/dhcpd.leases"
pool_key = "shared-networkname"
@@ -190,7 +193,7 @@ if __name__ == '__main__':
sys.exit(0)
# if dhcp server is down, inactive leases may still be shown as active, so warn the user.
- if os.system('systemctl -q is-active isc-dhcpv4-server.service') != 0:
+ if run('systemctl -q is-active isc-dhcpv4-server.service') != 0:
print("WARNING: DHCP server is configured but not started. Data may be stale.")
if args.leases:
diff --git a/src/op_mode/show_dhcpv6.py b/src/op_mode/show_dhcpv6.py
index ae63af39b..4ef4849ff 100755
--- a/src/op_mode/show_dhcpv6.py
+++ b/src/op_mode/show_dhcpv6.py
@@ -24,9 +24,11 @@ import collections
import os
from datetime import datetime
-from vyos.config import Config
from isc_dhcp_leases import Lease, IscDhcpLeases
+from vyos.config import Config
+from vyos.util import run
+
lease_file = "/config/dhcpdv6.leases"
pool_key = "shared-networkname"
@@ -177,7 +179,7 @@ if __name__ == '__main__':
sys.exit(0)
# if dhcp server is down, inactive leases may still be shown as active, so warn the user.
- if os.system('systemctl -q is-active isc-dhcpv6-server.service') != 0:
+ if run('systemctl -q is-active isc-dhcpv6-server.service') != 0:
print("WARNING: DHCPv6 server is configured but not started. Data may be stale.")
if args.leases:
diff --git a/src/op_mode/show_vpn_ra.py b/src/op_mode/show_vpn_ra.py
index cf6119c2f..2323193b1 100755
--- a/src/op_mode/show_vpn_ra.py
+++ b/src/op_mode/show_vpn_ra.py
@@ -17,8 +17,8 @@
import os
import sys
import re
-import subprocess
-# from subprocess import Popen, PIPE
+
+from vyos.util import popen
# chech connection to pptp and l2tp daemon
def get_sessions():
@@ -31,18 +31,16 @@ def get_sessions():
len_def_header = 170
# Check pptp
- ret = subprocess.Popen(pptp_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
- if not err and len(output.decode("utf-8")) > len_def_header and not re.search(err_pattern, output.decode("utf-8")):
- print(output.decode("utf-8"))
+ output, err = popen(pptp_cmd, decode='utf-8')
+ if not err and len(output) > len_def_header and not re.search(err_pattern, output):
+ print(output)
else:
absent_pptp = True
# Check l2tp
- ret = subprocess.Popen(l2tp_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (output, err) = ret.communicate()
- if not err and len(output.decode("utf-8")) > len_def_header and not re.search(err_pattern, output.decode("utf-8")):
- print(output.decode("utf-8"))
+ output, err = popen(l2tp_cmd, decode='utf-8')
+ if not err and len(output) > len_def_header and not re.search(err_pattern, output):
+ print(output)
else:
absent_l2tp = True
diff --git a/src/op_mode/show_vrf.py b/src/op_mode/show_vrf.py
index 66c33e607..b6bb73d01 100755
--- a/src/op_mode/show_vrf.py
+++ b/src/op_mode/show_vrf.py
@@ -16,10 +16,10 @@
import argparse
import jinja2
-
-from subprocess import check_output
from json import loads
+from vyos.util import cmd
+
vrf_out_tmpl = """
VRF name state mac address flags interfaces
-------- ----- ----------- ----- ----------
@@ -31,12 +31,12 @@ VRF name state mac address flags interfa
def list_vrfs():
command = 'ip -j -br link show type vrf'
- answer = loads(check_output(command.split()).decode())
+ answer = loads(cmd(command))
return [_ for _ in answer if _]
def list_vrf_members(vrf):
command = f'ip -j -br link show master {vrf}'
- answer = loads(check_output(command.split()).decode())
+ answer = loads(cmd(command))
return [_ for _ in answer if _]
parser = argparse.ArgumentParser()
diff --git a/src/op_mode/show_wireless.py b/src/op_mode/show_wireless.py
index aff882559..b5ee3aee1 100755
--- a/src/op_mode/show_wireless.py
+++ b/src/op_mode/show_wireless.py
@@ -19,19 +19,15 @@ import re
from sys import exit
from copy import deepcopy
-from subprocess import Popen, PIPE, STDOUT
from vyos.config import Config
+from vyos.util import popen
parser = argparse.ArgumentParser()
parser.add_argument("-s", "--scan", help="Scan for Wireless APs on given interface, e.g. 'wlan0'")
parser.add_argument("-b", "--brief", action="store_true", help="Show wireless configuration")
parser.add_argument("-c", "--stations", help="Show wireless clients connected on interface, e.g. 'wlan0'")
-def _cmd(command):
- p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True)
- tmp = p.communicate()[0].strip()
- return tmp.decode()
def show_brief():
config = Config()
@@ -57,7 +53,8 @@ def show_brief():
return interfaces
def ssid_scan(intf):
- tmp = _cmd('/sbin/iw dev {} scan ap-force'.format(intf))
+ # XXX: This ignores errors
+ tmp, _ = popen(f'/sbin/iw dev {intf} scan ap-force')
networks = []
data = {
'ssid': '',
@@ -89,7 +86,8 @@ def ssid_scan(intf):
return networks
def show_clients(intf):
- tmp = _cmd('/sbin/iw dev {} station dump'.format(intf))
+ # XXX: This ignores errors
+ tmp, _ = popen(f'/sbin/iw dev {intf} station dump')
clients = []
data = {
'mac': '',
diff --git a/src/op_mode/snmp.py b/src/op_mode/snmp.py
index e08441f0e..b09eab97f 100755
--- a/src/op_mode/snmp.py
+++ b/src/op_mode/snmp.py
@@ -24,6 +24,7 @@ import sys
import argparse
from vyos.config import Config
+from vyos.util import run
config_file_daemon = r'/etc/snmp/snmpd.conf'
@@ -53,7 +54,7 @@ def show_all():
def show_community(c, h):
print('Status of SNMP community {0} on {1}'.format(c, h), flush=True)
- os.system('/usr/bin/snmpstatus -t1 -v1 -c {0} {1}'.format(c, h))
+ run('/usr/bin/snmpstatus -t1 -v1 -c {0} {1}'.format(c, h))
if __name__ == '__main__':
args = parser.parse_args()
diff --git a/src/op_mode/snmp_ifmib.py b/src/op_mode/snmp_ifmib.py
index 3a0e0d4b2..2479936bd 100755
--- a/src/op_mode/snmp_ifmib.py
+++ b/src/op_mode/snmp_ifmib.py
@@ -22,36 +22,24 @@
import sys
import argparse
import netifaces
-import subprocess
from vyos.config import Config
+from vyos.util import popen
parser = argparse.ArgumentParser(description='Retrieve SNMP interfaces information')
parser.add_argument('--ifindex', action='store', nargs='?', const='all', help='Show interface index')
parser.add_argument('--ifalias', action='store', nargs='?', const='all', help='Show interface aliase')
parser.add_argument('--ifdescr', action='store', nargs='?', const='all', help='Show interface description')
-def show_ifindex(i):
- proc = subprocess.Popen(['/bin/ip', 'link', 'show', i], stdout=subprocess.PIPE)
- (out, err) = proc.communicate()
- # convert output to string
- string = out.decode("utf-8")
-
- index = 'ifIndex = ' + string.split(':')[0]
+def show_ifindex(intf):
+ out, err = popen(f'/bin/ip link show {intf}', decode='utf-8')
+ index = 'ifIndex = ' + out.split(':')[0]
return index.replace('\n', '')
-def show_ifalias(i):
- proc = subprocess.Popen(['/bin/ip', 'link', 'show', i], stdout=subprocess.PIPE)
- (out, err) = proc.communicate()
- # convert output to string
- string = out.decode("utf-8")
-
- if 'alias' in string:
- alias = 'ifAlias = ' + string.split('alias')[1].lstrip()
- else:
- alias = 'ifAlias = ' + i
-
- return alias.replace('\n', '')
+def show_ifalias(intf):
+ out, err = popen(f'/bin/ip link show {intf}', decode='utf-8')
+ alias = out.split('alias')[1].lstrip() if 'alias' in out else intf
+ return 'ifAlias = ' + alias.replace('\n', '')
def show_ifdescr(i):
ven_id = ''
@@ -74,14 +62,13 @@ def show_ifdescr(i):
return ret
device = str(ven_id) + ':' + str(dev_id)
- proc = subprocess.Popen(['/usr/bin/lspci', '-mm', '-d', device], stdout=subprocess.PIPE)
- (out, err) = proc.communicate()
+ out, err = popen(f'/usr/bin/lspci -mm -d {device}', decode='utf-8')
vendor = ""
device = ""
# convert output to string
- string = out.decode("utf-8").split('"')
+ string = out.split('"')
if len(string) > 3:
vendor = string[3]
diff --git a/src/op_mode/system_integrity.py b/src/op_mode/system_integrity.py
index 886d94f16..c0e3d1095 100755
--- a/src/op_mode/system_integrity.py
+++ b/src/op_mode/system_integrity.py
@@ -18,18 +18,19 @@
import sys
import os
-import subprocess
import re
import itertools
from datetime import datetime, timedelta
+from vyos.util import cmd
+
verf = r'/usr/libexec/vyos/op_mode/version.py'
def get_sys_build_version():
if not os.path.exists(verf):
return None
- a = subprocess.check_output(['/usr/libexec/vyos/op_mode/version.py']).decode()
+ a = cmd('/usr/libexec/vyos/op_mode/version.py')
if re.search('^Built on:.+',a, re.M) == None:
return None
diff --git a/src/op_mode/version.py b/src/op_mode/version.py
index 5aff0f767..34eca44b1 100755
--- a/src/op_mode/version.py
+++ b/src/op_mode/version.py
@@ -22,7 +22,6 @@
import os
import sys
-import subprocess
import argparse
import json
@@ -31,6 +30,8 @@ import pystache
import vyos.version
import vyos.limericks
+from vyos.util import cmd, run
+
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--all", action="store_true", help="Include individual package versions")
@@ -73,15 +74,15 @@ if __name__ == '__main__':
version_data = vyos.version.get_version_data()
# Get system architecture (well, kernel architecture rather)
- version_data['system_arch'] = subprocess.check_output('uname -m', shell=True).decode().strip()
+ version_data['system_arch'] = cmd('uname -m')
# Get hypervisor name, if any
system_type = "bare metal"
try:
- hypervisor = subprocess.check_output('hvinfo 2>/dev/null', shell=True).decode().strip()
+ hypervisor = cmd('hvinfo 2>/dev/null')
system_type = "{0} guest".format(hypervisor)
- except subprocess.CalledProcessError:
+ except OSError:
# hvinfo returns 1 if it cannot detect any hypervisor
pass
version_data['system_type'] = system_type
@@ -93,9 +94,9 @@ if __name__ == '__main__':
# while on livecd it's just "filesystem.squashfs", that's how we tell a livecd boot
# from an installed image
boot_via = "installed image"
- if subprocess.call(""" grep -e '^overlay.*/filesystem.squashfs' /proc/mounts >/dev/null""", shell=True) == 0:
+ if run(""" grep -e '^overlay.*/filesystem.squashfs' /proc/mounts >/dev/null""") == 0:
boot_via = "livecd"
- elif subprocess.call(""" grep '^overlay /' /proc/mounts >/dev/null """, shell=True) != 0:
+ elif run(""" grep '^overlay /' /proc/mounts >/dev/null """) != 0:
boot_via = "legacy non-image installation"
version_data['boot_via'] = boot_via
@@ -118,7 +119,7 @@ if __name__ == '__main__':
if args.all:
print("Package versions:")
- os.system("dpkg -l")
+ run("dpkg -l")
if args.funny:
print(vyos.limericks.get_random())
diff --git a/src/op_mode/wireguard.py b/src/op_mode/wireguard.py
index c684f8a47..d940d79eb 100755
--- a/src/op_mode/wireguard.py
+++ b/src/op_mode/wireguard.py
@@ -20,7 +20,6 @@ import argparse
import os
import sys
import shutil
-import subprocess
import syslog as sl
import re
@@ -28,6 +27,7 @@ from vyos.ifconfig import WireGuardIf
from vyos import ConfigError
from vyos.config import Config
+from vyos.util import run
dir = r'/config/auth/wireguard'
psk = dir + '/preshared.key'
@@ -36,16 +36,14 @@ def check_kmod():
""" check if kmod is loaded, if not load it """
if not os.path.exists('/sys/module/wireguard'):
sl.syslog(sl.LOG_NOTICE, "loading wirguard kmod")
- if os.system('sudo modprobe wireguard') != 0:
+ if run('sudo modprobe wireguard') != 0:
sl.syslog(sl.LOG_ERR, "modprobe wireguard failed")
raise ConfigError("modprobe wireguard failed")
def generate_keypair(pk, pub):
""" generates a keypair which is stored in /config/auth/wireguard """
old_umask = os.umask(0o027)
- ret = subprocess.call(
- ['wg genkey | tee ' + pk + '|wg pubkey > ' + pub], shell=True)
- if ret != 0:
+ if run(f'wg genkey | tee {pk} | wg pubkey > {pub}') != 0:
raise ConfigError("wireguard key-pair generation failed")
else:
sl.syslog(
@@ -69,9 +67,9 @@ def genkey(location):
else:
""" if keypair is bing executed from a running iso """
if not os.path.exists(location):
- subprocess.call(['sudo mkdir -p ' + location], shell=True)
- subprocess.call(['sudo chgrp vyattacfg ' + location], shell=True)
- subprocess.call(['sudo chmod 750 ' + location], shell=True)
+ run(f'sudo mkdir -p {location}')
+ run(f'sudo chgrp vyattacfg {location}')
+ run(f'sudo chmod 750 {location}')
generate_keypair(pk, pub)
os.umask(old_umask)
@@ -90,7 +88,7 @@ def genpsk():
it's stored only in the cli config
"""
- subprocess.call(['wg genpsk'], shell=True)
+ run('wg genpsk')
def list_key_dirs():
""" lists all dirs under /config/auth/wireguard """
diff --git a/src/system/keepalived-fifo.py b/src/system/keepalived-fifo.py
index 5e85da4a4..2778deaab 100755
--- a/src/system/keepalived-fifo.py
+++ b/src/system/keepalived-fifo.py
@@ -20,7 +20,6 @@ import time
import signal
import argparse
import threading
-import subprocess
import re
import json
from pathlib import Path
@@ -28,6 +27,8 @@ from queue import Queue
import logging
from logging.handlers import SysLogHandler
+from vyos.util import cmd
+
# configure logging
logger = logging.getLogger(__name__)
logs_format = logging.Formatter('%(filename)s: %(message)s')
@@ -84,14 +85,11 @@ class KeepalivedFifo:
# run command
def _run_command(self, command):
+ logger.debug("Running the command: {}".format(command))
try:
- logger.debug("Running the command: {}".format(command))
- process = subprocess.Popen(command.split(' '), stdout=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
- stdout, stderr = process.communicate()
- if process.returncode != 0:
- raise Exception("The command \"{}\" returned status {}. Error: {}".format(command, process.returncode, stderr))
- except Exception as err:
- logger.error("Unable to execute command \"{}\": {}".format(command, err))
+ cmd(command, universal_newlines=True)
+ except OSError as err:
+ logger.error(f'Unable to execute command "{command}": {err}')
# create FIFO pipe
def pipe_create(self):
diff --git a/src/validators/timezone b/src/validators/timezone
index d7a8f64c4..ec845e755 100755
--- a/src/validators/timezone
+++ b/src/validators/timezone
@@ -17,12 +17,8 @@
import argparse
from sys import exit
-from subprocess import Popen, PIPE, STDOUT
-def _cmd(cmd):
- p = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True)
- tmp = p.communicate()[0].strip()
- return tmp.decode()
+from vyos.util import cmd
parser = argparse.ArgumentParser()
parser.add_argument("--validate", action="store", help="Check if timezone is valid")
@@ -31,7 +27,7 @@ if __name__ == '__main__':
args = parser.parse_args()
if args.validate:
- tz_data = _cmd('find /usr/share/zoneinfo/posix -type f -or -type l | sed -e s:/usr/share/zoneinfo/posix/::')
+ tz_data = cmd('find /usr/share/zoneinfo/posix -type f -or -type l | sed -e s:/usr/share/zoneinfo/posix/::')
tz_data = tz_data.split('\n')
# if timezone can't be found in list it's invalid
if args.validate not in tz_data: