Remove rootwrap execution (1)
Replace rootwrap execution with privsep context execution. This series of patches will progressively replace any rootwrap call. This patch replaces some "IpNetnsCommand" command execution methods. Change-Id: Ic5fdf221a2a2cd0951539b0e040d2a941feee287 Story: #2007686 Task: #41558
This commit is contained in:
parent
f9c9d102aa
commit
c89c1f53db
@ -192,7 +192,7 @@ class FipNamespace(namespaces.Namespace):
|
|||||||
self.agent_gateway_port = ex_gw_port
|
self.agent_gateway_port = ex_gw_port
|
||||||
|
|
||||||
cmd = ['sysctl', '-w', 'net.ipv4.conf.%s.proxy_arp=1' % interface_name]
|
cmd = ['sysctl', '-w', 'net.ipv4.conf.%s.proxy_arp=1' % interface_name]
|
||||||
ip_wrapper.netns.execute(cmd, check_exit_code=False)
|
ip_wrapper.netns.execute(cmd, check_exit_code=False, privsep_exec=True)
|
||||||
|
|
||||||
def create(self):
|
def create(self):
|
||||||
LOG.debug("DVR: add fip namespace: %s", self.name)
|
LOG.debug("DVR: add fip namespace: %s", self.name)
|
||||||
|
@ -804,7 +804,8 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase):
|
|||||||
'via', route['nexthop'], 'table', tbl_index]
|
'via', route['nexthop'], 'table', tbl_index]
|
||||||
ip_wrapper = ip_lib.IPWrapper(namespace=fip_ns_name)
|
ip_wrapper = ip_lib.IPWrapper(namespace=fip_ns_name)
|
||||||
if ip_wrapper.netns.exists(fip_ns_name):
|
if ip_wrapper.netns.exists(fip_ns_name):
|
||||||
ip_wrapper.netns.execute(cmd, check_exit_code=False)
|
ip_wrapper.netns.execute(cmd, check_exit_code=False,
|
||||||
|
privsep_exec=True)
|
||||||
else:
|
else:
|
||||||
LOG.debug("The FIP namespace %(ns)s does not exist for "
|
LOG.debug("The FIP namespace %(ns)s does not exist for "
|
||||||
"router %(id)s",
|
"router %(id)s",
|
||||||
|
@ -94,18 +94,18 @@ class Namespace(object):
|
|||||||
# these sysctl values.
|
# these sysctl values.
|
||||||
ip_wrapper = self.ip_wrapper_root.ensure_namespace(self.name)
|
ip_wrapper = self.ip_wrapper_root.ensure_namespace(self.name)
|
||||||
cmd = ['sysctl', '-w', 'net.ipv4.ip_forward=1']
|
cmd = ['sysctl', '-w', 'net.ipv4.ip_forward=1']
|
||||||
ip_wrapper.netns.execute(cmd)
|
ip_wrapper.netns.execute(cmd, privsep_exec=True)
|
||||||
# 1. Reply only if the target IP address is local address configured
|
# 1. Reply only if the target IP address is local address configured
|
||||||
# on the incoming interface; and
|
# on the incoming interface; and
|
||||||
# 2. Always use the best local address
|
# 2. Always use the best local address
|
||||||
cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1']
|
cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1']
|
||||||
ip_wrapper.netns.execute(cmd)
|
ip_wrapper.netns.execute(cmd, privsep_exec=True)
|
||||||
cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2']
|
cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2']
|
||||||
ip_wrapper.netns.execute(cmd)
|
ip_wrapper.netns.execute(cmd, privsep_exec=True)
|
||||||
if self.use_ipv6:
|
if self.use_ipv6:
|
||||||
cmd = ['sysctl', '-w',
|
cmd = ['sysctl', '-w',
|
||||||
'net.ipv6.conf.all.forwarding=%d' % int(ipv6_forwarding)]
|
'net.ipv6.conf.all.forwarding=%d' % int(ipv6_forwarding)]
|
||||||
ip_wrapper.netns.execute(cmd)
|
ip_wrapper.netns.execute(cmd, privsep_exec=True)
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
try:
|
try:
|
||||||
|
@ -98,7 +98,7 @@ class ProcessManager(MonitoredProcess):
|
|||||||
else:
|
else:
|
||||||
self.disable('HUP')
|
self.disable('HUP')
|
||||||
|
|
||||||
def disable(self, sig='9', get_stop_command=None):
|
def disable(self, sig='9', get_stop_command=None, privsep_exec=False):
|
||||||
pid = self.pid
|
pid = self.pid
|
||||||
|
|
||||||
if self.active:
|
if self.active:
|
||||||
@ -106,10 +106,12 @@ class ProcessManager(MonitoredProcess):
|
|||||||
cmd = get_stop_command(self.get_pid_file_name())
|
cmd = get_stop_command(self.get_pid_file_name())
|
||||||
ip_wrapper = ip_lib.IPWrapper(namespace=self.namespace)
|
ip_wrapper = ip_lib.IPWrapper(namespace=self.namespace)
|
||||||
ip_wrapper.netns.execute(cmd, addl_env=self.cmd_addl_env,
|
ip_wrapper.netns.execute(cmd, addl_env=self.cmd_addl_env,
|
||||||
run_as_root=self.run_as_root)
|
run_as_root=self.run_as_root,
|
||||||
|
privsep_exec=privsep_exec)
|
||||||
else:
|
else:
|
||||||
cmd = self.get_kill_cmd(sig, pid)
|
cmd = self.get_kill_cmd(sig, pid)
|
||||||
utils.execute(cmd, run_as_root=self.run_as_root)
|
utils.execute(cmd, run_as_root=self.run_as_root,
|
||||||
|
privsep_exec=privsep_exec)
|
||||||
# In the case of shutting down, remove the pid file
|
# In the case of shutting down, remove the pid file
|
||||||
if sig == '9':
|
if sig == '9':
|
||||||
utils.delete_if_exists(self.get_pid_file_name(),
|
utils.delete_if_exists(self.get_pid_file_name(),
|
||||||
|
@ -354,7 +354,7 @@ class IPDevice(SubProcessBase):
|
|||||||
try:
|
try:
|
||||||
ip_wrapper.netns.execute(["conntrack", "-D", "-d", ip_str],
|
ip_wrapper.netns.execute(["conntrack", "-D", "-d", ip_str],
|
||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
extra_ok_codes=[1])
|
extra_ok_codes=[1], privsep_exec=True)
|
||||||
|
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
LOG.exception("Failed deleting ingress connection state of"
|
LOG.exception("Failed deleting ingress connection state of"
|
||||||
@ -364,7 +364,7 @@ class IPDevice(SubProcessBase):
|
|||||||
try:
|
try:
|
||||||
ip_wrapper.netns.execute(["conntrack", "-D", "-q", ip_str],
|
ip_wrapper.netns.execute(["conntrack", "-D", "-q", ip_str],
|
||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
extra_ok_codes=[1])
|
extra_ok_codes=[1], privsep_exec=True)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
LOG.exception("Failed deleting egress connection state of"
|
LOG.exception("Failed deleting egress connection state of"
|
||||||
" floatingip %s", ip_str)
|
" floatingip %s", ip_str)
|
||||||
@ -376,7 +376,7 @@ class IPDevice(SubProcessBase):
|
|||||||
'--dport', dport]
|
'--dport', dport]
|
||||||
try:
|
try:
|
||||||
ip_wrapper.netns.execute(cmd, check_exit_code=True,
|
ip_wrapper.netns.execute(cmd, check_exit_code=True,
|
||||||
extra_ok_codes=[1])
|
extra_ok_codes=[1], privsep_exec=True)
|
||||||
|
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
LOG.exception("Failed deleting ingress connection state of "
|
LOG.exception("Failed deleting ingress connection state of "
|
||||||
@ -699,7 +699,8 @@ class IpNetnsCommand(IpCommandBase):
|
|||||||
create_network_namespace(name)
|
create_network_namespace(name)
|
||||||
wrapper = IPWrapper(namespace=name)
|
wrapper = IPWrapper(namespace=name)
|
||||||
wrapper.netns.execute(['sysctl', '-w',
|
wrapper.netns.execute(['sysctl', '-w',
|
||||||
'net.ipv4.conf.all.promote_secondaries=1'])
|
'net.ipv4.conf.all.promote_secondaries=1'],
|
||||||
|
privsep_exec=True)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
def delete(self, name):
|
def delete(self, name):
|
||||||
@ -707,7 +708,7 @@ class IpNetnsCommand(IpCommandBase):
|
|||||||
|
|
||||||
def execute(self, cmds, addl_env=None, check_exit_code=True,
|
def execute(self, cmds, addl_env=None, check_exit_code=True,
|
||||||
log_fail_as_error=True, extra_ok_codes=None,
|
log_fail_as_error=True, extra_ok_codes=None,
|
||||||
run_as_root=False):
|
run_as_root=False, privsep_exec=False):
|
||||||
ns_params = []
|
ns_params = []
|
||||||
if self._parent.namespace:
|
if self._parent.namespace:
|
||||||
run_as_root = True
|
run_as_root = True
|
||||||
@ -721,7 +722,8 @@ class IpNetnsCommand(IpCommandBase):
|
|||||||
return utils.execute(cmd, check_exit_code=check_exit_code,
|
return utils.execute(cmd, check_exit_code=check_exit_code,
|
||||||
extra_ok_codes=extra_ok_codes,
|
extra_ok_codes=extra_ok_codes,
|
||||||
log_fail_as_error=log_fail_as_error,
|
log_fail_as_error=log_fail_as_error,
|
||||||
run_as_root=run_as_root)
|
run_as_root=run_as_root,
|
||||||
|
privsep_exec=privsep_exec)
|
||||||
|
|
||||||
def exists(self, name):
|
def exists(self, name):
|
||||||
return network_namespace_exists(name)
|
return network_namespace_exists(name)
|
||||||
@ -1014,7 +1016,8 @@ def _arping(ns_name, iface_name, address, count, log_exception):
|
|||||||
'-w', 2, address]
|
'-w', 2, address]
|
||||||
try:
|
try:
|
||||||
ip_wrapper.netns.execute(arping_cmd,
|
ip_wrapper.netns.execute(arping_cmd,
|
||||||
extra_ok_codes=extra_ok_codes)
|
extra_ok_codes=extra_ok_codes,
|
||||||
|
privsep_exec=True)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
# Since this is spawned in a thread and executed 2 seconds
|
# Since this is spawned in a thread and executed 2 seconds
|
||||||
# apart, something may have been deleted while we were
|
# apart, something may have been deleted while we were
|
||||||
@ -1101,7 +1104,8 @@ def sysctl(cmd, namespace=None, log_fail_as_error=True):
|
|||||||
ip_wrapper = IPWrapper(namespace=namespace)
|
ip_wrapper = IPWrapper(namespace=namespace)
|
||||||
try:
|
try:
|
||||||
ip_wrapper.netns.execute(cmd, run_as_root=True,
|
ip_wrapper.netns.execute(cmd, run_as_root=True,
|
||||||
log_fail_as_error=log_fail_as_error)
|
log_fail_as_error=log_fail_as_error,
|
||||||
|
privsep_exec=True)
|
||||||
except RuntimeError as rte:
|
except RuntimeError as rte:
|
||||||
LOG.warning(
|
LOG.warning(
|
||||||
"Setting %(cmd)s in namespace %(ns)s failed: %(err)s.",
|
"Setting %(cmd)s in namespace %(ns)s failed: %(err)s.",
|
||||||
@ -1127,7 +1131,8 @@ def get_ip_nonlocal_bind(namespace=None):
|
|||||||
"""Get kernel option value of ip_nonlocal_bind in given namespace."""
|
"""Get kernel option value of ip_nonlocal_bind in given namespace."""
|
||||||
cmd = ['sysctl', '-bn', IP_NONLOCAL_BIND]
|
cmd = ['sysctl', '-bn', IP_NONLOCAL_BIND]
|
||||||
ip_wrapper = IPWrapper(namespace)
|
ip_wrapper = IPWrapper(namespace)
|
||||||
return int(ip_wrapper.netns.execute(cmd, run_as_root=True))
|
return int(ip_wrapper.netns.execute(cmd, run_as_root=True,
|
||||||
|
privsep_exec=True))
|
||||||
|
|
||||||
|
|
||||||
def set_ip_nonlocal_bind(value, namespace=None, log_fail_as_error=True):
|
def set_ip_nonlocal_bind(value, namespace=None, log_fail_as_error=True):
|
||||||
@ -1162,7 +1167,8 @@ def get_ipv6_forwarding(device, namespace=None):
|
|||||||
"""Get kernel value of IPv6 forwarding for device in given namespace."""
|
"""Get kernel value of IPv6 forwarding for device in given namespace."""
|
||||||
cmd = ['sysctl', '-b', "net.ipv6.conf.%s.forwarding" % device]
|
cmd = ['sysctl', '-b', "net.ipv6.conf.%s.forwarding" % device]
|
||||||
ip_wrapper = IPWrapper(namespace)
|
ip_wrapper = IPWrapper(namespace)
|
||||||
return int(ip_wrapper.netns.execute(cmd, run_as_root=True))
|
return int(ip_wrapper.netns.execute(cmd, run_as_root=True,
|
||||||
|
privsep_exec=True))
|
||||||
|
|
||||||
|
|
||||||
def _parse_ip_rule(rule, ip_version):
|
def _parse_ip_rule(rule, ip_version):
|
||||||
|
@ -33,7 +33,8 @@ class FloatingIPTcCommandBase(ip_lib.IPDevice):
|
|||||||
def _execute_tc_cmd(self, cmd, **kwargs):
|
def _execute_tc_cmd(self, cmd, **kwargs):
|
||||||
cmd = ['tc'] + cmd
|
cmd = ['tc'] + cmd
|
||||||
ip_wrapper = ip_lib.IPWrapper(self.namespace)
|
ip_wrapper = ip_lib.IPWrapper(self.namespace)
|
||||||
return ip_wrapper.netns.execute(cmd, run_as_root=True, **kwargs)
|
return ip_wrapper.netns.execute(cmd, run_as_root=True,
|
||||||
|
privsep_exec=True, **kwargs)
|
||||||
|
|
||||||
def _get_qdisc_id_for_filter(self, direction):
|
def _get_qdisc_id_for_filter(self, direction):
|
||||||
qdiscs = tc_lib.list_tc_qdiscs(self.name, namespace=self.namespace)
|
qdiscs = tc_lib.list_tc_qdiscs(self.name, namespace=self.namespace)
|
||||||
|
@ -35,7 +35,6 @@ from oslo_utils import excutils
|
|||||||
from oslo_utils import fileutils
|
from oslo_utils import fileutils
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
from neutron.common import utils
|
|
||||||
from neutron.conf.agent import common as config
|
from neutron.conf.agent import common as config
|
||||||
from neutron.privileged.agent.linux import utils as priv_utils
|
from neutron.privileged.agent.linux import utils as priv_utils
|
||||||
from neutron import wsgi
|
from neutron import wsgi
|
||||||
@ -79,16 +78,26 @@ def create_process(cmd, run_as_root=False, addl_env=None):
|
|||||||
"""
|
"""
|
||||||
cmd = list(map(str, addl_env_args(addl_env) + cmd))
|
cmd = list(map(str, addl_env_args(addl_env) + cmd))
|
||||||
if run_as_root:
|
if run_as_root:
|
||||||
|
# NOTE(ralonsoh): to be removed once the migration to privsep
|
||||||
|
# execution is done.
|
||||||
cmd = shlex.split(config.get_root_helper(cfg.CONF)) + cmd
|
cmd = shlex.split(config.get_root_helper(cfg.CONF)) + cmd
|
||||||
LOG.debug("Running command: %s", cmd)
|
LOG.debug("Running command: %s", cmd)
|
||||||
obj = utils.subprocess_popen(cmd, shell=False,
|
obj = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE,
|
||||||
stdin=subprocess.PIPE,
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE)
|
|
||||||
|
|
||||||
return obj, cmd
|
return obj, cmd
|
||||||
|
|
||||||
|
|
||||||
|
def _execute_process(cmd, _process_input, addl_env, run_as_root):
|
||||||
|
obj, cmd = create_process(cmd, run_as_root=run_as_root, addl_env=addl_env)
|
||||||
|
_stdout, _stderr = obj.communicate(_process_input)
|
||||||
|
returncode = obj.returncode
|
||||||
|
obj.stdin.close()
|
||||||
|
_stdout = helpers.safe_decode_utf8(_stdout)
|
||||||
|
_stderr = helpers.safe_decode_utf8(_stderr)
|
||||||
|
return _stdout, _stderr, returncode
|
||||||
|
|
||||||
|
|
||||||
def execute_rootwrap_daemon(cmd, process_input, addl_env):
|
def execute_rootwrap_daemon(cmd, process_input, addl_env):
|
||||||
cmd = list(map(str, addl_env_args(addl_env) + cmd))
|
cmd = list(map(str, addl_env_args(addl_env) + cmd))
|
||||||
# NOTE(twilson) oslo_rootwrap.daemon will raise on filter match
|
# NOTE(twilson) oslo_rootwrap.daemon will raise on filter match
|
||||||
@ -99,31 +108,34 @@ def execute_rootwrap_daemon(cmd, process_input, addl_env):
|
|||||||
LOG.debug("Running command (rootwrap daemon): %s", cmd)
|
LOG.debug("Running command (rootwrap daemon): %s", cmd)
|
||||||
client = RootwrapDaemonHelper.get_client()
|
client = RootwrapDaemonHelper.get_client()
|
||||||
try:
|
try:
|
||||||
return client.execute(cmd, process_input)
|
returncode, _stdout, _stderr = client.execute(cmd, process_input)
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
LOG.error("Rootwrap error running command: %s", cmd)
|
LOG.error("Rootwrap error running command: %s", cmd)
|
||||||
|
|
||||||
|
_stdout = helpers.safe_decode_utf8(_stdout)
|
||||||
|
_stderr = helpers.safe_decode_utf8(_stderr)
|
||||||
|
return _stdout, _stderr, returncode
|
||||||
|
|
||||||
|
|
||||||
def execute(cmd, process_input=None, addl_env=None,
|
def execute(cmd, process_input=None, addl_env=None,
|
||||||
check_exit_code=True, return_stderr=False, log_fail_as_error=True,
|
check_exit_code=True, return_stderr=False, log_fail_as_error=True,
|
||||||
extra_ok_codes=None, run_as_root=False):
|
extra_ok_codes=None, run_as_root=False, privsep_exec=False):
|
||||||
try:
|
try:
|
||||||
if process_input is not None:
|
if process_input is not None:
|
||||||
_process_input = encodeutils.to_utf8(process_input)
|
_process_input = encodeutils.to_utf8(process_input)
|
||||||
else:
|
else:
|
||||||
_process_input = None
|
_process_input = None
|
||||||
if run_as_root and cfg.CONF.AGENT.root_helper_daemon:
|
|
||||||
returncode, _stdout, _stderr = (
|
if run_as_root and privsep_exec:
|
||||||
execute_rootwrap_daemon(cmd, process_input, addl_env))
|
_stdout, _stderr, returncode = priv_utils.execute_process(
|
||||||
|
cmd, _process_input, addl_env)
|
||||||
|
elif run_as_root and cfg.CONF.AGENT.root_helper_daemon:
|
||||||
|
_stdout, _stderr, returncode = execute_rootwrap_daemon(
|
||||||
|
cmd, process_input, addl_env)
|
||||||
else:
|
else:
|
||||||
obj, cmd = create_process(cmd, run_as_root=run_as_root,
|
_stdout, _stderr, returncode = _execute_process(
|
||||||
addl_env=addl_env)
|
cmd, _process_input, addl_env, run_as_root)
|
||||||
_stdout, _stderr = obj.communicate(_process_input)
|
|
||||||
returncode = obj.returncode
|
|
||||||
obj.stdin.close()
|
|
||||||
_stdout = helpers.safe_decode_utf8(_stdout)
|
|
||||||
_stderr = helpers.safe_decode_utf8(_stderr)
|
|
||||||
|
|
||||||
extra_ok_codes = extra_ok_codes or []
|
extra_ok_codes = extra_ok_codes or []
|
||||||
if returncode and returncode not in extra_ok_codes:
|
if returncode and returncode not in extra_ok_codes:
|
||||||
@ -202,10 +214,11 @@ def find_fork_top_parent(pid):
|
|||||||
return pid
|
return pid
|
||||||
|
|
||||||
|
|
||||||
def kill_process(pid, signal, run_as_root=False):
|
def kill_process(pid, signal, run_as_root=False, privsep_exec=False):
|
||||||
"""Kill the process with the given pid using the given signal."""
|
"""Kill the process with the given pid using the given signal."""
|
||||||
try:
|
try:
|
||||||
execute(['kill', '-%d' % signal, pid], run_as_root=run_as_root)
|
execute(['kill', '-%d' % signal, pid], run_as_root=run_as_root,
|
||||||
|
privsep_exec=privsep_exec)
|
||||||
except exceptions.ProcessExecutionError:
|
except exceptions.ProcessExecutionError:
|
||||||
if process_is_running(pid):
|
if process_is_running(pid):
|
||||||
raise
|
raise
|
||||||
|
@ -100,7 +100,7 @@ def kill_process(pid, signal, run_as_root=False):
|
|||||||
|
|
||||||
def execute(cmd, process_input=None, addl_env=None,
|
def execute(cmd, process_input=None, addl_env=None,
|
||||||
check_exit_code=True, return_stderr=False, log_fail_as_error=True,
|
check_exit_code=True, return_stderr=False, log_fail_as_error=True,
|
||||||
extra_ok_codes=None, run_as_root=False):
|
extra_ok_codes=None, run_as_root=False, privsep_exec=False):
|
||||||
|
|
||||||
if process_input is not None:
|
if process_input is not None:
|
||||||
_process_input = encodeutils.to_utf8(process_input)
|
_process_input = encodeutils.to_utf8(process_input)
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from eventlet.green import subprocess
|
||||||
|
from neutron_lib.utils import helpers
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
from oslo_utils import fileutils
|
from oslo_utils import fileutils
|
||||||
|
|
||||||
@ -47,3 +49,36 @@ def _find_listen_pids_namespace(namespace):
|
|||||||
@privileged.default.entrypoint
|
@privileged.default.entrypoint
|
||||||
def delete_if_exists(path, remove=os.unlink):
|
def delete_if_exists(path, remove=os.unlink):
|
||||||
fileutils.delete_if_exists(path, remove=remove)
|
fileutils.delete_if_exists(path, remove=remove)
|
||||||
|
|
||||||
|
|
||||||
|
@privileged.default.entrypoint
|
||||||
|
def execute_process(cmd, _process_input, addl_env):
|
||||||
|
obj, cmd = _create_process(cmd, addl_env=addl_env)
|
||||||
|
_stdout, _stderr = obj.communicate(_process_input)
|
||||||
|
returncode = obj.returncode
|
||||||
|
obj.stdin.close()
|
||||||
|
_stdout = helpers.safe_decode_utf8(_stdout)
|
||||||
|
_stderr = helpers.safe_decode_utf8(_stderr)
|
||||||
|
return _stdout, _stderr, returncode
|
||||||
|
|
||||||
|
|
||||||
|
def _addl_env_args(addl_env):
|
||||||
|
"""Build arguments for adding additional environment vars with env"""
|
||||||
|
|
||||||
|
# NOTE (twilson) If using rootwrap, an EnvFilter should be set up for the
|
||||||
|
# command instead of a CommandFilter.
|
||||||
|
if addl_env is None:
|
||||||
|
return []
|
||||||
|
return ['env'] + ['%s=%s' % pair for pair in addl_env.items()]
|
||||||
|
|
||||||
|
|
||||||
|
def _create_process(cmd, addl_env=None):
|
||||||
|
"""Create a process object for the given command.
|
||||||
|
|
||||||
|
The return value will be a tuple of the process object and the
|
||||||
|
list of command arguments used to create it.
|
||||||
|
"""
|
||||||
|
cmd = list(map(str, _addl_env_args(addl_env) + list(cmd)))
|
||||||
|
obj = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
return obj, cmd
|
||||||
|
@ -620,7 +620,8 @@ class NamespaceFixture(fixtures.Fixture):
|
|||||||
if self.ip_wrapper.netns.exists(self.name):
|
if self.ip_wrapper.netns.exists(self.name):
|
||||||
for pid in ip_lib.list_namespace_pids(self.name):
|
for pid in ip_lib.list_namespace_pids(self.name):
|
||||||
utils.kill_process(pid, signal.SIGKILL,
|
utils.kill_process(pid, signal.SIGKILL,
|
||||||
run_as_root=True)
|
run_as_root=True,
|
||||||
|
privsep_exec=True)
|
||||||
self.ip_wrapper.netns.delete(self.name)
|
self.ip_wrapper.netns.delete(self.name)
|
||||||
except helpers.TestTimerTimeout:
|
except helpers.TestTimerTimeout:
|
||||||
LOG.warning('Namespace %s was not deleted due to a timeout.',
|
LOG.warning('Namespace %s was not deleted due to a timeout.',
|
||||||
|
@ -134,8 +134,8 @@ class TcPolicyClassTestCase(functional_base.BaseSudoTestCase):
|
|||||||
|
|
||||||
bytes = tc_classes[0]['stats']['bytes']
|
bytes = tc_classes[0]['stats']['bytes']
|
||||||
packets = tc_classes[0]['stats']['packets']
|
packets = tc_classes[0]['stats']['packets']
|
||||||
net_helpers.assert_ping(self.ns[1], netaddr.IPNetwork(self.ip[0]).ip,
|
net_helpers.assert_ping(
|
||||||
count=1)
|
self.ns[1], str(netaddr.IPNetwork(self.ip[0]).ip), count=1)
|
||||||
tc_classes = tc_lib.list_tc_policy_class(self.device[0],
|
tc_classes = tc_lib.list_tc_policy_class(self.device[0],
|
||||||
namespace=self.ns[0])
|
namespace=self.ns[0])
|
||||||
self.assertGreater(tc_classes[0]['stats']['bytes'], bytes)
|
self.assertGreater(tc_classes[0]['stats']['bytes'], bytes)
|
||||||
@ -268,7 +268,7 @@ class TcFiltersTestCase(functional_base.BaseSudoTestCase):
|
|||||||
'device': self.device[0]})
|
'device': self.device[0]})
|
||||||
|
|
||||||
net_helpers.assert_ping(
|
net_helpers.assert_ping(
|
||||||
self.ns[1], netaddr.IPNetwork(self.ip_vxlan[0]).ip, count=1)
|
self.ns[1], str(netaddr.IPNetwork(self.ip_vxlan[0]).ip), count=1)
|
||||||
tc_classes = tc_lib.list_tc_policy_class(self.device[0],
|
tc_classes = tc_lib.list_tc_policy_class(self.device[0],
|
||||||
namespace=self.ns[0])
|
namespace=self.ns[0])
|
||||||
for tc_class in tc_classes:
|
for tc_class in tc_classes:
|
||||||
|
@ -2595,13 +2595,17 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||||||
'qrouter-bar', self.conf, agent.driver, agent.use_ipv6)
|
'qrouter-bar', self.conf, agent.driver, agent.use_ipv6)
|
||||||
ns.create()
|
ns.create()
|
||||||
|
|
||||||
calls = [mock.call(['sysctl', '-w', 'net.ipv4.ip_forward=1']),
|
calls = [mock.call(['sysctl', '-w', 'net.ipv4.ip_forward=1'],
|
||||||
mock.call(['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1']),
|
privsep_exec=True),
|
||||||
|
mock.call(['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1'],
|
||||||
|
privsep_exec=True),
|
||||||
mock.call(
|
mock.call(
|
||||||
['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2'])]
|
['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2'],
|
||||||
|
privsep_exec=True)]
|
||||||
if agent.use_ipv6:
|
if agent.use_ipv6:
|
||||||
calls.append(mock.call(
|
calls.append(mock.call(
|
||||||
['sysctl', '-w', 'net.ipv6.conf.all.forwarding=1']))
|
['sysctl', '-w', 'net.ipv6.conf.all.forwarding=1'],
|
||||||
|
privsep_exec=True))
|
||||||
|
|
||||||
self.mock_ip.netns.execute.assert_has_calls(calls)
|
self.mock_ip.netns.execute.assert_has_calls(calls)
|
||||||
|
|
||||||
|
@ -217,13 +217,14 @@ class TestDvrFipNs(base.BaseTestCase):
|
|||||||
bind_cmd = ['sysctl', '-w', 'net.ipv4.ip_nonlocal_bind=1']
|
bind_cmd = ['sysctl', '-w', 'net.ipv4.ip_nonlocal_bind=1']
|
||||||
expected = [mock.call(netns_cmd + bind_cmd, check_exit_code=True,
|
expected = [mock.call(netns_cmd + bind_cmd, check_exit_code=True,
|
||||||
extra_ok_codes=None, log_fail_as_error=False,
|
extra_ok_codes=None, log_fail_as_error=False,
|
||||||
run_as_root=True)]
|
run_as_root=True, privsep_exec=True)]
|
||||||
|
|
||||||
if old_kernel:
|
if old_kernel:
|
||||||
expected.append(mock.call(bind_cmd, check_exit_code=True,
|
expected.append(mock.call(bind_cmd, check_exit_code=True,
|
||||||
extra_ok_codes=None,
|
extra_ok_codes=None,
|
||||||
log_fail_as_error=True,
|
log_fail_as_error=True,
|
||||||
run_as_root=True))
|
run_as_root=True,
|
||||||
|
privsep_exec=True))
|
||||||
|
|
||||||
execute.assert_has_calls(expected)
|
execute.assert_has_calls(expected)
|
||||||
|
|
||||||
|
@ -50,7 +50,8 @@ class TestDvrSnatNs(base.BaseTestCase):
|
|||||||
loose_cmd = ['sysctl', '-w', 'net.netfilter.nf_conntrack_tcp_loose=0']
|
loose_cmd = ['sysctl', '-w', 'net.netfilter.nf_conntrack_tcp_loose=0']
|
||||||
expected = [mock.call(netns_cmd + loose_cmd,
|
expected = [mock.call(netns_cmd + loose_cmd,
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True)]
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=True)]
|
||||||
|
|
||||||
create.assert_called_once_with(self.snat_ns.name)
|
create.assert_called_once_with(self.snat_ns.name)
|
||||||
execute.assert_has_calls(expected)
|
execute.assert_has_calls(expected)
|
||||||
|
@ -110,8 +110,10 @@ class TestHybridIptablesHelper(base.BaseTestCase):
|
|||||||
def test_overloaded_remove_conntrack(self):
|
def test_overloaded_remove_conntrack(self):
|
||||||
with mock.patch.object(iptables_firewall.IptablesFirewallDriver,
|
with mock.patch.object(iptables_firewall.IptablesFirewallDriver,
|
||||||
'_remove_conntrack_entries_from_port_deleted') as rcefpd, \
|
'_remove_conntrack_entries_from_port_deleted') as rcefpd, \
|
||||||
mock.patch("neutron.agent.linux.ip_conntrack.IpConntrackManager"
|
mock.patch("neutron.agent.linux.ip_conntrack."
|
||||||
"._populate_initial_zone_map"):
|
"IpConntrackManager._populate_initial_zone_map"), \
|
||||||
|
mock.patch.object(iptables_firewall.IptablesFirewallDriver,
|
||||||
|
'_check_netfilter_for_bridges'):
|
||||||
firewall = iptables.get_iptables_driver_instance()
|
firewall = iptables.get_iptables_driver_instance()
|
||||||
firewall._remove_conntrack_entries_from_port_deleted(None)
|
firewall._remove_conntrack_entries_from_port_deleted(None)
|
||||||
rcefpd.assert_not_called()
|
rcefpd.assert_not_called()
|
||||||
|
@ -138,7 +138,8 @@ class TestProcessManager(base.BaseTestCase):
|
|||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
extra_ok_codes=None,
|
extra_ok_codes=None,
|
||||||
run_as_root=False,
|
run_as_root=False,
|
||||||
log_fail_as_error=True)
|
log_fail_as_error=True,
|
||||||
|
privsep_exec=False)
|
||||||
|
|
||||||
def test_enable_with_namespace(self):
|
def test_enable_with_namespace(self):
|
||||||
callback = mock.Mock()
|
callback = mock.Mock()
|
||||||
@ -228,7 +229,8 @@ class TestProcessManager(base.BaseTestCase):
|
|||||||
manager.disable()
|
manager.disable()
|
||||||
utils.assert_has_calls([
|
utils.assert_has_calls([
|
||||||
mock.call.execute(['kill', '-9', 4],
|
mock.call.execute(['kill', '-9', 4],
|
||||||
run_as_root=False)])
|
run_as_root=False,
|
||||||
|
privsep_exec=False)])
|
||||||
|
|
||||||
def test_disable_namespace(self):
|
def test_disable_namespace(self):
|
||||||
with mock.patch.object(ep.ProcessManager, 'pid') as pid:
|
with mock.patch.object(ep.ProcessManager, 'pid') as pid:
|
||||||
@ -242,7 +244,8 @@ class TestProcessManager(base.BaseTestCase):
|
|||||||
manager.disable()
|
manager.disable()
|
||||||
utils.assert_has_calls([
|
utils.assert_has_calls([
|
||||||
mock.call.execute(['kill', '-9', 4],
|
mock.call.execute(['kill', '-9', 4],
|
||||||
run_as_root=True)])
|
run_as_root=True,
|
||||||
|
privsep_exec=False)])
|
||||||
|
|
||||||
def test_disable_not_active(self):
|
def test_disable_not_active(self):
|
||||||
with mock.patch.object(ep.ProcessManager, 'pid') as pid:
|
with mock.patch.object(ep.ProcessManager, 'pid') as pid:
|
||||||
@ -284,7 +287,8 @@ class TestProcessManager(base.BaseTestCase):
|
|||||||
return_value=kill_script_exists):
|
return_value=kill_script_exists):
|
||||||
manager.disable()
|
manager.disable()
|
||||||
utils.execute.assert_called_with(
|
utils.execute.assert_called_with(
|
||||||
expected_cmd, run_as_root=bool(namespace))
|
expected_cmd, run_as_root=bool(namespace),
|
||||||
|
privsep_exec=False)
|
||||||
|
|
||||||
def test_disable_custom_kill_script_no_namespace(self):
|
def test_disable_custom_kill_script_no_namespace(self):
|
||||||
self._test_disable_custom_kill_script(
|
self._test_disable_custom_kill_script(
|
||||||
|
@ -858,7 +858,7 @@ class TestIpNetnsCommand(TestIPCmdBase):
|
|||||||
['ip', 'netns', 'exec', 'ns',
|
['ip', 'netns', 'exec', 'ns',
|
||||||
'sysctl', '-w', 'net.ipv4.conf.all.promote_secondaries=1'],
|
'sysctl', '-w', 'net.ipv4.conf.all.promote_secondaries=1'],
|
||||||
run_as_root=True, check_exit_code=True, extra_ok_codes=None,
|
run_as_root=True, check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True)
|
log_fail_as_error=True, privsep_exec=True)
|
||||||
|
|
||||||
@mock.patch.object(priv_lib, 'remove_netns')
|
@mock.patch.object(priv_lib, 'remove_netns')
|
||||||
def test_delete_namespace(self, remove):
|
def test_delete_namespace(self, remove):
|
||||||
@ -899,7 +899,8 @@ class TestIpNetnsCommand(TestIPCmdBase):
|
|||||||
run_as_root=True,
|
run_as_root=True,
|
||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
extra_ok_codes=None,
|
extra_ok_codes=None,
|
||||||
log_fail_as_error=True)
|
log_fail_as_error=True,
|
||||||
|
privsep_exec=False)
|
||||||
|
|
||||||
def test_execute_env_var_prepend(self):
|
def test_execute_env_var_prepend(self):
|
||||||
self.parent.namespace = 'ns'
|
self.parent.namespace = 'ns'
|
||||||
@ -911,7 +912,7 @@ class TestIpNetnsCommand(TestIPCmdBase):
|
|||||||
['%s=%s' % (k, v) for k, v in env.items()] +
|
['%s=%s' % (k, v) for k, v in env.items()] +
|
||||||
['ip', 'link', 'list'],
|
['ip', 'link', 'list'],
|
||||||
run_as_root=True, check_exit_code=True, extra_ok_codes=None,
|
run_as_root=True, check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True)
|
log_fail_as_error=True, privsep_exec=False)
|
||||||
|
|
||||||
def test_execute_nosudo_with_no_namespace(self):
|
def test_execute_nosudo_with_no_namespace(self):
|
||||||
with mock.patch('neutron.agent.common.utils.execute') as execute:
|
with mock.patch('neutron.agent.common.utils.execute') as execute:
|
||||||
@ -921,7 +922,8 @@ class TestIpNetnsCommand(TestIPCmdBase):
|
|||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
extra_ok_codes=None,
|
extra_ok_codes=None,
|
||||||
run_as_root=False,
|
run_as_root=False,
|
||||||
log_fail_as_error=True)
|
log_fail_as_error=True,
|
||||||
|
privsep_exec=False)
|
||||||
|
|
||||||
|
|
||||||
class TestDeviceExists(base.BaseTestCase):
|
class TestDeviceExists(base.BaseTestCase):
|
||||||
@ -1378,12 +1380,18 @@ class TestArpPing(TestIPCmdBase):
|
|||||||
self.assertTrue(spawn_n.called)
|
self.assertTrue(spawn_n.called)
|
||||||
mIPWrapper.assert_has_calls([
|
mIPWrapper.assert_has_calls([
|
||||||
mock.call(namespace=mock.sentinel.ns_name),
|
mock.call(namespace=mock.sentinel.ns_name),
|
||||||
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1]),
|
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1],
|
||||||
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1]),
|
privsep_exec=True),
|
||||||
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2]),
|
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1],
|
||||||
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2]),
|
privsep_exec=True),
|
||||||
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2]),
|
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2],
|
||||||
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2])])
|
privsep_exec=True),
|
||||||
|
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2],
|
||||||
|
privsep_exec=True),
|
||||||
|
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2],
|
||||||
|
privsep_exec=True),
|
||||||
|
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2],
|
||||||
|
privsep_exec=True)])
|
||||||
|
|
||||||
ip_wrapper = mIPWrapper(namespace=mock.sentinel.ns_name)
|
ip_wrapper = mIPWrapper(namespace=mock.sentinel.ns_name)
|
||||||
|
|
||||||
@ -1395,7 +1403,8 @@ class TestArpPing(TestIPCmdBase):
|
|||||||
'-w', mock.ANY,
|
'-w', mock.ANY,
|
||||||
address]
|
address]
|
||||||
ip_wrapper.netns.execute.assert_any_call(arping_cmd,
|
ip_wrapper.netns.execute.assert_any_call(arping_cmd,
|
||||||
extra_ok_codes=mock.ANY)
|
extra_ok_codes=mock.ANY,
|
||||||
|
privsep_exec=True)
|
||||||
|
|
||||||
@mock.patch.object(ip_lib, 'IPWrapper')
|
@mock.patch.object(ip_lib, 'IPWrapper')
|
||||||
@mock.patch('eventlet.spawn_n')
|
@mock.patch('eventlet.spawn_n')
|
||||||
@ -1415,7 +1424,8 @@ class TestArpPing(TestIPCmdBase):
|
|||||||
# should return early with a single call when ENODEV
|
# should return early with a single call when ENODEV
|
||||||
mIPWrapper.assert_has_calls([
|
mIPWrapper.assert_has_calls([
|
||||||
mock.call(namespace=mock.sentinel.ns_name),
|
mock.call(namespace=mock.sentinel.ns_name),
|
||||||
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1])
|
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1],
|
||||||
|
privsep_exec=True)
|
||||||
] * 1)
|
] * 1)
|
||||||
|
|
||||||
@mock.patch('eventlet.spawn_n')
|
@mock.patch('eventlet.spawn_n')
|
||||||
@ -1458,7 +1468,7 @@ class TestSysctl(base.BaseTestCase):
|
|||||||
dev.disable_ipv6()
|
dev.disable_ipv6()
|
||||||
self.execute.assert_called_once_with(
|
self.execute.assert_called_once_with(
|
||||||
['sysctl', '-w', 'net.ipv6.conf.tap0.disable_ipv6=1'],
|
['sysctl', '-w', 'net.ipv6.conf.tap0.disable_ipv6=1'],
|
||||||
log_fail_as_error=True, run_as_root=True)
|
log_fail_as_error=True, run_as_root=True, privsep_exec=True)
|
||||||
|
|
||||||
def test_disable_ipv6_when_ipv6_globally_disabled(self):
|
def test_disable_ipv6_when_ipv6_globally_disabled(self):
|
||||||
dev = ip_lib.IPDevice('tap0', 'ns1')
|
dev = ip_lib.IPDevice('tap0', 'ns1')
|
||||||
@ -1483,7 +1493,8 @@ class TestConntrack(base.BaseTestCase):
|
|||||||
'--dport', dport]
|
'--dport', dport]
|
||||||
device.delete_socket_conntrack_state(ip_str, dport, protocol)
|
device.delete_socket_conntrack_state(ip_str, dport, protocol)
|
||||||
self.execute.assert_called_once_with(expect_cmd, check_exit_code=True,
|
self.execute.assert_called_once_with(expect_cmd, check_exit_code=True,
|
||||||
extra_ok_codes=[1])
|
extra_ok_codes=[1],
|
||||||
|
privsep_exec=True)
|
||||||
|
|
||||||
|
|
||||||
class ParseIpRuleTestCase(base.BaseTestCase):
|
class ParseIpRuleTestCase(base.BaseTestCase):
|
||||||
|
@ -47,6 +47,8 @@ class KeepalivedBaseTestCase(base.BaseTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(KeepalivedBaseTestCase, self).setUp()
|
super(KeepalivedBaseTestCase, self).setUp()
|
||||||
l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF)
|
l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF)
|
||||||
|
self._mock_no_track_supported = mock.patch.object(
|
||||||
|
keepalived, '_is_keepalived_use_no_track_supported')
|
||||||
|
|
||||||
|
|
||||||
class KeepalivedGetFreeRangeTestCase(KeepalivedBaseTestCase):
|
class KeepalivedGetFreeRangeTestCase(KeepalivedBaseTestCase):
|
||||||
@ -193,6 +195,7 @@ class KeepalivedConfTestCase(KeepalivedBaseTestCase,
|
|||||||
self.assertEqual(self.expected, config.get_config_str())
|
self.assertEqual(self.expected, config.get_config_str())
|
||||||
|
|
||||||
def test_config_generation_no_track_not_supported(self):
|
def test_config_generation_no_track_not_supported(self):
|
||||||
|
self._mock_no_track_supported.start().return_value = False
|
||||||
config = self._get_config()
|
config = self._get_config()
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
keepalived, '_is_keepalived_use_no_track_supported',
|
keepalived, '_is_keepalived_use_no_track_supported',
|
||||||
|
@ -171,7 +171,8 @@ class TestFloatingIPTcCommandBase(base.BaseTestCase):
|
|||||||
run_as_root=True,
|
run_as_root=True,
|
||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
log_fail_as_error=True,
|
log_fail_as_error=True,
|
||||||
extra_ok_codes=None
|
extra_ok_codes=None,
|
||||||
|
privsep_exec=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def _test__get_filterid_for_ip(self, filters):
|
def _test__get_filterid_for_ip(self, filters):
|
||||||
@ -236,7 +237,8 @@ class TestFloatingIPTcCommandBase(base.BaseTestCase):
|
|||||||
run_as_root=True,
|
run_as_root=True,
|
||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
log_fail_as_error=True,
|
log_fail_as_error=True,
|
||||||
extra_ok_codes=None
|
extra_ok_codes=None,
|
||||||
|
privsep_exec=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def _test__get_qdisc_filters(self, filters):
|
def _test__get_qdisc_filters(self, filters):
|
||||||
@ -277,7 +279,8 @@ class TestFloatingIPTcCommandBase(base.BaseTestCase):
|
|||||||
run_as_root=True,
|
run_as_root=True,
|
||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
log_fail_as_error=True,
|
log_fail_as_error=True,
|
||||||
extra_ok_codes=None
|
extra_ok_codes=None,
|
||||||
|
privsep_exec=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def test__get_or_create_qdisc(self):
|
def test__get_or_create_qdisc(self):
|
||||||
@ -382,7 +385,8 @@ class TestFloatingIPTcCommand(base.BaseTestCase):
|
|||||||
run_as_root=True,
|
run_as_root=True,
|
||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
log_fail_as_error=True,
|
log_fail_as_error=True,
|
||||||
extra_ok_codes=None
|
extra_ok_codes=None,
|
||||||
|
privsep_exec=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_set_ip_rate_limit_no_qdisc_without_chain(self):
|
def test_set_ip_rate_limit_no_qdisc_without_chain(self):
|
||||||
@ -409,7 +413,8 @@ class TestFloatingIPTcCommand(base.BaseTestCase):
|
|||||||
run_as_root=True,
|
run_as_root=True,
|
||||||
check_exit_code=True,
|
check_exit_code=True,
|
||||||
log_fail_as_error=True,
|
log_fail_as_error=True,
|
||||||
extra_ok_codes=None
|
extra_ok_codes=None,
|
||||||
|
privsep_exec=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_filter_id_for_ip(self):
|
def test_get_filter_id_for_ip(self):
|
||||||
|
@ -25,6 +25,7 @@ from oslo_config import cfg
|
|||||||
import oslo_i18n
|
import oslo_i18n
|
||||||
|
|
||||||
from neutron.agent.linux import utils
|
from neutron.agent.linux import utils
|
||||||
|
from neutron.privileged.agent.linux import utils as priv_utils
|
||||||
from neutron.tests import base
|
from neutron.tests import base
|
||||||
|
|
||||||
|
|
||||||
@ -46,7 +47,15 @@ class AgentUtilsExecuteTest(base.BaseTestCase):
|
|||||||
result = utils.execute(["ls", self.test_file])
|
result = utils.execute(["ls", self.test_file])
|
||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
def test_with_helper(self):
|
def test_with_root_privileges_privsep(self):
|
||||||
|
with mock.patch.object(priv_utils, 'execute_process') as \
|
||||||
|
mock_execute_process:
|
||||||
|
mock_execute_process.return_value = ['', '', 0]
|
||||||
|
utils.execute(['ls', self.test_file], run_as_root=True,
|
||||||
|
privsep_exec=True)
|
||||||
|
mock_execute_process.assert_called_once()
|
||||||
|
|
||||||
|
def test_with_root_privileges_rootwrap(self):
|
||||||
expected = "ls %s\n" % self.test_file
|
expected = "ls %s\n" % self.test_file
|
||||||
self.mock_popen.return_value = [expected, ""]
|
self.mock_popen.return_value = [expected, ""]
|
||||||
self.config(group='AGENT', root_helper='echo')
|
self.config(group='AGENT', root_helper='echo')
|
||||||
@ -54,7 +63,7 @@ class AgentUtilsExecuteTest(base.BaseTestCase):
|
|||||||
self.assertEqual(result, expected)
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
@mock.patch.object(utils.RootwrapDaemonHelper, 'get_client')
|
@mock.patch.object(utils.RootwrapDaemonHelper, 'get_client')
|
||||||
def test_with_helper_exception(self, get_client):
|
def test_with_root_privileges_rootwrap_exception(self, get_client):
|
||||||
client_inst = mock.Mock()
|
client_inst = mock.Mock()
|
||||||
client_inst.execute.side_effect = RuntimeError
|
client_inst.execute.side_effect = RuntimeError
|
||||||
get_client.return_value = client_inst
|
get_client.return_value = client_inst
|
||||||
@ -229,10 +238,11 @@ class TestKillProcess(base.BaseTestCase):
|
|||||||
side_effect=exc) as mock_execute:
|
side_effect=exc) as mock_execute:
|
||||||
with mock.patch.object(utils, 'process_is_running',
|
with mock.patch.object(utils, 'process_is_running',
|
||||||
return_value=not pid_killed):
|
return_value=not pid_killed):
|
||||||
utils.kill_process(pid, kill_signal, run_as_root=True)
|
utils.kill_process(pid, kill_signal, run_as_root=True,
|
||||||
|
privsep_exec=False)
|
||||||
|
|
||||||
mock_execute.assert_called_with(['kill', '-%d' % kill_signal, pid],
|
mock_execute.assert_called_with(['kill', '-%d' % kill_signal, pid],
|
||||||
run_as_root=True)
|
run_as_root=True, privsep_exec=False)
|
||||||
|
|
||||||
def test_kill_process_returns_none_for_valid_pid(self):
|
def test_kill_process_returns_none_for_valid_pid(self):
|
||||||
self._test_kill_process('1')
|
self._test_kill_process('1')
|
||||||
|
@ -66,34 +66,40 @@ class TestLinuxBridgeARPSpoofing(base.BaseTestCase):
|
|||||||
expected = [
|
expected = [
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'],
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
|
||||||
'neutronMAC-%s' % vif, '-P', 'DROP'],
|
'neutronMAC-%s' % vif, '-P', 'DROP'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
|
||||||
'PREROUTING', '-i', vif, '-j', mac_chain],
|
'PREROUTING', '-i', vif, '-j', mac_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
|
||||||
mac_chain, '-i', vif,
|
mac_chain, '-i', vif,
|
||||||
'--among-src', '%s' % ','.join(sorted(mac_addresses)),
|
'--among-src', '%s' % ','.join(sorted(mac_addresses)),
|
||||||
'-j', 'RETURN'],
|
'-j', 'RETURN'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
|
||||||
spoof_chain, '-P', 'DROP'],
|
spoof_chain, '-P', 'DROP'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
|
||||||
spoof_chain],
|
spoof_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
]
|
]
|
||||||
for addr in sorted(ip_addresses):
|
for addr in sorted(ip_addresses):
|
||||||
expected.extend([
|
expected.extend([
|
||||||
@ -101,7 +107,8 @@ class TestLinuxBridgeARPSpoofing(base.BaseTestCase):
|
|||||||
spoof_chain, '-p', 'ARP',
|
spoof_chain, '-p', 'ARP',
|
||||||
'--arp-ip-src', addr, '-j', 'ACCEPT'],
|
'--arp-ip-src', addr, '-j', 'ACCEPT'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
])
|
])
|
||||||
expected.extend([
|
expected.extend([
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
@ -109,7 +116,8 @@ class TestLinuxBridgeARPSpoofing(base.BaseTestCase):
|
|||||||
'PREROUTING', '-i', vif, '-j',
|
'PREROUTING', '-i', vif, '-j',
|
||||||
spoof_chain, '-p', 'ARP'],
|
spoof_chain, '-p', 'ARP'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
])
|
])
|
||||||
|
|
||||||
arp_protect.setup_arp_spoofing_protection(vif, port)
|
arp_protect.setup_arp_spoofing_protection(vif, port)
|
||||||
@ -129,56 +137,68 @@ class TestLinuxBridgeARPSpoofing(base.BaseTestCase):
|
|||||||
expected = [
|
expected = [
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'],
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-D',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-D',
|
||||||
'PREROUTING', '-i', VIF, '-j', spoof_chain,
|
'PREROUTING', '-i', VIF, '-j', spoof_chain,
|
||||||
'-p', 'ARP'],
|
'-p', 'ARP'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
|
||||||
spoof_chain],
|
spoof_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-X',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-X',
|
||||||
spoof_chain],
|
spoof_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
|
||||||
mac_chain],
|
mac_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-X',
|
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-X',
|
||||||
mac_chain],
|
mac_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-L'],
|
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-L'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-D',
|
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-D',
|
||||||
'FORWARD', '-i', VIF, '-j', spoof_chain,
|
'FORWARD', '-i', VIF, '-j', spoof_chain,
|
||||||
'-p', 'ARP'],
|
'-p', 'ARP'],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-F',
|
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-F',
|
||||||
spoof_chain],
|
spoof_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-X',
|
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-X',
|
||||||
spoof_chain],
|
spoof_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-F',
|
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-F',
|
||||||
mac_chain],
|
mac_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-X',
|
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-X',
|
||||||
mac_chain],
|
mac_chain],
|
||||||
check_exit_code=True, extra_ok_codes=None,
|
check_exit_code=True, extra_ok_codes=None,
|
||||||
log_fail_as_error=True, run_as_root=True),
|
log_fail_as_error=True, run_as_root=True,
|
||||||
|
privsep_exec=False),
|
||||||
]
|
]
|
||||||
|
|
||||||
arp_protect.delete_arp_spoofing_protection([VIF])
|
arp_protect.delete_arp_spoofing_protection([VIF])
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
other:
|
||||||
|
- |
|
||||||
|
As defined in `Migrate from oslo.rootwrap to oslo.privsep
|
||||||
|
<https://opendev.org/openstack/governance/src/branch/master/goals/selected/wallaby/migrate-to-privsep.rst>`_,
|
||||||
|
all OpenStack proyects should migrate from oslo.rootwrap to oslo.privsep
|
||||||
|
because "oslo.privsep offers a superior security model, faster and more
|
||||||
|
secure".
|
||||||
|
This migration will end with the deprecation and removal of oslo.rootwrap
|
||||||
|
from Neutron. To ensure the quality of the Neutron code, this migration
|
||||||
|
will be done sequentially in several patches, checking none of them breaks
|
||||||
|
the current functionality.
|
||||||
|
In order to easily migrate to execute all external commands inside a
|
||||||
|
privsep context, a new input variable "privsep_exec", that defaults to
|
||||||
|
"False", is added to ``neutron.agent.linux.utils.execute``. That will
|
||||||
|
divert the code to a privsep decorated executor.
|
||||||
|
Once the migration finishes, this new input parameter will be removed.
|
Loading…
Reference in New Issue
Block a user