Change ip_lib decorators order

Change the execution order of:
- @privileged.default.entrypoint
- @lockutils.synchronized("privileged-ip-lib")

"synchronized" decorator holds the execution of the function until
the lock is released. Using the current decorator ordering, this
active wait is done inside the privsep context. This can exhaust
the number of execution threads reserved for the privsep daemon.

Closes-Bug: #1833721

Change-Id: Ifcce954003e360f620f9131a36a08ab84cbe6193
This commit is contained in:
Rodolfo Alonso Hernandez 2019-09-19 10:58:32 +00:00
parent a309dee7c5
commit 2a7030a6b7
1 changed files with 43 additions and 88 deletions

View File

@ -11,6 +11,7 @@
# under the License.
import errno
import functools
import os
import socket
@ -24,6 +25,7 @@ from pyroute2.netlink.rtnl import ifinfmsg
from pyroute2.netlink.rtnl import ndmsg
from pyroute2 import NetlinkError
from pyroute2 import netns
import six
from neutron._i18n import _
from neutron import privileged
@ -34,6 +36,25 @@ _IP_VERSION_FAMILY_MAP = {4: socket.AF_INET, 6: socket.AF_INET6}
NETNS_RUN_DIR = '/var/run/netns'
@lockutils.synchronized("privileged-ip-lib")
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
def _sync(input_func):
# NOTE(ralonsoh): this is needed because PY2 functools.update_wrapper do
# not handle correctly partial functions (nested decorators). This could be
# removed once we abandon support for PY2.
if six.PY2 and isinstance(input_func, functools.partial):
for asig in functools.WRAPPER_ASSIGNMENTS:
setattr(input_func, asig, '')
@six.wraps(input_func)
def sync_inner(*args, **kwargs):
return input_func(*args, **kwargs)
return sync_inner
def _get_scope_name(scope):
"""Return the name of the scope (given as a number), or the scope number
if the name is unknown.
@ -116,11 +137,8 @@ def _make_route_dict(destination, nexthop, device, scope):
'scope': scope}
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def get_routing_table(ip_version, namespace=None):
"""Return a list of dictionaries, each representing a route.
@ -179,11 +197,8 @@ def get_iproute(namespace):
return pyroute2.IPRoute()
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def open_namespace(namespace):
"""Open namespace to test if the namespace is ready to be manipulated"""
with pyroute2.NetNS(namespace, flags=0):
@ -275,11 +290,8 @@ def _run_iproute_addr(command, device, namespace, **kwargs):
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def add_ip_address(ip_version, ip, prefixlen, device, namespace, scope,
broadcast=None):
family = _IP_VERSION_FAMILY_MAP[ip_version]
@ -298,11 +310,8 @@ def add_ip_address(ip_version, ip, prefixlen, device, namespace, scope,
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def delete_ip_address(ip_version, ip, prefixlen, device, namespace):
family = _IP_VERSION_FAMILY_MAP[ip_version]
try:
@ -322,11 +331,8 @@ def delete_ip_address(ip_version, ip, prefixlen, device, namespace):
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def flush_ip_addresses(ip_version, device, namespace):
family = _IP_VERSION_FAMILY_MAP[ip_version]
try:
@ -339,11 +345,8 @@ def flush_ip_addresses(ip_version, device, namespace):
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def create_interface(ifname, namespace, kind, **kwargs):
ifname = ifname[:constants.DEVICE_NAME_MAX_LEN]
try:
@ -363,20 +366,14 @@ def create_interface(ifname, namespace, kind, **kwargs):
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def delete_interface(ifname, namespace, **kwargs):
_run_iproute_link("del", ifname, namespace, **kwargs)
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def interface_exists(ifname, namespace):
try:
idx = get_link_id(ifname, namespace)
@ -389,31 +386,22 @@ def interface_exists(ifname, namespace):
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def set_link_flags(device, namespace, flags):
link = _run_iproute_link("get", device, namespace)[0]
new_flags = flags | link['flags']
return _run_iproute_link("set", device, namespace, flags=new_flags)
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def set_link_attribute(device, namespace, **attributes):
return _run_iproute_link("set", device, namespace, **attributes)
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def get_link_attributes(device, namespace):
link = _run_iproute_link("get", device, namespace)[0]
return {
@ -429,11 +417,8 @@ def get_link_attributes(device, namespace):
}
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def add_neigh_entry(ip_version, ip_address, mac_address, device, namespace,
**kwargs):
"""Add a neighbour entry.
@ -454,11 +439,8 @@ def add_neigh_entry(ip_version, ip_address, mac_address, device, namespace,
**kwargs)
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def delete_neigh_entry(ip_version, ip_address, mac_address, device, namespace,
**kwargs):
"""Delete a neighbour entry.
@ -484,11 +466,8 @@ def delete_neigh_entry(ip_version, ip_address, mac_address, device, namespace,
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def dump_neigh_entries(ip_version, device, namespace, **kwargs):
"""Dump all neighbour entries.
@ -569,11 +548,8 @@ def make_serializable(value):
return value
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def get_link_devices(namespace, **kwargs):
"""List interfaces in a namespace
@ -603,11 +579,8 @@ def get_device_names(namespace, **kwargs):
return device_names
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def get_ip_addresses(namespace, **kwargs):
"""List of IP addresses in a namespace
@ -622,11 +595,8 @@ def get_ip_addresses(namespace, **kwargs):
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def list_ip_rules(namespace, ip_version, match=None, **kwargs):
"""List all IP rules"""
try:
@ -645,11 +615,8 @@ def list_ip_rules(namespace, ip_version, match=None, **kwargs):
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def add_ip_rule(namespace, **kwargs):
"""Add a new IP rule"""
try:
@ -665,11 +632,8 @@ def add_ip_rule(namespace, **kwargs):
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def delete_ip_rule(namespace, **kwargs):
"""Delete an IP rule"""
try:
@ -717,11 +681,8 @@ def _make_pyroute2_route_args(namespace, ip_version, cidr, device, via, table,
return args
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def add_ip_route(namespace, cidr, ip_version, device=None, via=None,
table=None, metric=None, scope=None, **kwargs):
"""Add an IP route"""
@ -737,11 +698,8 @@ def add_ip_route(namespace, cidr, ip_version, device=None, via=None,
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def list_ip_routes(namespace, ip_version, device=None, table=None, **kwargs):
"""List IP routes"""
kwargs.update(_make_pyroute2_route_args(
@ -755,11 +713,8 @@ def list_ip_routes(namespace, ip_version, device=None, table=None, **kwargs):
raise
@_sync
@privileged.default.entrypoint
# NOTE(slaweq): Because of issue with pyroute2.NetNS objects running in threads
# we need to lock this function to workaround this issue.
# For details please check https://bugs.launchpad.net/neutron/+bug/1811515
@lockutils.synchronized("privileged-ip-lib")
def delete_ip_route(namespace, cidr, ip_version, device=None, via=None,
table=None, scope=None, **kwargs):
"""Delete an IP route"""