summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorcreatiwit <shrin.krishnan@gmail.com>2019-07-12 17:00:11 -0700
committerLiam Hopkins <liamh@google.com>2019-07-12 17:00:11 -0700
commite6eab0c12df9192208233b31d8e2ac7e79cba44c (patch)
treee829053eddb8af77513c7e780c1a72c1015ff52f /packages
parentf8d3beb109f692a04ae61de314654624309e80ed (diff)
downloadgoogle-compute-image-packages-e6eab0c12df9192208233b31d8e2ac7e79cba44c.tar.gz
Support for Google Private Access over IPv6 (#790)
* Enable IPv6 on interfaces based on metadata key. * Support for FreeBSD and SLES images is still needed. * Support for multi-NIC is still needed. * NOTE: `-6` argument to dhclient silently changes pid-file to `/run/dhclient6.pid`
Diffstat (limited to 'packages')
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/utils_test.py22
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/utils.py10
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/tests/utils_test.py22
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py10
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/tests/utils_test.py24
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py10
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/tests/utils_test.py22
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py10
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py46
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/distro_lib/tests/helpers_test.py112
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py2
-rwxr-xr-xpackages/python-google-compute-engine/google_compute_engine/networking/network_setup/network_setup.py28
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/networking/network_setup/tests/network_setup_test.py89
-rw-r--r--packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py27
14 files changed, 383 insertions, 51 deletions
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/utils_test.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/utils_test.py
index f714ba8..7f92795 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/utils_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/tests/utils_test.py
@@ -27,12 +27,28 @@ class UtilsTest(unittest.TestCase):
self.mock_setup = mock.create_autospec(utils.Utils)
@mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
- def testEnableIpv6(self, mock_call):
+ @mock.patch('google_compute_engine.distro_lib.helpers.CallEnableRouteAdvertisements')
+ def testEnableIpv6(self, mock_call_enable_ra, mock_call_dhclient):
mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
+ mocks.attach_mock(mock_call_dhclient, 'dhclient')
+ mocks.attach_mock(mock_call_enable_ra, 'enable_ra')
utils.Utils.EnableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
- expected_calls = [mock.call.call(['A', 'B'], mock.ANY)]
+ expected_calls = [
+ mock.call.enable_ra(['A', 'B'], mock.ANY),
+ mock.call.dhclient(['A', 'B'], mock.ANY),
+ ]
+ self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
+ def testDisableIpv6(self, mock_call_dhclient):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call_dhclient, 'dhclient')
+
+ utils.Utils.DisableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
+ expected_calls = [
+ mock.call.dhclient(['A', 'B'], mock.ANY, None, release_lease=True),
+ ]
self.assertEqual(mocks.mock_calls, expected_calls)
@mock.patch('google_compute_engine.distro_lib.helpers.CallDhclient')
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/utils.py
index f58e09d..7872d1b 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_8/utils.py
@@ -31,8 +31,18 @@ class Utils(utils.Utils):
logger: logger object, used to write to SysLog and serial port.
dhclient_script: string, the path to a dhclient script used by dhclient.
"""
+ helpers.CallEnableRouteAdvertisements(interfaces, logger)
helpers.CallDhclientIpv6(interfaces, logger)
+ def DisableIpv6(self, interfaces, logger):
+ """Disable Ipv6 by giving up the DHCP lease using dhclient.
+
+ Args:
+ interface: string, the output device names for enabling IPv6.
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallDhclientIpv6(interfaces, logger, None, release_lease=True)
+
def EnableNetworkInterfaces(self, interfaces, logger, dhclient_script=None):
"""Enable the list of network interfaces.
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/tests/utils_test.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/tests/utils_test.py
index fbb9a8e..4840753 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/tests/utils_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/tests/utils_test.py
@@ -27,12 +27,28 @@ class UtilsTest(unittest.TestCase):
self.mock_setup = mock.create_autospec(utils.Utils)
@mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
- def testEnableIpv6(self, mock_call):
+ @mock.patch('google_compute_engine.distro_lib.helpers.CallEnableRouteAdvertisements')
+ def testEnableIpv6(self, mock_call_enable_ra, mock_call_dhclient):
mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
+ mocks.attach_mock(mock_call_dhclient, 'dhclient')
+ mocks.attach_mock(mock_call_enable_ra, 'enable_ra')
utils.Utils.EnableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
- expected_calls = [mock.call.call(['A', 'B'], mock.ANY)]
+ expected_calls = [
+ mock.call.enable_ra(['A', 'B'], mock.ANY),
+ mock.call.dhclient(['A', 'B'], mock.ANY),
+ ]
+ self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
+ def testDisableIpv6(self, mock_call_dhclient):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call_dhclient, 'dhclient')
+
+ utils.Utils.DisableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
+ expected_calls = [
+ mock.call.dhclient(['A', 'B'], mock.ANY, None, release_lease=True),
+ ]
self.assertEqual(mocks.mock_calls, expected_calls)
@mock.patch('google_compute_engine.distro_lib.helpers.CallDhclient')
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py
index 11a5cbd..9255214 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/debian_9/utils.py
@@ -31,8 +31,18 @@ class Utils(utils.Utils):
logger: logger object, used to write to SysLog and serial port.
dhclient_script: string, the path to a dhclient script used by dhclient.
"""
+ helpers.CallEnableRouteAdvertisements(interfaces, logger)
helpers.CallDhclientIpv6(interfaces, logger)
+ def DisableIpv6(self, interfaces, logger):
+ """Disable Ipv6 by giving up the DHCP lease using dhclient.
+
+ Args:
+ interface: string, the output device names for enabling IPv6.
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallDhclientIpv6(interfaces, logger, None, release_lease=True)
+
def EnableNetworkInterfaces(self, interfaces, logger, dhclient_script=None):
"""Enable the list of network interfaces.
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/tests/utils_test.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/tests/utils_test.py
index f47f5c7..1dcbc60 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/tests/utils_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/tests/utils_test.py
@@ -30,15 +30,27 @@ class UtilsTest(unittest.TestCase):
pass
@mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
- def testEnableIpv6(self, mock_call):
+ @mock.patch('google_compute_engine.distro_lib.helpers.CallEnableRouteAdvertisements')
+ def testEnableIpv6(self, mock_call_enable_ra, mock_call_dhclient):
mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
+ mocks.attach_mock(mock_call_dhclient, 'dhclient')
+ mocks.attach_mock(mock_call_enable_ra, 'enable_ra')
- utils.Utils.EnableIpv6(
- self.mock_setup, ['A', 'B'], self.mock_logger,
- dhclient_script='test_script')
+ utils.Utils.EnableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
expected_calls = [
- mock.call.call(['A', 'B'], mock.ANY, dhclient_script='test_script'),
+ mock.call.enable_ra(['A', 'B'], mock.ANY),
+ mock.call.dhclient(['A', 'B'], mock.ANY, dhclient_script=None),
+ ]
+ self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
+ def testDisableIpv6(self, mock_call_dhclient):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call_dhclient, 'dhclient')
+
+ utils.Utils.DisableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
+ expected_calls = [
+ mock.call.dhclient(['A', 'B'], mock.ANY, None, release_lease=True),
]
self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py
index 43b8769..9f9bb98 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_6/utils.py
@@ -31,9 +31,19 @@ class Utils(utils.Utils):
logger: logger object, used to write to SysLog and serial port.
dhclient_script: string, the path to a dhclient script used by dhclient.
"""
+ helpers.CallEnableRouteAdvertisements(interfaces, logger)
helpers.CallDhclientIpv6(
interfaces, logger, dhclient_script=dhclient_script)
+ def DisableIpv6(self, interfaces, logger):
+ """Disable Ipv6 by giving up the DHCP lease using dhclient.
+
+ Args:
+ interface: string, the output device names for enabling IPv6.
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallDhclientIpv6(interfaces, logger, None, release_lease=True)
+
def EnableNetworkInterfaces(self, interfaces, logger, dhclient_script=None):
"""Enable the list of network interfaces.
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/tests/utils_test.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/tests/utils_test.py
index 0e096db..61260b6 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/tests/utils_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/tests/utils_test.py
@@ -97,12 +97,28 @@ class UtilsTest(unittest.TestCase):
self.assertEqual(mocks.mock_calls, expected_calls)
@mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
- def testEnableIpv6(self, mock_call):
+ @mock.patch('google_compute_engine.distro_lib.helpers.CallEnableRouteAdvertisements')
+ def testEnableIpv6(self, mock_call_enable_ra, mock_call_dhclient):
mocks = mock.Mock()
- mocks.attach_mock(mock_call, 'call')
+ mocks.attach_mock(mock_call_dhclient, 'dhclient')
+ mocks.attach_mock(mock_call_enable_ra, 'enable_ra')
utils.Utils.EnableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
- expected_calls = [mock.call.call(['A', 'B'], mock.ANY)]
+ expected_calls = [
+ mock.call.enable_ra(['A', 'B'], mock.ANY),
+ mock.call.dhclient(['A', 'B'], mock.ANY),
+ ]
+ self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro_lib.helpers.CallDhclientIpv6')
+ def testDisableIpv6(self, mock_call_dhclient):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call_dhclient, 'dhclient')
+
+ utils.Utils.DisableIpv6(self.mock_setup, ['A', 'B'], self.mock_logger)
+ expected_calls = [
+ mock.call.dhclient(['A', 'B'], mock.ANY, None, release_lease=True),
+ ]
self.assertEqual(mocks.mock_calls, expected_calls)
@mock.patch('google_compute_engine.distro_lib.el_7.utils.os.path.exists')
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py
index 062d471..e0e318b 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/el_7/utils.py
@@ -38,8 +38,18 @@ class Utils(utils.Utils):
logger: logger object, used to write to SysLog and serial port.
dhclient_script: string, the path to a dhclient script used by dhclient.
"""
+ helpers.CallEnableRouteAdvertisements(interfaces, logger)
helpers.CallDhclientIpv6(interfaces, logger)
+ def DisableIpv6(self, interfaces, logger):
+ """Disable Ipv6 by giving up the DHCP lease using dhclient.
+
+ Args:
+ interface: string, the output device names for enabling IPv6.
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallDhclientIpv6(interfaces, logger, None, release_lease=True)
+
def EnableNetworkInterfaces(self, interfaces, logger, dhclient_script=None):
"""Enable the list of network interfaces.
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py
index cbe810e..b7d16a1 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/helpers.py
@@ -42,19 +42,32 @@ def CallDhclient(
logger.warning('Could not enable interfaces %s.', interfaces)
-def CallDhclientIpv6(interfaces, logger, dhclient_script=None):
+def CallDhclientIpv6(interfaces, logger, dhclient_script=None,
+ release_lease=False):
"""Configure the network interfaces for IPv6 using dhclient.
Args:
interface: string, the output device names for enabling IPv6.
logger: logger object, used to write to SysLog and serial port.
dhclient_script: string, the path to a dhclient script used by dhclient.
+ release_lease: Release the IPv6 lease.
"""
- logger.info('Enabling IPv6 on the Ethernet interfaces %s.', interfaces)
+ logger.info('Calling Dhclient for IPv6 configuration '
+ 'on the Ethernet interfaces %s.', interfaces)
timeout_command = ['timeout', '5']
dhclient_command = ['dhclient']
+ if release_lease:
+ try:
+ subprocess.check_call(
+ timeout_command + dhclient_command + [
+ '-6', '-r', '-v'] + interfaces)
+ except subprocess.CalledProcessError:
+ logger.warning('Could not release IPv6 lease on interface %s.',
+ interfaces)
+ return
+
if dhclient_script and os.path.exists(dhclient_script):
dhclient_command += ['-sf', dhclient_script]
@@ -65,6 +78,18 @@ def CallDhclientIpv6(interfaces, logger, dhclient_script=None):
logger.warning('Could not enable IPv6 on interface %s.', interfaces)
+def CallEnableRouteAdvertisements(interfaces, logger):
+ """Enable route advertisements.
+ Args:
+ interfaces: list of string, the output device names to enable.
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ for interface in interfaces:
+ accept_ra = (
+ 'net.ipv6.conf.{interface}.accept_ra_rt_info_max_plen'.format(
+ interface=interface))
+ CallSysctl(logger, accept_ra, 128)
+
def CallHwclock(logger):
"""Sync clock using hwclock.
@@ -98,3 +123,20 @@ def CallNtpdate(logger):
logger.warning('Failed to sync system time with ntp server.')
else:
logger.info('Synced system time with ntp server.')
+
+def CallSysctl(logger, name, value):
+ """Write a variable using sysctl.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ name: string name of the sysctl variable.
+ value: value of the sysctl variable.
+ """
+ logger.info('Configuring sysctl %s.', name)
+
+ sysctl_command = [
+ 'sysctl', '-w', '{name}={value}'.format(name=name, value=value)]
+ try:
+ subprocess.check_call(sysctl_command)
+ except subprocess.CalledProcessError:
+ logger.warning('Unable to configure sysctl %s.', name)
diff --git a/packages/python-google-compute-engine/google_compute_engine/distro_lib/tests/helpers_test.py b/packages/python-google-compute-engine/google_compute_engine/distro_lib/tests/helpers_test.py
index 7c2c0b6..6afca57 100644
--- a/packages/python-google-compute-engine/google_compute_engine/distro_lib/tests/helpers_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/distro_lib/tests/helpers_test.py
@@ -67,42 +67,89 @@ class HelpersTest(unittest.TestCase):
@mock.patch('google_compute_engine.distro_lib.helpers.os.path.exists')
@mock.patch('google_compute_engine.distro_lib.helpers.subprocess.check_call')
- def testCallDhclientIpv6(self, mock_call, mock_exists):
- mocks = mock.Mock()
- mocks.attach_mock(mock_exists, 'exists')
- mocks.attach_mock(mock_call, 'call')
- mocks.attach_mock(self.mock_logger, 'logger')
+ def testCallDhclientIpv6NonExistentScript(self, mock_call, mock_exists):
+ mock_logger = mock.Mock()
- mock_exists.side_effect = [False, True]
+ mock_exists.side_effect = [False]
+ helpers.CallDhclientIpv6(['a', 'b'], mock_logger, 'test_script')
+ mock_call.assert_has_calls(
+ [
+ mock.call.call(
+ ['timeout', '5', 'dhclient', '-1', '-6', '-v', 'a', 'b']),
+ ])
+
+ @mock.patch('google_compute_engine.distro_lib.helpers.os.path.exists')
+ @mock.patch('google_compute_engine.distro_lib.helpers.subprocess.check_call')
+ def testCallDhclientIpv6(self, mock_call, mock_exists):
+ mock_logger = mock.Mock()
+ mock_exists.side_effect = [True]
mock_call.side_effect = [
- None, None, None, subprocess.CalledProcessError(1, 'Test'),
+ None,
+ None,
+ subprocess.CalledProcessError(1, 'Test'),
+ None,
+ None,
+ subprocess.CalledProcessError(1, 'Test'),
]
- helpers.CallDhclientIpv6(['a', 'b'], self.mock_logger, 'test_script')
- helpers.CallDhclientIpv6(['c', 'd'], self.mock_logger, 'test_script')
- helpers.CallDhclientIpv6(['e', 'f'], self.mock_logger, None)
- helpers.CallDhclientIpv6(['g', 'h'], self.mock_logger, None)
+ helpers.CallDhclientIpv6(['a', 'b'], mock_logger, 'test_script')
+ helpers.CallDhclientIpv6(['c', 'd'], mock_logger, None)
+ helpers.CallDhclientIpv6(['e', 'f'], mock_logger, None)
+ helpers.CallDhclientIpv6(
+ ['g', 'h'], mock_logger, 'test_script', release_lease=True)
+ helpers.CallDhclientIpv6(['i', 'j'], mock_logger, None, release_lease=True)
+ helpers.CallDhclientIpv6(['k', 'l'], mock_logger, None, release_lease=True)
expected_calls = [
- mock.call.logger.info(mock.ANY, ['a', 'b']),
- mock.call.exists('test_script'),
mock.call.call(
- ['timeout', '5', 'dhclient', '-1', '-6', '-v', 'a', 'b']),
- mock.call.logger.info(mock.ANY, ['c', 'd']),
- mock.call.exists('test_script'),
+ [
+ 'timeout', '5','dhclient', '-sf', 'test_script', '-1', '-6',
+ '-v', 'a', 'b',
+ ]),
mock.call.call(
- ['timeout', '5', 'dhclient', '-sf', 'test_script', '-1', '-6',
- '-v', 'c', 'd']),
- mock.call.logger.info(mock.ANY, ['e', 'f']),
+ [
+ 'timeout', '5', 'dhclient', '-1', '-6', '-v', 'c', 'd',
+ ]),
mock.call.call(
- ['timeout', '5', 'dhclient', '-1', '-6', '-v', 'e', 'f']),
- mock.call.logger.info(mock.ANY, ['g', 'h']),
+ [
+ 'timeout', '5', 'dhclient', '-1', '-6', '-v', 'e', 'f',
+ ]),
mock.call.call(
- ['timeout', '5', 'dhclient', '-1', '-6', '-v', 'g', 'h']),
- mock.call.logger.warning(mock.ANY, ['g', 'h']),
+ [
+ 'timeout', '5', 'dhclient', '-6', '-r', '-v', 'g', 'h',
+ ]),
+ mock.call.call(
+ [
+ 'timeout', '5', 'dhclient', '-6', '-r', '-v', 'i', 'j',
+ ]),
+ mock.call.call(
+ [
+ 'timeout', '5', 'dhclient', '-6', '-r', '-v', 'k', 'l',
+ ]),
]
- self.assertEqual(mocks.mock_calls, expected_calls)
+ self.assertEqual(mock_call.mock_calls, expected_calls)
+ mock_logger.assert_has_calls(
+ [
+ mock.call.warning(mock.ANY, ['e', 'f']),
+ ])
+ mock_logger.assert_has_calls(
+ [
+ mock.call.warning(mock.ANY, ['k', 'l']),
+ ])
+
+ @mock.patch('google_compute_engine.distro_lib.helpers.subprocess.check_call')
+ def testEnableRouteAdvertisements(self, mock_call):
+ mock_logger = mock.Mock()
+ interfaces = ['foo', 'bar', 'baz']
+ helpers.CallEnableRouteAdvertisements(interfaces, mock_logger)
+ mock_call.assert_has_calls([
+ mock.call(
+ [
+ 'sysctl', '-w',
+ 'net.ipv6.conf.%s.accept_ra_rt_info_max_plen=128' % interface,
+ ])
+ for interface in interfaces])
@mock.patch('google_compute_engine.distro_lib.helpers.subprocess.check_call')
def testCallHwclock(self, mock_call):
@@ -174,3 +221,20 @@ class HelpersTest(unittest.TestCase):
mock_check_call.assert_called_once_with(command_ntpdate, shell=True)
expected_calls = [mock.call.warning(mock.ANY)]
self.assertEqual(mock_logger.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro_lib.helpers.subprocess.check_call')
+ def testCallSysctl(self, mock_call):
+ command = ['sysctl', '-w']
+ mock_logger = mock.Mock()
+ expected_log_calls = []
+ for name in ['foo', 'bar', 'baz']:
+ for value in ['foo', 'bar', 'baz']:
+ params = ['{name}={value}'.format(name=name, value=value)]
+ helpers.CallSysctl(mock_logger, name, value)
+ mock_call.assert_called_with(command + params)
+ expected_log_calls.append(mock.call.info(mock.ANY, name))
+ self.assertEqual(mock_logger.mock_calls, expected_log_calls)
+
+ mock_call.side_effect = subprocess.CalledProcessError(1, 'Test')
+ helpers.CallSysctl(mock_logger, 'fail', 1)
+ mock_logger.assert_has_calls([mock.call.warning(mock.ANY, 'fail')])
diff --git a/packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py b/packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py
index ce0dd65..e152464 100644
--- a/packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py
+++ b/packages/python-google-compute-engine/google_compute_engine/networking/network_daemon.py
@@ -93,6 +93,8 @@ class NetworkDaemon(object):
default_interface = network_interfaces[0]
if default_interface.ipv6:
self.network_setup.EnableIpv6([default_interface.name])
+ else:
+ self.network_setup.DisableIpv6([default_interface.name])
self.network_setup.EnableNetworkInterfaces(
[interface.name for interface in network_interfaces[1:]])
diff --git a/packages/python-google-compute-engine/google_compute_engine/networking/network_setup/network_setup.py b/packages/python-google-compute-engine/google_compute_engine/networking/network_setup/network_setup.py
index f8b3be5..b92bed1 100755
--- a/packages/python-google-compute-engine/google_compute_engine/networking/network_setup/network_setup.py
+++ b/packages/python-google-compute-engine/google_compute_engine/networking/network_setup/network_setup.py
@@ -26,7 +26,6 @@ class NetworkSetup(object):
"""Enable network interfaces."""
interfaces = set()
- ipv6_interfaces = set()
network_interfaces = 'instance/network-interfaces'
def __init__(self, dhclient_script=None, dhcp_command=None, debug=False):
@@ -43,6 +42,8 @@ class NetworkSetup(object):
self.logger = logger.Logger(
name='network-setup', debug=debug, facility=facility)
self.distro_utils = distro_utils.Utils(debug=debug)
+ self.ipv6_initialized = False
+ self.ipv6_interfaces = set()
def EnableIpv6(self, interfaces):
"""Enable IPv6 on the list of network interfaces.
@@ -50,16 +51,37 @@ class NetworkSetup(object):
Args:
interfaces: list of string, the output device names for enabling IPv6.
"""
- if not interfaces or set(interfaces) == self.ipv6_interfaces:
+ if not interfaces or self.ipv6_interfaces == set(interfaces):
return
self.logger.info('Enabling IPv6 on Ethernet interface: %s.', interfaces)
- self.ipv6_interfaces = set(interfaces)
+ self.ipv6_interfaces = self.ipv6_interfaces.union(set(interfaces))
+ self.ipv6_initialized = True
# Distro-specific setup for enabling IPv6 on network interfaces.
self.distro_utils.EnableIpv6(
interfaces, self.logger, dhclient_script=self.dhclient_script)
+ def DisableIpv6(self, interfaces):
+ """Disable IPv6 on the list of network interfaces.
+
+ Args:
+ interfaces: list of string, the output device names for disabling IPv6.
+ """
+ # Allow to run once during Initialization and after that only when an
+ # interface is found in the ipv6_interfaces set.
+ if not interfaces or (
+ self.ipv6_initialized and not self.ipv6_interfaces.intersection(
+ set(interfaces))):
+ return
+
+ self.logger.info('Disabling IPv6 on Ethernet interface: %s.', interfaces)
+ self.ipv6_interfaces.difference_update(interfaces)
+ self.ipv6_initialized = True
+
+ # Distro-specific setup for disabling IPv6 on network interfaces.
+ self.distro_utils.DisableIpv6(interfaces, self.logger)
+
def EnableNetworkInterfaces(self, interfaces):
"""Enable the list of network interfaces.
diff --git a/packages/python-google-compute-engine/google_compute_engine/networking/network_setup/tests/network_setup_test.py b/packages/python-google-compute-engine/google_compute_engine/networking/network_setup/tests/network_setup_test.py
index c57547e..10fe2c5 100644
--- a/packages/python-google-compute-engine/google_compute_engine/networking/network_setup/tests/network_setup_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/networking/network_setup/tests/network_setup_test.py
@@ -47,16 +47,13 @@ class NetworkSetupTest(unittest.TestCase):
network_setup.NetworkSetup.EnableIpv6(self.setup, None)
network_setup.NetworkSetup.EnableIpv6(self.setup, [])
# Enable interfaces.
- network_setup.NetworkSetup.EnableIpv6(
- self.setup, ['A', 'B'])
+ network_setup.NetworkSetup.EnableIpv6(self.setup, ['A', 'B'])
self.assertEqual(self.setup.ipv6_interfaces, set(['A', 'B']))
# Add a new interface.
- network_setup.NetworkSetup.EnableIpv6(
- self.setup, ['A', 'B', 'C'])
+ network_setup.NetworkSetup.EnableIpv6(self.setup, ['A', 'B', 'C'])
self.assertEqual(self.setup.ipv6_interfaces, set(['A', 'B', 'C']))
- # Interfaces are already enabled.
- network_setup.NetworkSetup.EnableIpv6(
- self.setup, ['A', 'B', 'C'])
+ # Interfaces are already enabled, do nothing.
+ network_setup.NetworkSetup.EnableIpv6(self.setup, ['A', 'B', 'C'])
self.assertEqual(self.setup.ipv6_interfaces, set(['A', 'B', 'C']))
expected_calls = [
mock.call.logger.info(mock.ANY, ['A', 'B']),
@@ -68,6 +65,84 @@ class NetworkSetupTest(unittest.TestCase):
self.assertEqual(mocks.mock_calls, expected_calls)
@mock.patch('google_compute_engine.networking.network_setup.network_setup.subprocess.check_call')
+ def testDisableIpv6(self, mock_call):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call, 'call')
+ mocks.attach_mock(self.mock_logger, 'logger')
+ mocks.attach_mock(self.mock_distro_utils.EnableIpv6, 'enable')
+ mocks.attach_mock(self.mock_distro_utils.DisableIpv6, 'disable')
+ expected_calls = []
+
+ # Clean run, run disable once e.g. at boot.
+ network_setup.NetworkSetup.DisableIpv6(self.setup, ['A'])
+ self.assertEqual(self.setup.ipv6_interfaces, set([]))
+ # No more disables allowed, have to follow the contract of Enable and then
+ # Disable.
+ network_setup.NetworkSetup.DisableIpv6(self.setup, ['A'])
+ expected_calls.extend(
+ [
+ mock.call.logger.info(mock.ANY, ['A']),
+ mock.call.disable(['A'], mock.ANY),
+ ])
+ # Enable interfaces.
+ network_setup.NetworkSetup.EnableIpv6(self.setup, ['A', 'B', 'C'])
+ expected_calls.extend(
+ [
+ mock.call.logger.info(mock.ANY, ['A', 'B', 'C']),
+ mock.call.enable(
+ ['A', 'B', 'C'], mock.ANY, dhclient_script='/bin/script'),
+ ])
+ # Remove interface.
+ network_setup.NetworkSetup.DisableIpv6(self.setup, ['A'])
+ self.assertEqual(self.setup.ipv6_interfaces, set(['B', 'C']))
+ expected_calls.extend(
+ [
+ mock.call.logger.info(mock.ANY, ['A']),
+ mock.call.disable(['A'], mock.ANY),
+ ])
+
+ # Add it back.
+ network_setup.NetworkSetup.EnableIpv6(self.setup, ['A'])
+ self.assertEqual(self.setup.ipv6_interfaces, set(['A', 'B', 'C']))
+ expected_calls.extend(
+ [
+ mock.call.logger.info(mock.ANY, ['A']),
+ mock.call.enable(['A'], mock.ANY, dhclient_script='/bin/script'),
+ ])
+
+ # Remove list.
+ network_setup.NetworkSetup.DisableIpv6(self.setup, ['A', 'B'])
+ self.assertEqual(self.setup.ipv6_interfaces, set(['C']))
+ expected_calls.extend(
+ [
+ mock.call.logger.info(mock.ANY, ['A', 'B']),
+ mock.call.disable(['A', 'B'], mock.ANY),
+ ])
+
+ # Try removing again, these are no ops.
+ network_setup.NetworkSetup.DisableIpv6(self.setup, ['A'])
+ network_setup.NetworkSetup.DisableIpv6(self.setup, ['A', 'B'])
+
+ # Remove the last element.
+ network_setup.NetworkSetup.DisableIpv6(self.setup, ['C'])
+ self.assertEqual(self.setup.ipv6_interfaces, set([]))
+ expected_calls.extend(
+ [
+ mock.call.logger.info(mock.ANY, ['C']),
+ mock.call.disable(['C'], mock.ANY),
+ ])
+
+ # Empty list, allow adds back again.
+ network_setup.NetworkSetup.EnableIpv6(self.setup, ['A'])
+ self.assertEqual(self.setup.ipv6_interfaces, set(['A']))
+ expected_calls.extend(
+ [
+ mock.call.logger.info(mock.ANY, ['A']),
+ mock.call.enable(['A'], mock.ANY, dhclient_script='/bin/script'),
+ ])
+ self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.networking.network_setup.network_setup.subprocess.check_call')
def testEnableNetworkInterfaces(self, mock_call):
mocks = mock.Mock()
mocks.attach_mock(mock_call, 'call')
diff --git a/packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py b/packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py
index dd74fdd..9216ea3 100644
--- a/packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py
+++ b/packages/python-google-compute-engine/google_compute_engine/networking/tests/network_daemon_test.py
@@ -149,6 +149,7 @@ class NetworkDaemonTest(unittest.TestCase):
self.mock_setup, result)
expected_calls = [
mock.call.setup._ExtractInterfaceMetadata(result),
+ mock.call.network_setup.DisableIpv6(['eth0']),
mock.call.network_setup.EnableNetworkInterfaces(['eth1']),
mock.call.forwarding.HandleForwardedIps(
'eth0', ['a'], '1.1.1.1'),
@@ -182,6 +183,32 @@ class NetworkDaemonTest(unittest.TestCase):
]
self.assertEqual(mocks.mock_calls, expected_calls)
+ def testHandleNetworkInterfacesIpv6Disabled(self):
+ mocks = mock.Mock()
+ mocks.attach_mock(self.mock_ip_forwarding, 'forwarding')
+ mocks.attach_mock(self.mock_network_setup, 'network_setup')
+ mocks.attach_mock(self.mock_setup, 'setup')
+ self.mock_setup.ip_aliases = None
+ self.mock_setup.target_instance_ips = None
+ self.mock_setup.ip_forwarding_enabled = True
+ self.mock_setup.network_setup_enabled = True
+ self.mock_setup._ExtractInterfaceMetadata.return_value = [
+ network_daemon.NetworkDaemon.NetworkInterface(
+ 'eth0', forwarded_ips=['a'], ip='1.1.1.1', ipv6=False),
+ ]
+ result = mock.Mock()
+
+ network_daemon.NetworkDaemon.HandleNetworkInterfaces(
+ self.mock_setup, result)
+ expected_calls = [
+ mock.call.setup._ExtractInterfaceMetadata(result),
+ mock.call.network_setup.DisableIpv6(['eth0']),
+ mock.call.network_setup.EnableNetworkInterfaces([]),
+ mock.call.forwarding.HandleForwardedIps(
+ 'eth0', ['a'], '1.1.1.1'),
+ ]
+ self.assertEqual(mocks.mock_calls, expected_calls)
+
def testHandleNetworkInterfacesDisabled(self):
mocks = mock.Mock()
mocks.attach_mock(self.mock_ip_forwarding, 'forwarding')