Load system sysctl in amphora network namespace

In the default amphora image, load system sysctl optimizations inside
the amphora-haproxy network namespace when it's created.

Change-Id: I00981460c18784f268ee048662dfe0e42d4f42f3
Co-Authored-By: Dustin Lundqiust <dustin@null-ptr.net>
This commit is contained in:
Stephen Balukoff 2016-10-13 21:30:26 -07:00
parent 3ef947ad3a
commit 838e52f245
7 changed files with 54 additions and 7 deletions

View File

@ -158,6 +158,14 @@ class Plug(object):
netns = pyroute2.NetNS(consts.AMPHORA_NAMESPACE, flags=os.O_CREAT)
netns.close()
# Load sysctl in new namespace
sysctl = pyroute2.NSPopen(consts.AMPHORA_NAMESPACE,
[consts.SYSCTL_CMD, '--system'],
stdout=subprocess.PIPE)
sysctl.communicate()
sysctl.wait()
sysctl.release()
with pyroute2.IPRoute() as ipr:
# Move the interfaces into the namespace
idx = ipr.link_lookup(ifname=default_netns_interface)[0]
@ -355,4 +363,4 @@ class Plug(object):
for attr in link['attrs']:
if attr[0] == 'IFLA_ADDRESS' and attr[1] == mac_address:
return True
return False
return False

View File

