Skip to content

Commit 0b4ca01

Browse files
mikalstillstephenfin
authored andcommitted
Privsepify ipv4 forwarding enablement.
Follows the usual pattern, but with some nice cleanups to unit test code as we get closer to the end of this journey. Change-Id: Ie10b2f171842d19e55fbad3d751660e11bfce2cb
1 parent c743f66 commit 0b4ca01

File tree

7 files changed

+101
-53
lines changed

7 files changed

+101
-53
lines changed

nova/network/linux_net.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -736,19 +736,12 @@ def floating_forward_rules(floating_ip, fixed_ip, device):
736736
return rules
737737

738738

739-
def _enable_ipv4_forwarding():
740-
sysctl_key = 'net.ipv4.ip_forward'
741-
stdout, stderr = _execute('sysctl', '-n', sysctl_key)
742-
if stdout.strip() is not '1':
743-
_execute('sysctl', '-w', '%s=1' % sysctl_key, run_as_root=True)
744-
745-
746739
@utils.synchronized('lock_gateway', external=True)
747740
def initialize_gateway_device(dev, network_ref):
748741
if not network_ref:
749742
return
750743

751-
_enable_ipv4_forwarding()
744+
nova.privsep.linux_net.enable_ipv4_forwarding()
752745

753746
# NOTE(vish): The ip for dnsmasq has to be the first address on the
754747
# bridge for it to respond to requests properly

nova/privsep/linux_net.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,18 @@ def clean_conntrack(fixed_ip):
232232
check_exit_code=[0, 1])
233233
except processutils.ProcessExecutionError:
234234
LOG.exception('Error deleting conntrack entries for %s', fixed_ip)
235+
236+
237+
def enable_ipv4_forwarding():
238+
if not ipv4_forwarding_check():
239+
_enable_ipv4_forwarding_inner()
240+
241+
242+
def ipv4_forwarding_check():
243+
with open('/proc/sys/net/ipv4/ip_forward', 'r') as f:
244+
return f.readline().strip() == '1'
245+
246+
247+
@nova.privsep.sys_admin_pctxt.entrypoint
248+
def _enable_ipv4_forwarding_inner():
249+
processutils.execute('sysctl', '-w', 'net.ipv4.ip_forward=1')

nova/tests/functional/api_sample_tests/api_sample_base.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ def setUp(self):
126126
# NOTE(mikal): this is used to stub away privsep helpers
127127
def fake_noop(*args, **kwargs):
128128
return '', ''
129+
130+
def fake_true(*args, **kwargs):
131+
return True
132+
129133
self.stub_out('nova.privsep.linux_net.add_bridge', fake_noop)
130134
self.stub_out('nova.privsep.linux_net.set_device_mtu', fake_noop)
131135
self.stub_out('nova.privsep.linux_net.set_device_enabled', fake_noop)
@@ -135,6 +139,10 @@ def fake_noop(*args, **kwargs):
135139
self.stub_out('nova.privsep.linux_net.change_ip', fake_noop)
136140
self.stub_out('nova.privsep.linux_net.address_command_deprecated',
137141
fake_noop)
142+
self.stub_out('nova.privsep.linux_net.ipv4_forwarding_check',
143+
fake_true)
144+
self.stub_out('nova.privsep.linux_net._enable_ipv4_forwarding_inner',
145+
fake_noop)
138146

139147
if self.availability_zones:
140148
self.useFixture(

nova/tests/unit/network/test_linux_net.py

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -875,31 +875,23 @@ def fake_remove(bridge, gateway):
875875
]
876876
self.assertEqual(expected, executes)
877877

