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:
parent
3ef947ad3a
commit
838e52f245
@ -158,6 +158,14 @@ class Plug(object):
|
|||||||
netns = pyroute2.NetNS(consts.AMPHORA_NAMESPACE, flags=os.O_CREAT)
|
netns = pyroute2.NetNS(consts.AMPHORA_NAMESPACE, flags=os.O_CREAT)
|
||||||
netns.close()
|
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:
|
with pyroute2.IPRoute() as ipr:
|
||||||
# Move the interfaces into the namespace
|
# Move the interfaces into the namespace
|
||||||
idx = ipr.link_lookup(ifname=default_netns_interface)[0]
|
idx = ipr.link_lookup(ifname=default_netns_interface)[0]
|
||||||
@ -355,4 +363,4 @@ class Plug(object):
|
|||||||
for attr in link['attrs']:
|
for attr in link['attrs']:
|
||||||
if attr[0] == 'IFLA_ADDRESS' and attr[1] == mac_address:
|
if attr[0] == 'IFLA_ADDRESS' and attr[1] == mac_address:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
@ -52,6 +52,8 @@ haproxy_start()
|
|||||||
{
|
{
|
||||||
# Re-add the namespace
|
# Re-add the namespace
|
||||||
ip netns add {{ amphora_nsname }} || true
|
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
|
# 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
|
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
|
# Assign the interfaces into the namespace with the appropriate name
|
||||||
|
@ -33,6 +33,8 @@ pre-start script
|
|||||||
[ -r $CONF_PATH ]
|
[ -r $CONF_PATH ]
|
||||||
# Re-add the namespace
|
# Re-add the namespace
|
||||||
ip netns add {{ amphora_nsname }} || true
|
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
|
# We need the plugged_interfaces file sorted to join with the host
|
||||||
# interfaces
|
# interfaces
|
||||||
sort -k 1 /var/lib/octavia/plugged_interfaces > /var/lib/octavia/plugged_interfaces.sorted || true
|
sort -k 1 /var/lib/octavia/plugged_interfaces > /var/lib/octavia/plugged_interfaces.sorted || true
|
||||||
|
@ -330,6 +330,7 @@ FLOW_DOC_TITLES = {'AmphoraFlows': 'Amphora Flows',
|
|||||||
'L7RuleFlows': 'Layer 7 Rule Flows'}
|
'L7RuleFlows': 'Layer 7 Rule Flows'}
|
||||||
|
|
||||||
NETNS_PRIMARY_INTERFACE = 'eth1'
|
NETNS_PRIMARY_INTERFACE = 'eth1'
|
||||||
|
SYSCTL_CMD = '/sbin/sysctl'
|
||||||
|
|
||||||
AMP_ACTION_START = 'start'
|
AMP_ACTION_START = 'start'
|
||||||
AMP_ACTION_STOP = 'stop'
|
AMP_ACTION_STOP = 'stop'
|
||||||
|
@ -807,6 +807,7 @@ class TestServerTestCase(base.TestCase):
|
|||||||
['ip', 'netns', 'exec', consts.AMPHORA_NAMESPACE,
|
['ip', 'netns', 'exec', consts.AMPHORA_NAMESPACE,
|
||||||
'ifup', consts.NETNS_PRIMARY_INTERFACE], stderr=-2)
|
'ifup', consts.NETNS_PRIMARY_INTERFACE], stderr=-2)
|
||||||
|
|
||||||
|
@mock.patch('pyroute2.NSPopen')
|
||||||
@mock.patch('octavia.amphorae.backends.agent.api_server.'
|
@mock.patch('octavia.amphorae.backends.agent.api_server.'
|
||||||
'plug.Plug._netns_interface_exists')
|
'plug.Plug._netns_interface_exists')
|
||||||
@mock.patch('netifaces.interfaces')
|
@mock.patch('netifaces.interfaces')
|
||||||
@ -819,7 +820,8 @@ class TestServerTestCase(base.TestCase):
|
|||||||
@mock.patch('os.makedirs')
|
@mock.patch('os.makedirs')
|
||||||
def test_plug_VIP4(self, mock_makedirs, mock_copytree, mock_check_output,
|
def test_plug_VIP4(self, mock_makedirs, mock_copytree, mock_check_output,
|
||||||
mock_netns, mock_netns_create, mock_pyroute2,
|
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_info = {
|
||||||
'subnet_cidr': '203.0.113.0/24',
|
'subnet_cidr': '203.0.113.0/24',
|
||||||
@ -937,6 +939,11 @@ class TestServerTestCase(base.TestCase):
|
|||||||
'ifup', '{netns_int}:0'.format(
|
'ifup', '{netns_int}:0'.format(
|
||||||
netns_int=consts.NETNS_PRIMARY_INTERFACE)], stderr=-2)
|
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
|
# One Interface down, Happy Path IPv4
|
||||||
mock_interfaces.side_effect = [['blah']]
|
mock_interfaces.side_effect = [['blah']]
|
||||||
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
|
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
|
||||||
@ -1003,6 +1010,7 @@ class TestServerTestCase(base.TestCase):
|
|||||||
'message': 'Error plugging VIP'},
|
'message': 'Error plugging VIP'},
|
||||||
json.loads(rv.data.decode('utf-8')))
|
json.loads(rv.data.decode('utf-8')))
|
||||||
|
|
||||||
|
@mock.patch('pyroute2.NSPopen')
|
||||||
@mock.patch('netifaces.interfaces')
|
@mock.patch('netifaces.interfaces')
|
||||||
@mock.patch('netifaces.ifaddresses')
|
@mock.patch('netifaces.ifaddresses')
|
||||||
@mock.patch('pyroute2.IPRoute')
|
@mock.patch('pyroute2.IPRoute')
|
||||||
@ -1013,7 +1021,7 @@ class TestServerTestCase(base.TestCase):
|
|||||||
@mock.patch('os.makedirs')
|
@mock.patch('os.makedirs')
|
||||||
def test_plug_vip6(self, mock_makedirs, mock_copytree, mock_check_output,
|
def test_plug_vip6(self, mock_makedirs, mock_copytree, mock_check_output,
|
||||||
mock_netns, mock_netns_create, mock_pyroute2,
|
mock_netns, mock_netns_create, mock_pyroute2,
|
||||||
mock_ifaddress, mock_interfaces):
|
mock_ifaddress, mock_interfaces, mock_nspopen):
|
||||||
|
|
||||||
subnet_info = {
|
subnet_info = {
|
||||||
'subnet_cidr': '2001:db8::/32',
|
'subnet_cidr': '2001:db8::/32',
|
||||||
@ -1119,6 +1127,11 @@ class TestServerTestCase(base.TestCase):
|
|||||||
'ifup', '{netns_int}:0'.format(
|
'ifup', '{netns_int}:0'.format(
|
||||||
netns_int=consts.NETNS_PRIMARY_INTERFACE)], stderr=-2)
|
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
|
# One Interface down, Happy Path IPv6
|
||||||
mock_interfaces.side_effect = [['blah']]
|
mock_interfaces.side_effect = [['blah']]
|
||||||
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
|
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
|
||||||
|
@ -663,6 +663,7 @@ class ServerTestCase(base.TestCase):
|
|||||||
['ip', 'netns', 'exec', consts.AMPHORA_NAMESPACE,
|
['ip', 'netns', 'exec', consts.AMPHORA_NAMESPACE,
|
||||||
'ifup', consts.NETNS_PRIMARY_INTERFACE], stderr=-2)
|
'ifup', consts.NETNS_PRIMARY_INTERFACE], stderr=-2)
|
||||||
|
|
||||||
|
@mock.patch('pyroute2.NSPopen')
|
||||||
@mock.patch('netifaces.interfaces')
|
@mock.patch('netifaces.interfaces')
|
||||||
@mock.patch('netifaces.ifaddresses')
|
@mock.patch('netifaces.ifaddresses')
|
||||||
@mock.patch('pyroute2.IPRoute')
|
@mock.patch('pyroute2.IPRoute')
|
||||||
@ -673,7 +674,7 @@ class ServerTestCase(base.TestCase):
|
|||||||
@mock.patch('os.makedirs')
|
@mock.patch('os.makedirs')
|
||||||
def test_plug_vip4(self, mock_makedirs, mock_copytree, mock_check_output,
|
def test_plug_vip4(self, mock_makedirs, mock_copytree, mock_check_output,
|
||||||
mock_netns, mock_netns_create, mock_pyroute2,
|
mock_netns, mock_netns_create, mock_pyroute2,
|
||||||
mock_ifaddress, mock_interfaces):
|
mock_ifaddress, mock_interfaces, mock_nspopen):
|
||||||
|
|
||||||
subnet_info = {
|
subnet_info = {
|
||||||
'subnet_cidr': '203.0.113.0/24',
|
'subnet_cidr': '203.0.113.0/24',
|
||||||
@ -779,6 +780,11 @@ class ServerTestCase(base.TestCase):
|
|||||||
'ifup', '{netns_int}:0'.format(
|
'ifup', '{netns_int}:0'.format(
|
||||||
netns_int=consts.NETNS_PRIMARY_INTERFACE)], stderr=-2)
|
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
|
# One Interface down, Happy Path IPv4
|
||||||
mock_interfaces.side_effect = [['blah']]
|
mock_interfaces.side_effect = [['blah']]
|
||||||
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
|
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
|
||||||
@ -845,6 +851,7 @@ class ServerTestCase(base.TestCase):
|
|||||||
'message': 'Error plugging VIP'},
|
'message': 'Error plugging VIP'},
|
||||||
json.loads(rv.data.decode('utf-8')))
|
json.loads(rv.data.decode('utf-8')))
|
||||||
|
|
||||||
|
@mock.patch('pyroute2.NSPopen')
|
||||||
@mock.patch('netifaces.interfaces')
|
@mock.patch('netifaces.interfaces')
|
||||||
@mock.patch('netifaces.ifaddresses')
|
@mock.patch('netifaces.ifaddresses')
|
||||||
@mock.patch('pyroute2.IPRoute')
|
@mock.patch('pyroute2.IPRoute')
|
||||||
@ -855,7 +862,7 @@ class ServerTestCase(base.TestCase):
|
|||||||
@mock.patch('os.makedirs')
|
@mock.patch('os.makedirs')
|
||||||
def test_plug_vip6(self, mock_makedirs, mock_copytree, mock_check_output,
|
def test_plug_vip6(self, mock_makedirs, mock_copytree, mock_check_output,
|
||||||
mock_netns, mock_netns_create, mock_pyroute2,
|
mock_netns, mock_netns_create, mock_pyroute2,
|
||||||
mock_ifaddress, mock_interfaces):
|
mock_ifaddress, mock_interfaces, mock_nspopen):
|
||||||
|
|
||||||
subnet_info = {
|
subnet_info = {
|
||||||
'subnet_cidr': '2001:db8::/32',
|
'subnet_cidr': '2001:db8::/32',
|
||||||
@ -959,6 +966,11 @@ class ServerTestCase(base.TestCase):
|
|||||||
'ifup', '{netns_int}:0'.format(
|
'ifup', '{netns_int}:0'.format(
|
||||||
netns_int=consts.NETNS_PRIMARY_INTERFACE)], stderr=-2)
|
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
|
# One Interface down, Happy Path IPv6
|
||||||
mock_interfaces.side_effect = [['blah']]
|
mock_interfaces.side_effect = [['blah']]
|
||||||
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
|
mock_ifaddress.side_effect = [[netifaces.AF_LINK],
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
import netifaces
|
import netifaces
|
||||||
@ -51,6 +52,7 @@ class TestPlug(base.TestCase):
|
|||||||
interface = self.test_plug._interface_by_mac(FAKE_MAC_ADDRESS.upper())
|
interface = self.test_plug._interface_by_mac(FAKE_MAC_ADDRESS.upper())
|
||||||
self.assertEqual(FAKE_INTERFACE, interface)
|
self.assertEqual(FAKE_INTERFACE, interface)
|
||||||
|
|
||||||
|
@mock.patch('pyroute2.NSPopen')
|
||||||
@mock.patch.object(plug, "flask")
|
@mock.patch.object(plug, "flask")
|
||||||
@mock.patch('pyroute2.IPRoute')
|
@mock.patch('pyroute2.IPRoute')
|
||||||
@mock.patch('pyroute2.netns.create')
|
@mock.patch('pyroute2.netns.create')
|
||||||
@ -60,7 +62,7 @@ class TestPlug(base.TestCase):
|
|||||||
@mock.patch('os.makedirs')
|
@mock.patch('os.makedirs')
|
||||||
def test_plug_vip_ipv4(self, mock_makedirs, mock_copytree,
|
def test_plug_vip_ipv4(self, mock_makedirs, mock_copytree,
|
||||||
mock_check_output, mock_netns, mock_netns_create,
|
mock_check_output, mock_netns, mock_netns_create,
|
||||||
mock_pyroute2, mock_flask):
|
mock_pyroute2, mock_flask, mock_nspopen):
|
||||||
m = mock.mock_open()
|
m = mock.mock_open()
|
||||||
with mock.patch('os.open'), mock.patch.object(os, 'fdopen', m):
|
with mock.patch('os.open'), mock.patch.object(os, 'fdopen', m):
|
||||||
self.test_plug.plug_vip(
|
self.test_plug.plug_vip(
|
||||||
@ -74,7 +76,11 @@ class TestPlug(base.TestCase):
|
|||||||
'details': 'VIP {vip} plugged on interface {interface}'.format(
|
'details': 'VIP {vip} plugged on interface {interface}'.format(
|
||||||
vip=FAKE_IP_IPV4, interface='eth1')
|
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.object(plug, "flask")
|
||||||
@mock.patch('pyroute2.IPRoute')
|
@mock.patch('pyroute2.IPRoute')
|
||||||
@mock.patch('pyroute2.netns.create')
|
@mock.patch('pyroute2.netns.create')
|
||||||
@ -84,7 +90,7 @@ class TestPlug(base.TestCase):
|
|||||||
@mock.patch('os.makedirs')
|
@mock.patch('os.makedirs')
|
||||||
def test_plug_vip_ipv6(self, mock_makedirs, mock_copytree,
|
def test_plug_vip_ipv6(self, mock_makedirs, mock_copytree,
|
||||||
mock_check_output, mock_netns, mock_netns_create,
|
mock_check_output, mock_netns, mock_netns_create,
|
||||||
mock_pyroute2, mock_flask):
|
mock_pyroute2, mock_flask, mock_nspopen):
|
||||||
m = mock.mock_open()
|
m = mock.mock_open()
|
||||||
with mock.patch('os.open'), mock.patch.object(os, 'fdopen', m):
|
with mock.patch('os.open'), mock.patch.object(os, 'fdopen', m):
|
||||||
self.test_plug.plug_vip(
|
self.test_plug.plug_vip(
|
||||||
@ -98,6 +104,9 @@ class TestPlug(base.TestCase):
|
|||||||
'details': 'VIP {vip} plugged on interface {interface}'.format(
|
'details': 'VIP {vip} plugged on interface {interface}'.format(
|
||||||
vip=FAKE_IP_IPV6_EXPANDED, interface='eth1')
|
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.object(plug, "flask")
|
||||||
@mock.patch('pyroute2.IPRoute')
|
@mock.patch('pyroute2.IPRoute')
|
||||||
|
Loading…
Reference in New Issue
Block a user