@ -52,6 +52,8 @@ haproxy_start()
{
# Re-add the namespace
ip netns add {{ amphora_nsname }} || true
# Load the system sysctl into the new namespace
ip netns exec {{ amphora_nsname }} sysctl --system || true
# We need the plugged_interfaces file sorted to join the host interfaces
sort -k 1 /var/lib/octavia/plugged_interfaces > /var/lib/octavia/plugged_interfaces.sorted || true
# Assign the interfaces into the namespace with the appropriate name

View File

@ -33,6 +33,8 @@ pre-start script
[ -r $CONF_PATH ]
# Re-add the namespace
ip netns add {{ amphora_nsname }} || true
# Load the system sysctl into the new namespace
ip netns exec {{ amphora_nsname }} sysctl --system || true
# We need the plugged_interfaces file sorted to join with the host
# interfaces
sort -k 1 /var/lib/octavia/plugged_interfaces > /var/lib/octavia/plugged_interfaces.sorted || true

View File

@ -330,6 +330,7 @@ FLOW_DOC_TITLES = {'AmphoraFlows': 'Amphora Flows',
'L7RuleFlows': 'Layer 7 Rule Flows'}
NETNS_PRIMARY_INTERFACE = 'eth1'
SYSCTL_CMD = '/sbin/sysctl'
AMP_ACTION_START = 'start'
AMP_ACTION_STOP = 'stop'

View File

@ -807,6 +807,7 @@ class TestServerTestCase(base.TestCase):
['ip', 'netns', 'exec', consts.AMPHORA_NAMESPACE,
'ifup', consts.NETNS_PRIMARY_INTERFACE], stderr=-2)
@mock.patch('pyroute2.NSPopen')
@mock.patch('octavia.amphorae.backends.agent.api_server.'
'plug.Plug._netns_interface_exists')
@mock.patch('netifaces.interfaces')
@ -819,7 +820,8 @@ class TestServerTestCase(base.TestCase):
@mock.patch('os.makedirs')
def test_plug_VIP4(self, mock_makedirs, mock_copytree, mock_check_output,
mock_netns, mock_netns_create, mock_pyroute2,
mock_ifaddress, mock_interfaces, mock_int_exists):
mock_ifaddress, mock_interfaces, mock_int_exists,
mock_nspopen):
subnet_info = {
'subnet_cidr': '203.0.113.0/24',
@ -937,6 +939,11 @@ class TestServerTestCase(base.TestCase):
'ifup', '{netns_int}:0'.format(
netns_int=consts.NETNS_PRIMARY_INTERFACE)], stderr=-2)
# Verify sysctl was loaded
mock_nspopen.assert_called_once_with(
'amphora-haproxy', ['/sbin/sysctl', '--system'],
stdout=subprocess.PIPE)
# One Interface down, Happy Path IPv4
mock_interfaces.side_effect = [['blah']]
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
@ -1003,6 +1010,7 @@ class TestServerTestCase(base.TestCase):
'message': 'Error plugging VIP'},
json.loads(rv.data.decode('utf-8')))
@mock.patch('pyroute2.NSPopen')
@mock.patch('netifaces.interfaces')
@mock.patch('netifaces.ifaddresses')
@mock.patch('pyroute2.IPRoute')
@ -1013,7 +1021,7 @@ class TestServerTestCase(base.TestCase):
@mock.patch('os.makedirs')
def test_plug_vip6(self, mock_makedirs, mock_copytree, mock_check_output,
mock_netns, mock_netns_create, mock_pyroute2,
mock_ifaddress, mock_interfaces):
mock_ifaddress, mock_interfaces, mock_nspopen):
subnet_info = {
'subnet_cidr': '2001:db8::/32',
@ -1119,6 +1127,11 @@ class TestServerTestCase(base.TestCase):
'ifup', '{netns_int}:0'.format(
netns_int=consts.NETNS_PRIMARY_INTERFACE)], stderr=-2)
# Verify sysctl was loaded
mock_nspopen.assert_called_once_with(
'amphora-haproxy', ['/sbin/sysctl', '--system'],
stdout=subprocess.PIPE)
# One Interface down, Happy Path IPv6
mock_interfaces.side_effect = [['blah']]
mock_ifaddress.side_effect = [[netifaces.AF_LINK],

View File

@ -663,6 +663,7 @@ class ServerTestCase(base.TestCase):
['ip', 'netns', 'exec', consts.AMPHORA_NAMESPACE,
'ifup', consts.NETNS_PRIMARY_INTERFACE], stderr=-2)
@mock.patch('pyroute2.NSPopen')
@mock.patch('netifaces.interfaces')
@mock.patch('netifaces.ifaddresses')
@mock.patch('pyroute2.IPRoute')
@ -673,7 +674,7 @@ class ServerTestCase(base.TestCase):
@mock.patch('os.makedirs')
def test_plug_vip4(self, mock_makedirs, mock_copytree, mock_check_output,
mock_netns, mock_netns_create, mock_pyroute2,
mock_ifaddress, mock_interfaces):
mock_ifaddress, mock_interfaces, mock_nspopen):
subnet_info = {
'subnet_cidr': '203.0.113.0/24',
@ -779,6 +780,11 @@ class ServerTestCase(base.TestCase):
'ifup', '{netns_int}:0'.format(
netns_int=consts.NETNS_PRIMARY_INTERFACE)], stderr=-2)
# Verify sysctl was loaded
mock_nspopen.assert_called_once_with(
'amphora-haproxy', ['/sbin/sysctl', '--system'],
stdout=subprocess.PIPE)
# One Interface down, Happy Path IPv4
mock_interfaces.side_effect = [['blah']]
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
@ -845,6 +851,7 @@ class ServerTestCase(base.TestCase):
'message': 'Error plugging VIP'},
json.loads(rv.data.decode('utf-8')))
@mock.patch('pyroute2.NSPopen')
@mock.patch('netifaces.interfaces')
@mock.patch('netifaces.ifaddresses')
@mock.patch('pyroute2.IPRoute')
@ -855,7 +862,7 @@ class ServerTestCase(base.TestCase):
@mock.patch('os.makedirs')
def test_plug_vip6(self, mock_makedirs, mock_copytree, mock_check_output,
mock_netns, mock_netns_create, mock_pyroute2,
mock_ifaddress, mock_interfaces):
mock_ifaddress, mock_interfaces, mock_nspopen):
subnet_info = {
'subnet_cidr': '2001:db8::/32',
@ -959,6 +966,11 @@ class ServerTestCase(base.TestCase):
'ifup', '{netns_int}:0'.format(
netns_int=consts.NETNS_PRIMARY_INTERFACE)], stderr=-2)
# Verify sysctl was loaded
mock_nspopen.assert_called_once_with(
'amphora-haproxy', ['/sbin/sysctl', '--system'],
stdout=subprocess.PIPE)
# One Interface down, Happy Path IPv6
mock_interfaces.side_effect = [['blah']]
mock_ifaddress.side_effect = [[netifaces.AF_LINK],

View File

@ -13,6 +13,7 @@
# under the License.
import os
import subprocess
import mock
import netifaces
@ -51,6 +52,7 @@ class TestPlug(base.TestCase):
interface = self.test_plug._interface_by_mac(FAKE_MAC_ADDRESS.upper())
self.assertEqual(FAKE_INTERFACE, interface)
@mock.patch('pyroute2.NSPopen')
@mock.patch.object(plug, "flask")
@mock.patch('pyroute2.IPRoute')
@mock.patch('pyroute2.netns.create')
@ -60,7 +62,7 @@ class TestPlug(base.TestCase):
@mock.patch('os.makedirs')
def test_plug_vip_ipv4(self, mock_makedirs, mock_copytree,
mock_check_output, mock_netns, mock_netns_create,
mock_pyroute2, mock_flask):
mock_pyroute2, mock_flask, mock_nspopen):
m = mock.mock_open()
with mock.patch('os.open'), mock.patch.object(os, 'fdopen', m):
self.test_plug.plug_vip(
@ -74,7 +76,11 @@ class TestPlug(base.TestCase):
'details': 'VIP {vip} plugged on interface {interface}'.format(
vip=FAKE_IP_IPV4, interface='eth1')
})
mock_nspopen.assert_called_once_with(
'amphora-haproxy', ['/sbin/sysctl', '--system'],
stdout=subprocess.PIPE)
@mock.patch('pyroute2.NSPopen')
@mock.patch.object(plug, "flask")
@mock.patch('pyroute2.IPRoute')
@mock.patch('pyroute2.netns.create')
@ -84,7 +90,7 @@ class TestPlug(base.TestCase):
@mock.patch('os.makedirs')
def test_plug_vip_ipv6(self, mock_makedirs, mock_copytree,
mock_check_output, mock_netns, mock_netns_create,
mock_pyroute2, mock_flask):
mock_pyroute2, mock_flask, mock_nspopen):
m = mock.mock_open()
with mock.patch('os.open'), mock.patch.object(os, 'fdopen', m):
self.test_plug.plug_vip(
@ -98,6 +104,9 @@ class TestPlug(base.TestCase):
'details': 'VIP {vip} plugged on interface {interface}'.format(
vip=FAKE_IP_IPV6_EXPANDED, interface='eth1')
})
mock_nspopen.assert_called_once_with(
'amphora-haproxy', ['/sbin/sysctl', '--system'],
stdout=subprocess.PIPE)
@mock.patch.object(plug, "flask")
@mock.patch('pyroute2.IPRoute')