878-
@mock.patch.object(utils, 'execute')
879878
@mock.patch('nova.privsep.linux_net.routes_show')
880879
@mock.patch('nova.privsep.linux_net.route_delete')
881880
@mock.patch('nova.privsep.linux_net.route_add_deprecated')
882881
@mock.patch('nova.privsep.linux_net.lookup_ip')
883882
@mock.patch('nova.privsep.linux_net.change_ip')
884883
@mock.patch('nova.privsep.linux_net.address_command_deprecated')
885-
def _test_initialize_gateway(self, existing, expected,
884+
def _test_initialize_gateway(self, existing,
886885
mock_address_command, mock_change_ip,
887886
mock_lookup_ip, mock_route_add,
888887
mock_route_delete, mock_routes,
889-
mock_execute, routes='',
888+
routes='',
890889
routes_show_called=True, deleted_routes=None,
891890
added_routes=None, changed_interfaces=None,
892891
address_commands=None):
893892
self.flags(fake_network=False)
894893
mock_lookup_ip.return_value = (existing, '')
895-
executes = []
896-
897-
def fake_execute(*args, **kwargs):
898-
executes.append(args)
899-
if args[0] == 'sysctl':
900-
return '1\n', ''
901894

902-
mock_execute.side_effect = fake_execute
903895
mock_routes.return_value = (routes, '')
904896
mock_lookup_ip.return_value = (existing, '')
905897

@@ -908,8 +900,6 @@ def fake_execute(*args, **kwargs):
908900
'broadcast': '192.168.1.255',
909901
'cidr_v6': '2001:db8::/64'}
910902
self.driver.initialize_gateway_device('eth0', network)
911-
self.assertEqual(expected, executes)
912-
self.assertTrue(mock_execute.called)
913903
self.assertTrue(mock_lookup_ip.called)
914904

915905
if routes_show_called:
@@ -923,18 +913,17 @@ def fake_execute(*args, **kwargs):
923913
if address_commands:
924914
mock_address_command.assert_has_calls(address_commands)
925915

926-
def test_initialize_gateway_moves_wrong_ip(self):
916+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
917+
return_value=True)
918+
def test_initialize_gateway_moves_wrong_ip(self, mock_forwarding_check):
927919
existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
928920
" mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
929921
" link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
930922
" inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
931923
" inet6 dead::beef:dead:beef:dead/64 scope link\n"
932924
" valid_lft forever preferred_lft forever\n")
933-
expected = [
934-
('sysctl', '-n', 'net.ipv4.ip_forward'),
935-
]
936925
self._test_initialize_gateway(
937-
existing, expected,
926+
existing,
938927
changed_interfaces=[mock.call('eth0', '2001:db8::/64')],
939928
address_commands=[
940929
mock.call('eth0', 'del', ['192.168.0.1/24', 'brd',
@@ -947,19 +936,19 @@ def test_initialize_gateway_moves_wrong_ip(self):
947936
'scope', 'global'])]
948937
)
949938

950-
def test_initialize_gateway_ip_with_dynamic_flag(self):
939+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
940+
return_value=True)
941+
def test_initialize_gateway_ip_with_dynamic_flag(self,
942+
mock_forwarding_check):
951943
existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
952944
" mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
953945
" link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
954946
" inet 192.168.0.1/24 brd 192.168.0.255 scope global "
955947
"dynamic eth0\n"
956948
" inet6 dead::beef:dead:beef:dead/64 scope link\n"
957949
" valid_lft forever preferred_lft forever\n")
958-
expected = [
959-
('sysctl', '-n', 'net.ipv4.ip_forward'),
960-
]
961950
self._test_initialize_gateway(
962-
existing, expected,
951+
existing,
963952
changed_interfaces=[mock.call('eth0', '2001:db8::/64')],
964953
address_commands=[
965954
mock.call('eth0', 'del',
@@ -972,7 +961,9 @@ def test_initialize_gateway_ip_with_dynamic_flag(self):
972961
'scope', 'global'])]
973962
)
974963

975-
def test_initialize_gateway_resets_route(self):
964+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
965+
return_value=True)
966+
def test_initialize_gateway_resets_route(self, mock_forwarding_check):
976967
routes = ("default via 192.168.0.1 dev eth0\n"
977968
"192.168.100.0/24 via 192.168.0.254 dev eth0 proto static\n")
978969
existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
@@ -981,11 +972,8 @@ def test_initialize_gateway_resets_route(self):
981972
" inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
982973
" inet6 dead::beef:dead:beef:dead/64 scope link\n"
983974
" valid_lft forever preferred_lft forever\n")
984-
expected = [
985-
('sysctl', '-n', 'net.ipv4.ip_forward'),
986-
]
987975
self._test_initialize_gateway(
988-
existing, expected, routes=routes,
976+
existing, routes=routes,
989977
deleted_routes=[mock.call('eth0', 'default'),
990978
mock.call('eth0', '192.168.100.0/24')],
991979
added_routes=[mock.call(['default', 'via', '192.168.0.1',
@@ -1005,33 +993,31 @@ def test_initialize_gateway_resets_route(self):
1005993
'scope', 'global'])]
1006994
)
1007995

