From 3458a8b50853ecd032ebc3ee87f00452ac73ebcd Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Tue, 19 May 2020 21:13:05 +0100 Subject: util: T2467: add autosudo as an option to command --- python/vyos/util.py | 50 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/python/vyos/util.py b/python/vyos/util.py index 381cd0358..26352f93c 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -21,12 +21,24 @@ import sys # where it is used so it is as local as possible to the execution # -# There is many (too many) ways to run command with python -# os.system, subprocess.Popen, subproces.{run,call,check_output} -# which all have slighty different behaviour -from subprocess import Popen, PIPE, STDOUT, DEVNULL + +def _need_sudo(command): + return os.path.basename(command.split()[0]) in ('', ) + + +def _add_sudo(command): + if _need_sudo(command): + return 'sudo ' + command + return command + + +from subprocess import Popen +from subprocess import PIPE +from subprocess import DEVNULL + + def popen(command, flag='', shell=None, input=None, timeout=None, env=None, - stdout=PIPE, stderr=PIPE, decode='utf-8'): + stdout=PIPE, stderr=PIPE, decode='utf-8', autosudo=True): """ popen is a wrapper helper aound subprocess.Popen with it default setting it will return a tuple (out, err) @@ -52,15 +64,22 @@ def popen(command, flag='', shell=None, input=None, timeout=None, env=None, the default is explicitely utf-8 which is python's own default usage: - to get both stdout, and stderr: popen('command', stdout=PIPE, stderr=STDOUT) - to discard stdout and get stderr: popen('command', stdout=DEVNUL, stderr=PIPE) + get both stdout and stderr: popen('command', stdout=PIPE, stderr=STDOUT) + discard stdout and get stderr: popen('command', stdout=DEVNUL, stderr=PIPE) """ + + # airbag must be left as an import in the function as otherwise we have a + # a circual import dependency from vyos import debug from vyos import airbag + # log if the flag is set, otherwise log if command is set if not debug.enabled(flag): flag = 'command' + if autosudo: + command = _add_sudo(command) + cmd_msg = f"cmd '{command}'" debug.message(cmd_msg, flag) @@ -72,9 +91,11 @@ def popen(command, flag='', shell=None, input=None, timeout=None, env=None, use_shell = True if env: use_shell = True + if input: stdin = PIPE input = input.encode() if type(input) is str else input + p = Popen( command, stdin=stdin, stdout=stdout, stderr=stderr, @@ -112,9 +133,9 @@ def popen(command, flag='', shell=None, input=None, timeout=None, env=None, def run(command, flag='', shell=None, input=None, timeout=None, env=None, - stdout=DEVNULL, stderr=PIPE, decode='utf-8'): + stdout=DEVNULL, stderr=PIPE, decode='utf-8', autosudo=True): """ - A wrapper around vyos.util.popen, which discard the stdout and + A wrapper around popen, which discard the stdout and will return the error code of a command """ _, code = popen( @@ -128,14 +149,15 @@ def run(command, flag='', shell=None, input=None, timeout=None, env=None, def cmd(command, flag='', shell=None, input=None, timeout=None, env=None, - stdout=PIPE, stderr=PIPE, decode='utf-8', + stdout=PIPE, stderr=PIPE, decode='utf-8', autosudo=True, raising=None, message='', expect=[0]): """ - A wrapper around vyos.util.popen, which returns the stdout and + A wrapper around popen, which returns the stdout and will raise the error code of a command - raising: specify which call should be used when raising (default is OSError) + raising: specify which call should be used when raising the class should only require a string as parameter + (default is OSError) with the error code expect: a list of error codes to consider as normal """ decoded, code = popen( @@ -159,9 +181,9 @@ def cmd(command, flag='', shell=None, input=None, timeout=None, env=None, def call(command, flag='', shell=None, input=None, timeout=None, env=None, - stdout=PIPE, stderr=PIPE, decode='utf-8'): + stdout=PIPE, stderr=PIPE, decode='utf-8', autosudo=True): """ - A wrapper around vyos.util.popen, which print the stdout and + A wrapper around popen, which print the stdout and will return the error code of a command """ out, code = popen( -- cgit v1.2.3 From 43dd945c5a45c86c491892f30546d0179751bf4a Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Tue, 19 May 2020 21:13:40 +0100 Subject: util: T2467: add systemctl to autosudo --- python/vyos/util.py | 2 +- src/conf_mode/http-api.py | 4 ++-- src/conf_mode/https.py | 4 ++-- src/conf_mode/igmp_proxy.py | 2 +- src/conf_mode/lldp.py | 4 ++-- src/conf_mode/ntp.py | 4 ++-- src/conf_mode/ssh.py | 4 ++-- src/conf_mode/vrrp.py | 6 +++--- src/op_mode/flow_accounting_op.py | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/python/vyos/util.py b/python/vyos/util.py index 26352f93c..c2479aac4 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -23,7 +23,7 @@ import sys def _need_sudo(command): - return os.path.basename(command.split()[0]) in ('', ) + return os.path.basename(command.split()[0]) in ('systemctl', ) def _add_sudo(command): diff --git a/src/conf_mode/http-api.py b/src/conf_mode/http-api.py index 26f4aea7f..3b8a67ef6 100755 --- a/src/conf_mode/http-api.py +++ b/src/conf_mode/http-api.py @@ -92,9 +92,9 @@ def generate(http_api): def apply(http_api): if http_api is not None: - call('sudo systemctl restart vyos-http-api.service') + call('systemctl restart vyos-http-api.service') else: - call('sudo systemctl stop vyos-http-api.service') + call('systemctl stop vyos-http-api.service') for dep in dependencies: cmd(f'{vyos_conf_scripts_dir}/{dep}', raising=ConfigError) diff --git a/src/conf_mode/https.py b/src/conf_mode/https.py index 7d3a1b9cb..718e8375c 100755 --- a/src/conf_mode/https.py +++ b/src/conf_mode/https.py @@ -141,9 +141,9 @@ def generate(https): def apply(https): if https is not None: - call('sudo systemctl restart nginx.service') + call('systemctl restart nginx.service') else: - call('sudo systemctl stop nginx.service') + call('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 9fa591a2c..9cd7163f0 100755 --- a/src/conf_mode/igmp_proxy.py +++ b/src/conf_mode/igmp_proxy.py @@ -121,7 +121,7 @@ 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 - call('sudo systemctl stop igmpproxy.service') + call('systemctl stop igmpproxy.service') if os.path.exists(config_file): os.unlink(config_file) else: diff --git a/src/conf_mode/lldp.py b/src/conf_mode/lldp.py index d128c1fe6..6446074d8 100755 --- a/src/conf_mode/lldp.py +++ b/src/conf_mode/lldp.py @@ -228,10 +228,10 @@ def generate(lldp): def apply(lldp): if lldp: # start/restart lldp service - call('sudo systemctl restart lldpd.service') + call('systemctl restart lldpd.service') else: # LLDP service has been terminated - call('sudo systemctl stop lldpd.service') + call('systemctl stop lldpd.service') os.unlink(config_file) os.unlink(vyos_config_file) diff --git a/src/conf_mode/ntp.py b/src/conf_mode/ntp.py index 6d32f7fd6..85f60293d 100755 --- a/src/conf_mode/ntp.py +++ b/src/conf_mode/ntp.py @@ -103,10 +103,10 @@ def generate(ntp): def apply(ntp): if ntp is not None: - call('sudo systemctl restart ntp.service') + call('systemctl restart ntp.service') else: # NTP support is removed in the commit - call('sudo systemctl stop ntp.service') + call('systemctl stop ntp.service') os.unlink(config_file) return None diff --git a/src/conf_mode/ssh.py b/src/conf_mode/ssh.py index ae79eac2d..76fdad8ae 100755 --- a/src/conf_mode/ssh.py +++ b/src/conf_mode/ssh.py @@ -124,10 +124,10 @@ def generate(ssh): def apply(ssh): if ssh is not None and 'port' in ssh.keys(): - call("sudo systemctl restart ssh.service") + call("systemctl restart ssh.service") else: # SSH access is removed in the commit - call("sudo systemctl stop ssh.service") + call("systemctl stop ssh.service") if os.path.isfile(config_file): os.unlink(config_file) diff --git a/src/conf_mode/vrrp.py b/src/conf_mode/vrrp.py index f358891a5..1a5ad1f8c 100755 --- a/src/conf_mode/vrrp.py +++ b/src/conf_mode/vrrp.py @@ -227,17 +227,17 @@ def apply(data): if not VRRP.is_running(): print("Starting the VRRP process") - ret = call("sudo systemctl restart keepalived.service") + ret = call("systemctl restart keepalived.service") else: print("Reloading the VRRP process") - ret = call("sudo systemctl reload keepalived.service") + ret = call("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") - call("sudo systemctl stop keepalived.service") + call("systemctl stop keepalived.service") os.unlink(VRRP.location['daemon']) return None diff --git a/src/op_mode/flow_accounting_op.py b/src/op_mode/flow_accounting_op.py index 219ad6316..bf8c39fd6 100755 --- a/src/op_mode/flow_accounting_op.py +++ b/src/op_mode/flow_accounting_op.py @@ -195,7 +195,7 @@ if not _uacctd_running(): # restart pmacct daemon if cmd_args.action == 'restart': # run command to restart flow-accounting - cmd('sudo systemctl restart uacctd.service', + cmd('systemctl restart uacctd.service', message='Failed to restart flow-accounting') # clear in-memory collected flows -- cgit v1.2.3