summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-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
5 files changed, 66 insertions, 48 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():