1008-
def test_initialize_gateway_no_move_right_ip(self):
996+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
997+
return_value=True)
998+
def test_initialize_gateway_no_move_right_ip(self, mock_forwarding_check):
1009999
existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
10101000
" mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
10111001
" link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
10121002
" inet 192.168.1.1/24 brd 192.168.1.255 scope global eth0\n"
10131003
" inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
10141004
" inet6 dead::beef:dead:beef:dead/64 scope link\n"
10151005
" valid_lft forever preferred_lft forever\n")
1016-
expected = [
1017-
('sysctl', '-n', 'net.ipv4.ip_forward'),
1018-
]
10191006
self._test_initialize_gateway(
1020-
existing, expected,
1021-
routes_show_called=False,
1007+
existing, routes_show_called=False,
10221008
changed_interfaces=[mock.call('eth0', '2001:db8::/64')])
1009+
mock_forwarding_check.assert_called()
10231010

1024-
def test_initialize_gateway_add_if_blank(self):
1011+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
1012+
return_value=True)
1013+
def test_initialize_gateway_add_if_blank(self, mock_forwarding_check):
10251014
existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
10261015
" mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
10271016
" link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
10281017
" inet6 dead::beef:dead:beef:dead/64 scope link\n"
10291018
" valid_lft forever preferred_lft forever\n")
1030-
expected = [
1031-
('sysctl', '-n', 'net.ipv4.ip_forward'),
1032-
]
10331019
self._test_initialize_gateway(
1034-
existing, expected,
1020+
existing,
10351021
changed_interfaces=[mock.call('eth0', '2001:db8::/64')],
10361022
address_commands=[
10371023
mock.call('eth0', 'add',

nova/tests/unit/network/test_manager.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,12 @@ def test_quota_driver_type(self):
942942
@mock.patch('nova.privsep.linux_net.lookup_ip', return_value=('', ''))
943943
@mock.patch('nova.privsep.linux_net.change_ip')
944944
@mock.patch('nova.privsep.linux_net.address_command_deprecated')
945-
def test_vpn_allocate_fixed_ip(self, mock_address_command,
945+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
946+
return_value=False)
947+
@mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner')
948+
def test_vpn_allocate_fixed_ip(self, mock_forwarding_enable,
949+
mock_forwarding_check,
950+
mock_address_command,
946951
mock_change_ip, mock_lookup_ip,
947952
mock_routes_show, mock_enabled,
948953
mock_add_bridge):
@@ -984,8 +989,13 @@ def test_vpn_allocate_fixed_ip(self, mock_address_command,
984989
@mock.patch('nova.privsep.linux_net.lookup_ip', return_value=('', ''))
985990
@mock.patch('nova.privsep.linux_net.change_ip')
986991
@mock.patch('nova.privsep.linux_net.address_command_deprecated')
987-
def test_allocate_fixed_ip(self, mock_address_command, mock_change_ip,
988-
mock_lookup_ip, mock_routes_show, mock_enabled,
992+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
993+
return_value=False)
994+
@mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner')
995+
def test_allocate_fixed_ip(self, mock_forwarding_enable,
996+
mock_forwarding_check, mock_address_command,
997+
mock_change_ip, mock_lookup_ip,
998+
mock_routes_show, mock_enabled,
989999
mock_add_bridge):
9901000
self.stubs.Set(self.network,
9911001
'_do_trigger_security_group_members_refresh_for_instance',
@@ -1710,8 +1720,12 @@ def fake8(*args, **kwargs):
17101720
@mock.patch('nova.privsep.linux_net.lookup_ip', return_value=('', ''))
17111721
@mock.patch('nova.privsep.linux_net.change_ip')
17121722
@mock.patch('nova.privsep.linux_net.address_command_deprecated')
1723+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
1724+
return_value=False)
1725+
@mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner')
17131726
def test_add_fixed_ip_instance_without_vpn_requested_networks(
1714-
self, mock_address_command, mock_change_ip, mock_lookup_ip,
1727+
self, mock_forwarding_enable, mock_forwarding_check,
1728+
mock_address_command, mock_change_ip, mock_lookup_ip,
17151729
mock_routes_show, mock_enabled, mock_add_bridge):
17161730
self.stubs.Set(self.network,
17171731
'_do_trigger_security_group_members_refresh_for_instance',
@@ -2870,7 +2884,12 @@ def setUp(self):
28702884
@mock.patch('nova.privsep.linux_net.change_ip')
28712885
@mock.patch('nova.privsep.linux_net.clean_conntrack')
28722886
@mock.patch('nova.privsep.linux_net.address_command_deprecated')
2873-
def test_allocate_for_instance(self, mock_clean_conntrack,
2887+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
2888+
return_value=False)
2889+
@mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner')
2890+
def test_allocate_for_instance(self, mock_forwarding_enable,
2891+
mock_forwarding_check,
2892+
mock_clean_conntrack,
28742893
mock_address_command,
28752894
mock_change_ip, mock_lookup_ip,
28762895
mock_routes_show, mock_unbind, mock_bind,
@@ -2947,7 +2966,12 @@ def test_allocate_for_instance_illegal_network(self):
29472966
@mock.patch('nova.privsep.linux_net.lookup_ip', return_value=('', ''))
29482967
@mock.patch('nova.privsep.linux_net.change_ip')
29492968
@mock.patch('nova.privsep.linux_net.address_command_deprecated')
2950-
def test_allocate_for_instance_with_mac(self, mock_address_command,
2969+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
2970+
return_value=False)
2971+
@mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner')
2972+
def test_allocate_for_instance_with_mac(self, mock_forwarding_enable,
2973+
mock_forwarding_check,
2974+
mock_address_command,
29512975
mock_change_ip,
29522976
mock_lookup_ip,
29532977
mock_routes_show,

nova/tests/unit/privsep/test_linux_net.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,20 @@ def test_create_tap_dev_multiqueue_tunctl_raises(self, mock_execute):
115115
self.assertRaises(processutils.ProcessExecutionError,
116116
nova.privsep.linux_net.create_tap_dev,
117117
'tap42', multiqueue=True)
118+
119+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
120+
return_value=False)
121+
@mock.patch('oslo_concurrency.processutils.execute')
122+
def test_enable_ipv4_forwarding_required(self, mock_execute, mock_check):
123+
nova.privsep.linux_net.enable_ipv4_forwarding()
124+
mock_check.assert_called_once()
125+
mock_execute.assert_called_once_with(
126+
'sysctl', '-w', 'net.ipv4.ip_forward=1')
127+
128+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
129+
return_value=True)
130+
@mock.patch('oslo_concurrency.processutils.execute')
131+
def test_enable_ipv4_forwarding_redundant(self, mock_execute, mock_check):
132+
nova.privsep.linux_net.enable_ipv4_forwarding()
133+
mock_check.assert_called_once()
134+
mock_execute.assert_not_called()

nova/tests/unit/virt/xenapi/test_xenapi.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,12 @@ def test_spawn_injects_auto_disk_config_to_xenstore(
11411141
@mock.patch('nova.privsep.linux_net.set_device_macaddr')
11421142
@mock.patch('nova.privsep.linux_net.change_ip')
11431143
@mock.patch('nova.privsep.linux_net.address_command_deprecated')
1144-
def test_spawn_vlanmanager(self, mock_address_command_deprecated,
1144+
@mock.patch('nova.privsep.linux_net.ipv4_forwarding_check',
1145+
return_value=False)
1146+
@mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner')
1147+
def test_spawn_vlanmanager(self, mock_forwarding_enable,
1148+
mock_forwarding_check,
1149+
mock_address_command_horrid,
11451150
mock_change_ip, mock_set_macaddr,
11461151
mock_set_enabled, mock_set_mtu, mock_add_bridge,
11471152
mock_create_vifs):

0 commit comments

Comments
 (0)