summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Illfelder <illfelder@users.noreply.github.com>2016-07-27 17:42:19 -0700
committerGitHub <noreply@github.com>2016-07-27 17:42:19 -0700
commit709a82adbac3b41bf3f7f23dd29ef9112eaf7fe6 (patch)
treeb408572c84656bafc60d106f4d670f50dbac8861
parentaeadc0511f5cea3a417fabc73d3d386316bbf867 (diff)
downloadgoogle-compute-image-packages-709a82adbac3b41bf3f7f23dd29ef9112eaf7fe6.tar.gz
Use MAC address metadata for IP forwarding. (#312)
-rwxr-xr-xgoogle_compute_engine/ip_forwarding/ip_forwarding_daemon.py56
-rw-r--r--google_compute_engine/ip_forwarding/ip_forwarding_utils.py76
-rw-r--r--google_compute_engine/ip_forwarding/tests/ip_forwarding_daemon_test.py86
-rw-r--r--google_compute_engine/ip_forwarding/tests/ip_forwarding_utils_test.py121
4 files changed, 235 insertions, 104 deletions
diff --git a/google_compute_engine/ip_forwarding/ip_forwarding_daemon.py b/google_compute_engine/ip_forwarding/ip_forwarding_daemon.py
index e1abe4a..b56ffa9 100755
--- a/google_compute_engine/ip_forwarding/ip_forwarding_daemon.py
+++ b/google_compute_engine/ip_forwarding/ip_forwarding_daemon.py
@@ -41,7 +41,7 @@ LOCKFILE = '/var/lock/google_ip_forwarding.lock'
class IpForwardingDaemon(object):
"""Manage IP forwarding based on changes to forwarded IPs metadata."""
- forwarded_ips = 'instance/network-interfaces/0/forwarded-ips'
+ network_interfaces = 'instance/network-interfaces'
def __init__(self, proto_id=None, debug=False):
"""Constructor.
@@ -60,12 +60,12 @@ class IpForwardingDaemon(object):
with file_utils.LockFile(LOCKFILE):
self.logger.info('Starting Google IP Forwarding daemon.')
self.watcher.WatchMetadata(
- self.HandleForwardedIps, metadata_key=self.forwarded_ips,
+ self.HandleNetworkInterfaces, metadata_key=self.network_interfaces,
recursive=True)
except (IOError, OSError) as e:
self.logger.warning(str(e))
- def _LogForwardedIpChanges(self, configured, desired, to_add, to_remove):
+ def _LogForwardedIpChanges(self, configured, desired, to_add, to_remove, interface):
"""Log the planned IP address changes.
Args:
@@ -73,44 +73,66 @@ class IpForwardingDaemon(object):
desired: list, the IP address strings that will be configured.
to_add: list, the forwarded IP address strings to configure.
to_remove: list, the forwarded IP address strings to delete.
+ interface: string, the output device to modify.
"""
if not to_add and not to_remove:
return
self.logger.info(
- 'Changing forwarded IPs from %s to %s by adding %s and removing %s.',
- configured or None, desired or None, to_add or None, to_remove or None)
+ 'Changing %s forwarded IPs from %s to %s by adding %s and removing %s.',
+ interface, configured or None, desired or None, to_add or None,
+ to_remove or None)
- def _AddForwardedIps(self, forwarded_ips):
+ def _AddForwardedIps(self, forwarded_ips, interface):
"""Configure the forwarded IP address on the network interface.
Args:
forwarded_ips: list, the forwarded IP address strings to configure.
+ interface: string, the output device to use.
"""
for address in forwarded_ips:
- self.utils.AddForwardedIp(address)
+ self.utils.AddForwardedIp(address, interface)
- def _RemoveForwardedIps(self, forwarded_ips):
+ def _RemoveForwardedIps(self, forwarded_ips, interface):
"""Remove the forwarded IP addresses from the network interface.
Args:
forwarded_ips: list, the forwarded IP address strings to delete.
+ interface: string, the output device to use.
"""
for address in forwarded_ips:
- self.utils.RemoveForwardedIp(address)
+ self.utils.RemoveForwardedIp(address, interface)
- def HandleForwardedIps(self, result):
- """Called when forwarded IPs metadata changes.
+ def _HandleForwardedIps(self, forwarded_ips, interface):
+ """Handle changes to the forwarded IPs on a network interface.
Args:
- result: string, the metadata response with the new forwarded IP addresses.
+ forwarded_ips: list, the forwarded IP address strings desired.
+ interface: string, the output device to configure.
"""
- desired = self.utils.ParseForwardedIps(result)
- configured = self.utils.GetForwardedIps()
+ desired = self.utils.ParseForwardedIps(forwarded_ips)
+ configured = self.utils.GetForwardedIps(interface)
to_add = sorted(set(desired) - set(configured))
to_remove = sorted(set(configured) - set(desired))
- self._LogForwardedIpChanges(configured, desired, to_add, to_remove)
- self._AddForwardedIps(to_add)
- self._RemoveForwardedIps(to_remove)
+ self._LogForwardedIpChanges(
+ configured, desired, to_add, to_remove, interface)
+ self._AddForwardedIps(to_add, interface)
+ self._RemoveForwardedIps(to_remove, interface)
+
+ def HandleNetworkInterfaces(self, result):
+ """Called when network interface metadata changes.
+
+ Args:
+ result: string, the metadata response with the new network interfaces.
+ """
+ for network_interface in result:
+ mac_address = network_interface.get('mac')
+ interface = self.utils.GetNetworkInterface(mac_address)
+ if interface:
+ forwarded_ips = network_interface.get('forwardedIps')
+ self._HandleForwardedIps(forwarded_ips, interface)
+ else:
+ message = 'Network interface not found for MAC address: %s.'
+ self.logger.warning(message, mac_address)
def main():
diff --git a/google_compute_engine/ip_forwarding/ip_forwarding_utils.py b/google_compute_engine/ip_forwarding/ip_forwarding_utils.py
index dee62f1..913954b 100644
--- a/google_compute_engine/ip_forwarding/ip_forwarding_utils.py
+++ b/google_compute_engine/ip_forwarding/ip_forwarding_utils.py
@@ -15,6 +15,7 @@
"""Utilities for configuring IP address forwarding."""
+import os
import re
import subprocess
@@ -32,14 +33,44 @@ class IpForwardingUtils(object):
proto_id: string, the routing protocol identifier for Google IP changes.
"""
self.logger = logger
- self.options = {
- 'dev': self._GetDefaultInterface(),
- 'proto': proto_id or '66',
+ self.proto_id = proto_id or '66'
+ self.interfaces = self._CreateInterfaceMap()
+
+ def _CreateInterfaceMap(self):
+ """Generate a dictionary mapping MAC address to ethernet interfaces.
+
+ Returns:
+ dict, string MAC addresses mapped to the string network interface name.
+ """
+ interfaces = {}
+ for interface in os.listdir('/sys/class/net'):
+ try:
+ mac_address = open('/sys/class/net/%s/address' % interface).read().strip()
+ except (IOError, OSError) as e:
+ message = 'Unable to determine MAC address for %s. %s.'
+ self.logger.warning(message, interface, str(e))
+ else:
+ interfaces[mac_address] = interface
+ return interfaces
+
+ def _CreateRouteOptions(self, **kwargs):
+ """Create a dictionary of parameters to append to the ip route command.
+
+ Args:
+ **kwargs: dict, the string parameters to update in the ip route command.
+
+ Returns:
+ dict, the string parameters to append to the ip route command.
+ """
+ options = {
+ 'proto': self.proto_id,
'scope': 'host',
}
+ options.update(kwargs)
+ return options
def _RunIpRoute(self, args=None, options=None):
- """Run a command with IP route and return the response.
+ """Run a command with ip route and return the response.
Args:
args: list, the string ip route command args to execute.
@@ -68,19 +99,16 @@ class IpForwardingUtils(object):
return stdout
return ''
- def _GetDefaultInterface(self):
- """Get the name of the default network interface.
+ def GetNetworkInterface(self, mac_address):
+ """Get the name of the network interface associated with a MAC address.
+
+ Args:
+ mac_address: string, the hardware address of the network interface.
Returns:
- string, the name of the default network interface.
+ string, the network interface associated with a MAC address or None.
"""
- result = self._RunIpRoute(args=['list'])
- for route in result.decode('utf-8').split('\n'):
- fields = route.split()
- if fields and fields[0] == 'default' and 'dev' in fields:
- index = fields.index('dev') + 1
- return fields[index] if index < len(fields) else 'eth0'
- return 'eth0'
+ return self.interfaces.get(mac_address)
def ParseForwardedIps(self, forwarded_ips):
"""Parse and validate forwarded IP addresses.
@@ -100,30 +128,38 @@ class IpForwardingUtils(object):
self.logger.warning('Could not parse IP address: "%s".', ip)
return addresses
- def GetForwardedIps(self):
+ def GetForwardedIps(self, interface):
"""Retrieve the list of configured forwarded IP addresses.
+ Args:
+ interface: string, the output device to query.
+
Returns:
list, the IP address strings.
"""
args = ['ls', 'table', 'local', 'type', 'local']
- result = self._RunIpRoute(args=args, options=self.options)
+ options = self._CreateRouteOptions(dev=interface)
+ result = self._RunIpRoute(args=args, options=options)
return self.ParseForwardedIps(result.split())
- def AddForwardedIp(self, address):
+ def AddForwardedIp(self, address, interface):
"""Configure a new IP address on the network interface.
Args:
address: string, the IP address to configure.
+ interface: string, the output device to use.
"""
args = ['add', 'to', 'local', '%s/32' % address]
- self._RunIpRoute(args=args, options=self.options)
+ options = self._CreateRouteOptions(dev=interface)
+ self._RunIpRoute(args=args, options=options)
- def RemoveForwardedIp(self, address):
+ def RemoveForwardedIp(self, address, interface):
"""Delete an IP address on the network interface.
Args:
address: string, the IP address to configure.
+ interface: string, the output device to use.
"""
args = ['delete', 'to', 'local', '%s/32' % address]
- self._RunIpRoute(args=args, options=self.options)
+ options = self._CreateRouteOptions(dev=interface)
+ self._RunIpRoute(args=args, options=options)
diff --git a/google_compute_engine/ip_forwarding/tests/ip_forwarding_daemon_test.py b/google_compute_engine/ip_forwarding/tests/ip_forwarding_daemon_test.py
index 769eebf..0b06b36 100644
--- a/google_compute_engine/ip_forwarding/tests/ip_forwarding_daemon_test.py
+++ b/google_compute_engine/ip_forwarding/tests/ip_forwarding_daemon_test.py
@@ -46,10 +46,10 @@ class IpForwardingDaemonTest(unittest.TestCase):
mocks.attach_mock(mock_logger, 'logger')
mocks.attach_mock(mock_utils, 'utils')
mocks.attach_mock(mock_watcher, 'watcher')
- metadata_key = ip_forwarding_daemon.IpForwardingDaemon.forwarded_ips
+ metadata_key = ip_forwarding_daemon.IpForwardingDaemon.network_interfaces
with mock.patch.object(
ip_forwarding_daemon.IpForwardingDaemon,
- 'HandleForwardedIps') as mock_handle:
+ 'HandleNetworkInterfaces') as mock_handle:
ip_forwarding_daemon.IpForwardingDaemon(proto_id='66', debug=True)
expected_calls = [
mock.call.logger.Logger(name=mock.ANY, debug=True, facility=mock.ANY),
@@ -80,7 +80,7 @@ class IpForwardingDaemonTest(unittest.TestCase):
mocks.attach_mock(mock_watcher, 'watcher')
mock_lock.LockFile.side_effect = IOError('Test Error')
with mock.patch.object(
- ip_forwarding_daemon.IpForwardingDaemon, 'HandleForwardedIps'):
+ ip_forwarding_daemon.IpForwardingDaemon, 'HandleNetworkInterfaces'):
ip_forwarding_daemon.IpForwardingDaemon()
expected_calls = [
mock.call.logger.Logger(
@@ -95,47 +95,47 @@ class IpForwardingDaemonTest(unittest.TestCase):
def testLogForwardedIpChanges(self):
ip_forwarding_daemon.IpForwardingDaemon._LogForwardedIpChanges(
- self.mock_setup, [], [], [], [])
+ self.mock_setup, [], [], [], [], '1')
ip_forwarding_daemon.IpForwardingDaemon._LogForwardedIpChanges(
- self.mock_setup, ['a'], ['a'], [], [])
+ self.mock_setup, ['a'], ['a'], [], [], '2')
ip_forwarding_daemon.IpForwardingDaemon._LogForwardedIpChanges(
- self.mock_setup, ['a'], [], [], ['a'])
+ self.mock_setup, ['a'], [], [], ['a'], '3')
ip_forwarding_daemon.IpForwardingDaemon._LogForwardedIpChanges(
- self.mock_setup, ['a', 'b'], ['b'], [], ['a'])
+ self.mock_setup, ['a', 'b'], ['b'], [], ['a'], '4')
ip_forwarding_daemon.IpForwardingDaemon._LogForwardedIpChanges(
- self.mock_setup, ['a'], ['b'], ['b'], ['a'])
+ self.mock_setup, ['a'], ['b'], ['b'], ['a'], '5')
expected_calls = [
- mock.call.info(mock.ANY, ['a'], None, None, ['a']),
- mock.call.info(mock.ANY, ['a', 'b'], ['b'], None, ['a']),
- mock.call.info(mock.ANY, ['a'], ['b'], ['b'], ['a']),
+ mock.call.info(mock.ANY, '3', ['a'], None, None, ['a']),
+ mock.call.info(mock.ANY, '4', ['a', 'b'], ['b'], None, ['a']),
+ mock.call.info(mock.ANY, '5', ['a'], ['b'], ['b'], ['a']),
]
self.assertEqual(self.mock_logger.mock_calls, expected_calls)
def testAddForwardedIp(self):
ip_forwarding_daemon.IpForwardingDaemon._AddForwardedIps(
- self.mock_setup, [])
+ self.mock_setup, [], 'interface')
self.assertEqual(self.mock_utils.mock_calls, [])
ip_forwarding_daemon.IpForwardingDaemon._AddForwardedIps(
- self.mock_setup, ['a', 'b', 'c'])
+ self.mock_setup, ['a', 'b', 'c'], 'interface')
expected_calls = [
- mock.call.AddForwardedIp('a'),
- mock.call.AddForwardedIp('b'),
- mock.call.AddForwardedIp('c'),
+ mock.call.AddForwardedIp('a', 'interface'),
+ mock.call.AddForwardedIp('b', 'interface'),
+ mock.call.AddForwardedIp('c', 'interface'),
]
self.assertEqual(self.mock_utils.mock_calls, expected_calls)
def testRemoveForwardedIp(self):
ip_forwarding_daemon.IpForwardingDaemon._RemoveForwardedIps(
- self.mock_setup, [])
+ self.mock_setup, [], 'interface')
self.assertEqual(self.mock_utils.mock_calls, [])
ip_forwarding_daemon.IpForwardingDaemon._RemoveForwardedIps(
- self.mock_setup, ['a', 'b', 'c'])
+ self.mock_setup, ['a', 'b', 'c'], 'interface')
expected_calls = [
- mock.call.RemoveForwardedIp('a'),
- mock.call.RemoveForwardedIp('b'),
- mock.call.RemoveForwardedIp('c'),
+ mock.call.RemoveForwardedIp('a', 'interface'),
+ mock.call.RemoveForwardedIp('b', 'interface'),
+ mock.call.RemoveForwardedIp('c', 'interface'),
]
self.assertEqual(self.mock_utils.mock_calls, expected_calls)
@@ -147,19 +147,47 @@ class IpForwardingDaemonTest(unittest.TestCase):
mocks.attach_mock(self.mock_setup, 'setup')
self.mock_utils.ParseForwardedIps.return_value = desired
self.mock_utils.GetForwardedIps.return_value = configured
- result = 'result'
+ forwarded_ips = 'forwarded ips'
+ interface = 'interface'
expected_add = ['d']
expected_remove = ['a', 'b']
- ip_forwarding_daemon.IpForwardingDaemon.HandleForwardedIps(
- self.mock_setup, result)
+ ip_forwarding_daemon.IpForwardingDaemon._HandleForwardedIps(
+ self.mock_setup, forwarded_ips, interface)
expected_calls = [
- mock.call.utils.ParseForwardedIps(result),
- mock.call.utils.GetForwardedIps(),
+ mock.call.utils.ParseForwardedIps(forwarded_ips),
+ mock.call.utils.GetForwardedIps(interface),
mock.call.setup._LogForwardedIpChanges(
- configured, desired, expected_add, expected_remove),
- mock.call.setup._AddForwardedIps(expected_add),
- mock.call.setup._RemoveForwardedIps(expected_remove),
+ configured, desired, expected_add, expected_remove, interface),
+ mock.call.setup._AddForwardedIps(expected_add, interface),
+ mock.call.setup._RemoveForwardedIps(expected_remove, interface),
+ ]
+ self.assertEqual(mocks.mock_calls, expected_calls)
+
+ def testHandleNetworkInterfaces(self):
+ mocks = mock.Mock()
+ mocks.attach_mock(self.mock_utils, 'utils')
+ mocks.attach_mock(self.mock_setup, 'setup')
+ self.mock_utils.GetNetworkInterface.side_effect = [
+ 'eth0', 'eth1', 'eth2', None]
+ result = [
+ {'mac': '1', 'forwardedIps': 'a'},
+ {'mac': '2', 'forwardedIps': 'b'},
+ {'mac': '3'},
+ {'forwardedIps': 'c'},
+ ]
+
+ ip_forwarding_daemon.IpForwardingDaemon.HandleNetworkInterfaces(
+ self.mock_setup, result)
+ expected_calls = [
+ mock.call.utils.GetNetworkInterface('1'),
+ mock.call.setup._HandleForwardedIps('a', 'eth0'),
+ mock.call.utils.GetNetworkInterface('2'),
+ mock.call.setup._HandleForwardedIps('b', 'eth1'),
+ mock.call.utils.GetNetworkInterface('3'),
+ mock.call.setup._HandleForwardedIps(None, 'eth2'),
+ mock.call.utils.GetNetworkInterface(None),
+ mock.call.setup.logger.warning(mock.ANY, None),
]
self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/google_compute_engine/ip_forwarding/tests/ip_forwarding_utils_test.py b/google_compute_engine/ip_forwarding/tests/ip_forwarding_utils_test.py
index 0d32939..7c82dfb 100644
--- a/google_compute_engine/ip_forwarding/tests/ip_forwarding_utils_test.py
+++ b/google_compute_engine/ip_forwarding/tests/ip_forwarding_utils_test.py
@@ -16,6 +16,7 @@
"""Unittest for ip_forwarding_utils.py module."""
from google_compute_engine.ip_forwarding import ip_forwarding_utils
+from google_compute_engine.test_compat import builtin
from google_compute_engine.test_compat import mock
from google_compute_engine.test_compat import unittest
@@ -24,9 +25,70 @@ class IpForwardingUtilsTest(unittest.TestCase):
def setUp(self):
self.mock_logger = mock.Mock()
+ self.interfaces = {'address': 'interface'}
self.options = {'hello': 'world'}
self.mock_utils = ip_forwarding_utils.IpForwardingUtils(self.mock_logger)
- self.mock_utils.options = self.options
+ self.mock_utils.interfaces = self.interfaces
+ self.mock_utils.proto_id = 'proto'
+
+ @mock.patch('google_compute_engine.ip_forwarding.ip_forwarding_utils.os.listdir')
+ def testCreateInterfaceMap(self, mock_listdir):
+ mock_open = mock.mock_open()
+ interface_map = {
+ '1': 'a',
+ '2': 'b',
+ '3': 'c',
+ }
+ mock_listdir.return_value = interface_map.values()
+
+ with mock.patch('%s.open' % builtin, mock_open, create=False):
+ addresses = interface_map.keys()
+ addresses = ['%s\n' % address for address in addresses]
+ mock_open().read.side_effect = interface_map.keys()
+ self.assertEqual(self.mock_utils._CreateInterfaceMap(), interface_map)
+
+ @mock.patch('google_compute_engine.ip_forwarding.ip_forwarding_utils.os.listdir')
+ def testCreateInterfaceMapError(self, mock_listdir):
+ mock_open = mock.mock_open()
+ mock_listdir.return_value = ['a', 'b', 'c']
+
+ with mock.patch('%s.open' % builtin, mock_open, create=False):
+ mock_open().read.side_effect = [
+ '1', OSError('OSError'), IOError('IOError')]
+ self.assertEqual(self.mock_utils._CreateInterfaceMap(), {'1': 'a'})
+ expected_calls = [
+ mock.call.warning(mock.ANY, 'b', 'OSError'),
+ mock.call.warning(mock.ANY, 'c', 'IOError'),
+ ]
+ self.assertEqual(self.mock_logger.mock_calls, expected_calls)
+
+ def testCreateRouteOptions(self):
+ # Default options.
+ expected_options = {
+ 'proto': 'proto',
+ 'scope': 'host',
+ }
+ self.assertEqual(self.mock_utils._CreateRouteOptions(), expected_options)
+
+ # Update dictionary when arguments are specified.
+ expected_options = {
+ 'proto': 'proto',
+ 'scope': 'host',
+ 'num': 1,
+ 'string': 'hello world',
+ }
+ self.assertEqual(
+ self.mock_utils._CreateRouteOptions(num=1, string='hello world'),
+ expected_options)
+
+ # Update the default options.
+ expected_options = {
+ 'proto': 'test 1',
+ 'scope': 'test 2',
+ }
+ self.assertEqual(
+ self.mock_utils._CreateRouteOptions(proto='test 1', scope='test 2'),
+ expected_options)
@mock.patch('google_compute_engine.ip_forwarding.ip_forwarding_utils.subprocess')
def testRunIpRoute(self, mock_subprocess):
@@ -69,29 +131,10 @@ class IpForwardingUtilsTest(unittest.TestCase):
self.mock_logger.warning.assert_called_once_with(
mock.ANY, command, 'Test Error')
- def testGetDefaultInterface(self):
- mock_run = mock.Mock()
- mock_run.side_effect = [
- bytes(b''),
- bytes(b'invalid route\n'),
- bytes(b'default invalid interface\n'),
- bytes(b'default dev\n'),
- bytes(b'\n\n\ndefault dev interface\n\n\n'),
- bytes(b'default via ip dev interface\nip default eth0\n'),
- bytes(b'ip default eth0\ndefault via ip dev interface\n'),
- ]
- self.mock_utils._RunIpRoute = mock_run
-
- # Invalid routes default to 'eth0'.
- self.assertEqual(self.mock_utils._GetDefaultInterface(), 'eth0')
- self.assertEqual(self.mock_utils._GetDefaultInterface(), 'eth0')
- self.assertEqual(self.mock_utils._GetDefaultInterface(), 'eth0')
- self.assertEqual(self.mock_utils._GetDefaultInterface(), 'eth0')
-
- # Valid routes where the expected response is 'interface'.
- self.assertEqual(self.mock_utils._GetDefaultInterface(), 'interface')
- self.assertEqual(self.mock_utils._GetDefaultInterface(), 'interface')
- self.assertEqual(self.mock_utils._GetDefaultInterface(), 'interface')
+ def testGetNetworkInterface(self):
+ self.assertIsNone(self.mock_utils.GetNetworkInterface('invalid'))
+ self.assertEqual(
+ self.mock_utils.GetNetworkInterface('address'), 'interface')
def testParseForwardedIps(self):
self.assertEqual(self.mock_utils.ParseForwardedIps(None), [])
@@ -133,41 +176,43 @@ class IpForwardingUtilsTest(unittest.TestCase):
self.assertEqual(self.mock_logger.mock_calls, expected_calls)
def testGetForwardedIps(self):
+ mock_options = mock.Mock()
+ mock_options.return_value = self.options
mock_run = mock.Mock()
- mock_run.return_value = ''
+ mock_run.return_value = 'a\nb\n'
mock_parse = mock.Mock()
mock_parse.return_value = ['Test']
+ self.mock_utils._CreateRouteOptions = mock_options
self.mock_utils._RunIpRoute = mock_run
self.mock_utils.ParseForwardedIps = mock_parse
- self.assertEqual(self.mock_utils.GetForwardedIps(), ['Test'])
+ self.assertEqual(self.mock_utils.GetForwardedIps('interface'), ['Test'])
+ mock_options.assert_called_once_with(dev='interface')
mock_run.assert_called_once_with(
args=['ls', 'table', 'local', 'type', 'local'], options=self.options)
- mock_parse.assert_called_once_with([])
-
- def testGetForwardedIpsSplit(self):
- mock_run = mock.Mock()
- mock_run.return_value = 'a\nb\n'
- mock_parse = mock.Mock()
- self.mock_utils._RunIpRoute = mock_run
- self.mock_utils.ParseForwardedIps = mock_parse
-
- self.mock_utils.GetForwardedIps()
mock_parse.assert_called_once_with(['a', 'b'])
def testAddForwardedIp(self):
+ mock_options = mock.Mock()
+ mock_options.return_value = self.options
mock_run = mock.Mock()
+ self.mock_utils._CreateRouteOptions = mock_options
self.mock_utils._RunIpRoute = mock_run
- self.mock_utils.AddForwardedIp('1.1.1.1')
+ self.mock_utils.AddForwardedIp('1.1.1.1', 'interface')
+ mock_options.assert_called_once_with(dev='interface')
mock_run.assert_called_once_with(
args=['add', 'to', 'local', '1.1.1.1/32'], options=self.options)
def testRemoveForwardedIp(self):
+ mock_options = mock.Mock()
+ mock_options.return_value = self.options
mock_run = mock.Mock()
+ self.mock_utils._CreateRouteOptions = mock_options
self.mock_utils._RunIpRoute = mock_run
- self.mock_utils.RemoveForwardedIp('1.1.1.1')
+ self.mock_utils.RemoveForwardedIp('1.1.1.1', 'interface')
+ mock_options.assert_called_once_with(dev='interface')
mock_run.assert_called_once_with(
args=['delete', 'to', 'local', '1.1.1.1/32'], options=self.options)