diff options
| -rwxr-xr-x | nova/network/linux_net.py | 33 | ||||
| -rw-r--r-- | nova/tests/test_linux_net.py | 957 |
2 files changed, 514 insertions, 476 deletions
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 7f79a92f8..2a81488fe 100755 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -371,6 +371,18 @@ class IptablesManager(object): return new_filter +# NOTE(jkoelker) This is just a nice little stub point since mocking +# builtins with mox is a nightmare +def write_to_file(file, data, mode='w'): + with open(file, mode) as f: + f.write(data) + + +def ensure_path(path): + if not os.path.exists(path): + os.makedirs(path) + + def metadata_forward(): """Create forwarding rule for metadata.""" iptables_manager.ipv4['nat'].add_rule('PREROUTING', @@ -606,15 +618,13 @@ def release_dhcp(dev, address, mac_address): def update_dhcp(context, dev, network_ref): conffile = _dhcp_file(dev, 'conf') - with open(conffile, 'w') as f: - f.write(get_dhcp_hosts(context, network_ref)) + write_to_file(conffile, get_dhcp_hosts(context, network_ref)) restart_dhcp(context, dev, network_ref) def update_dhcp_hostfile_with_text(dev, hosts_text): conffile = _dhcp_file(dev, 'conf') - with open(conffile, 'w') as f: - f.write(hosts_text) + write_to_file(conffile, hosts_text) def kill_dhcp(dev): @@ -637,8 +647,7 @@ def restart_dhcp(context, dev, network_ref): if FLAGS.use_single_default_gateway: optsfile = _dhcp_file(dev, 'opts') - with open(optsfile, 'w') as f: - f.write(get_dhcp_opts(context, network_ref)) + write_to_file(optsfile, get_dhcp_opts(context, network_ref)) os.chmod(optsfile, 0644) # Make sure dnsmasq can actually read it (it setuid()s to "nobody") @@ -690,8 +699,7 @@ def restart_dhcp(context, dev, network_ref): @utils.synchronized('radvd_start') def update_ra(context, dev, network_ref): conffile = _ra_file(dev, 'conf') - with open(conffile, 'w') as f: - conf_str = """ + conf_str = """ interface %s { AdvSendAdvert on; @@ -704,7 +712,7 @@ interface %s }; }; """ % (dev, network_ref['cidr_v6']) - f.write(conf_str) + write_to_file(conffile, conf_str) # Make sure radvd can actually read it (it setuid()s to "nobody") os.chmod(conffile, 0644) @@ -792,8 +800,7 @@ def _device_exists(device): def _dhcp_file(dev, kind): """Return path to a pid, leases or conf file for a bridge/device.""" - if not os.path.exists(FLAGS.networks_path): - os.makedirs(FLAGS.networks_path) + ensure_path(FLAGS.networks_path) return os.path.abspath('%s/nova-%s.%s' % (FLAGS.networks_path, dev, kind)) @@ -801,9 +808,7 @@ def _dhcp_file(dev, kind): def _ra_file(dev, kind): """Return path to a pid or conf file for a bridge/device.""" - - if not os.path.exists(FLAGS.networks_path): - os.makedirs(FLAGS.networks_path) + ensure_path(FLAGS.networks_path) return os.path.abspath('%s/nova-ra-%s.%s' % (FLAGS.networks_path, dev, kind)) diff --git a/nova/tests/test_linux_net.py b/nova/tests/test_linux_net.py index 0f5862f22..c8f8cbe06 100644 --- a/nova/tests/test_linux_net.py +++ b/nova/tests/test_linux_net.py @@ -1,462 +1,495 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2011 NTT
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import mox
-
-from nova import db
-from nova import flags
-from nova import log as logging
-from nova import test
-from nova import utils
-from nova.network import linux_net
-
-
-FLAGS = flags.FLAGS
-
-LOG = logging.getLogger('nova.tests.network')
-
-
-HOST = "testhost"
-
-instances = [{'id': 0,
- 'host': 'fake_instance00',
- 'hostname': 'fake_instance00'},
- {'id': 1,
- 'host': 'fake_instance01',
- 'hostname': 'fake_instance01'}]
-
-
-addresses = [{"address": "10.0.0.1"},
- {"address": "10.0.0.2"},
- {"address": "10.0.0.3"},
- {"address": "10.0.0.4"},
- {"address": "10.0.0.5"},
- {"address": "10.0.0.6"}]
-
-
-networks = [{'id': 0,
- 'uuid': "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
- 'label': 'test0',
- 'injected': False,
- 'multi_host': False,
- 'cidr': '192.168.0.0/24',
- 'cidr_v6': '2001:db8::/64',
- 'gateway_v6': '2001:db8::1',
- 'netmask_v6': '64',
- 'netmask': '255.255.255.0',
- 'bridge': 'fa0',
- 'bridge_interface': 'fake_fa0',
- 'gateway': '192.168.0.1',
- 'broadcast': '192.168.0.255',
- 'dns1': '192.168.0.1',
- 'dns2': '192.168.0.2',
- 'dhcp_server': '0.0.0.0',
- 'dhcp_start': '192.168.100.1',
- 'vlan': None,
- 'host': None,
- 'project_id': 'fake_project',
- 'vpn_public_address': '192.168.0.2'},
- {'id': 1,
- 'uuid': "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
- 'label': 'test1',
- 'injected': False,
- 'multi_host': False,
- 'cidr': '192.168.1.0/24',
- 'cidr_v6': '2001:db9::/64',
- 'gateway_v6': '2001:db9::1',
- 'netmask_v6': '64',
- 'netmask': '255.255.255.0',
- 'bridge': 'fa1',
- 'bridge_interface': 'fake_fa1',
- 'gateway': '192.168.1.1',
- 'broadcast': '192.168.1.255',
- 'dns1': '192.168.0.1',
- 'dns2': '192.168.0.2',
- 'dhcp_server': '0.0.0.0',
- 'dhcp_start': '192.168.100.1',
- 'vlan': None,
- 'host': None,
- 'project_id': 'fake_project',
- 'vpn_public_address': '192.168.1.2'}]
-
-
-fixed_ips = [{'id': 0,
- 'network_id': 0,
- 'address': '192.168.0.100',
- 'instance_id': 0,
- 'allocated': True,
- 'virtual_interface_id': 0,
- 'virtual_interface': addresses[0],
- 'instance': instances[0],
- 'floating_ips': []},
- {'id': 1,
- 'network_id': 1,
- 'address': '192.168.1.100',
- 'instance_id': 0,
- 'allocated': True,
- 'virtual_interface_id': 1,
- 'virtual_interface': addresses[1],
- 'instance': instances[0],
- 'floating_ips': []},
- {'id': 2,
- 'network_id': 1,
- 'address': '192.168.0.101',
- 'instance_id': 1,
- 'allocated': True,
- 'virtual_interface_id': 2,
- 'virtual_interface': addresses[2],
- 'instance': instances[1],
- 'floating_ips': []},
- {'id': 3,
- 'network_id': 0,
- 'address': '192.168.1.101',
- 'instance_id': 1,
- 'allocated': True,
- 'virtual_interface_id': 3,
- 'virtual_interface': addresses[3],
- 'instance': instances[1],
- 'floating_ips': []},
- {'id': 4,
- 'network_id': 0,
- 'address': '192.168.0.102',
- 'instance_id': 0,
- 'allocated': True,
- 'virtual_interface_id': 4,
- 'virtual_interface': addresses[4],
- 'instance': instances[0],
- 'floating_ips': []},
- {'id': 5,
- 'network_id': 1,
- 'address': '192.168.1.102',
- 'instance_id': 1,
- 'allocated': True,
- 'virtual_interface_id': 5,
- 'virtual_interface': addresses[5],
- 'instance': instances[1],
- 'floating_ips': []}]
-
-
-vifs = [{'id': 0,
- 'address': 'DE:AD:BE:EF:00:00',
- 'uuid': '00000000-0000-0000-0000-0000000000000000',
- 'network_id': 0,
- 'network': networks[0],
- 'instance_id': 0},
- {'id': 1,
- 'address': 'DE:AD:BE:EF:00:01',
- 'uuid': '00000000-0000-0000-0000-0000000000000001',
- 'network_id': 1,
- 'network': networks[1],
- 'instance_id': 0},
- {'id': 2,
- 'address': 'DE:AD:BE:EF:00:02',
- 'uuid': '00000000-0000-0000-0000-0000000000000002',
- 'network_id': 1,
- 'network': networks[1],
- 'instance_id': 1},
- {'id': 3,
- 'address': 'DE:AD:BE:EF:00:03',
- 'uuid': '00000000-0000-0000-0000-0000000000000003',
- 'network_id': 0,
- 'network': networks[0],
- 'instance_id': 1},
- {'id': 4,
- 'address': 'DE:AD:BE:EF:00:04',
- 'uuid': '00000000-0000-0000-0000-0000000000000004',
- 'network_id': 0,
- 'network': networks[0],
- 'instance_id': 0},
- {'id': 5,
- 'address': 'DE:AD:BE:EF:00:05',
- 'uuid': '00000000-0000-0000-0000-0000000000000005',
- 'network_id': 1,
- 'network': networks[1],
- 'instance_id': 1}]
-
-
-class LinuxNetworkTestCase(test.TestCase):
-
- def setUp(self):
- super(LinuxNetworkTestCase, self).setUp()
- network_driver = FLAGS.network_driver
- self.driver = utils.import_object(network_driver)
- self.driver.db = db
-
- def test_update_dhcp_for_nw00(self):
- self.flags(use_single_default_gateway=True)
- self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips')
- self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance')
-
- db.network_get_associated_fixed_ips(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([fixed_ips[0],
- fixed_ips[3]])
-
- db.network_get_associated_fixed_ips(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([fixed_ips[0],
- fixed_ips[3]])
- db.virtual_interface_get_by_instance(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([vifs[0], vifs[1]])
- db.virtual_interface_get_by_instance(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([vifs[2], vifs[3]])
- self.mox.ReplayAll()
-
- self.driver.update_dhcp(None, "eth0", networks[0])
-
- def test_update_dhcp_for_nw01(self):
- self.flags(use_single_default_gateway=True)
- self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips')
- self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance')
-
- db.network_get_associated_fixed_ips(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([fixed_ips[1],
- fixed_ips[2]])
-
- db.network_get_associated_fixed_ips(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([fixed_ips[1],
- fixed_ips[2]])
- db.virtual_interface_get_by_instance(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([vifs[0], vifs[1]])
- db.virtual_interface_get_by_instance(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([vifs[2], vifs[3]])
- self.mox.ReplayAll()
-
- self.driver.update_dhcp(None, "eth0", networks[0])
-
- def test_get_dhcp_hosts_for_nw00(self):
- self.flags(use_single_default_gateway=True)
- self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips')
-
- db.network_get_associated_fixed_ips(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([fixed_ips[0],
- fixed_ips[3]])
- self.mox.ReplayAll()
-
- expected = \
- "10.0.0.1,fake_instance00.novalocal,"\
- "192.168.0.100,net:NW-i00000000-0\n"\
- "10.0.0.4,fake_instance01.novalocal,"\
- "192.168.1.101,net:NW-i00000001-0"
- actual_hosts = self.driver.get_dhcp_hosts(None, networks[1])
-
- self.assertEquals(actual_hosts, expected)
-
- def test_get_dhcp_hosts_for_nw01(self):
- self.flags(use_single_default_gateway=True)
- self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips')
-
- db.network_get_associated_fixed_ips(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([fixed_ips[1],
- fixed_ips[2]])
- self.mox.ReplayAll()
-
- expected = \
- "10.0.0.2,fake_instance00.novalocal,"\
- "192.168.1.100,net:NW-i00000000-1\n"\
- "10.0.0.3,fake_instance01.novalocal,"\
- "192.168.0.101,net:NW-i00000001-1"
- actual_hosts = self.driver.get_dhcp_hosts(None, networks[0])
-
- self.assertEquals(actual_hosts, expected)
-
- def test_get_dhcp_opts_for_nw00(self):
- self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips')
- self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance')
-
- db.network_get_associated_fixed_ips(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([fixed_ips[0],
- fixed_ips[3],
- fixed_ips[4]])
- db.virtual_interface_get_by_instance(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([vifs[0],
- vifs[1],
- vifs[4]])
- db.virtual_interface_get_by_instance(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([vifs[2],
- vifs[3],
- vifs[5]])
- self.mox.ReplayAll()
-
- expected_opts = 'NW-i00000001-0,3'
- actual_opts = self.driver.get_dhcp_opts(None, networks[0])
-
- self.assertEquals(actual_opts, expected_opts)
-
- def test_get_dhcp_opts_for_nw01(self):
- self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips')
- self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance')
-
- db.network_get_associated_fixed_ips(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([fixed_ips[1],
- fixed_ips[2],
- fixed_ips[5]])
- db.virtual_interface_get_by_instance(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([vifs[0],
- vifs[1],
- vifs[4]])
- db.virtual_interface_get_by_instance(mox.IgnoreArg(),
- mox.IgnoreArg())\
- .AndReturn([vifs[2],
- vifs[3],
- vifs[5]])
- self.mox.ReplayAll()
-
- expected_opts = "NW-i00000000-1,3"
- actual_opts = self.driver.get_dhcp_opts(None, networks[1])
-
- self.assertEquals(actual_opts, expected_opts)
-
- def test_dhcp_opts_not_default_gateway_network(self):
- expected = "NW-i00000000-0,3"
- actual = self.driver._host_dhcp_opts(fixed_ips[0])
- self.assertEquals(actual, expected)
-
- def test_host_dhcp_without_default_gateway_network(self):
- expected = ("10.0.0.1,fake_instance00.novalocal,192.168.0.100")
- actual = self.driver._host_dhcp(fixed_ips[0])
- self.assertEquals(actual, expected)
-
- def test_linux_bridge_driver_plug(self):
- """Makes sure plug doesn't drop FORWARD by default.
-
- Ensures bug 890195 doesn't reappear."""
-
- def fake_execute(*args, **kwargs):
- return "", ""
- self.stubs.Set(utils, 'execute', fake_execute)
-
- def verify_add_rule(chain, rule):
- self.assertEqual(chain, 'FORWARD')
- self.assertIn('ACCEPT', rule)
- self.stubs.Set(linux_net.iptables_manager.ipv4['filter'],
- 'add_rule', verify_add_rule)
- driver = linux_net.LinuxBridgeInterfaceDriver()
- driver.plug({"bridge": "br100", "bridge_interface": "eth0"},
- "fakemac")
-
- def _test_initialize_gateway(self, existing, expected, routes=''):
- self.flags(fake_network=False)
- executes = []
-
- def fake_execute(*args, **kwargs):
- executes.append(args)
- if args[0] == 'ip' and args[1] == 'addr' and args[2] == 'show':
- return existing, ""
- if args[0] == 'route' and args[1] == '-n':
- return routes, ""
- self.stubs.Set(utils, 'execute', fake_execute)
- network = {'dhcp_server': '192.168.1.1',
- 'cidr': '192.168.1.0/24',
- 'broadcast': '192.168.1.255',
- 'cidr_v6': '2001:db8::/64'}
- self.driver.initialize_gateway_device('eth0', network)
- self.assertEqual(executes, expected)
-
- def test_initialize_gateway_moves_wrong_ip(self):
- existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
- " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
- " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
- " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
- " inet6 dead::beef:dead:beef:dead/64 scope link\n"
- " valid_lft forever preferred_lft forever\n")
- expected = [
- ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
- ('route', '-n'),
- ('ip', 'addr', 'del', '192.168.0.1/24',
- 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'),
- ('ip', 'addr', 'add', '192.168.1.1/24',
- 'brd', '192.168.1.255', 'dev', 'eth0'),
- ('ip', 'addr', 'add', '192.168.0.1/24',
- 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'),
- ('ip', '-f', 'inet6', 'addr', 'change',
- '2001:db8::/64', 'dev', 'eth0'),
- ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
- ]
- self._test_initialize_gateway(existing, expected)
-
- def test_initialize_gateway_resets_route(self):
- routes = "0.0.0.0 192.68.0.1 0.0.0.0 " \
- "UG 100 0 0 eth0"
- existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
- " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
- " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
- " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
- " inet6 dead::beef:dead:beef:dead/64 scope link\n"
- " valid_lft forever preferred_lft forever\n")
- expected = [
- ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
- ('route', '-n'),
- ('route', 'del', 'default', 'gw', '192.68.0.1', 'dev', 'eth0'),
- ('ip', 'addr', 'del', '192.168.0.1/24',
- 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'),
- ('ip', 'addr', 'add', '192.168.1.1/24',
- 'brd', '192.168.1.255', 'dev', 'eth0'),
- ('ip', 'addr', 'add', '192.168.0.1/24',
- 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'),
- ('route', 'add', 'default', 'gw', '192.68.0.1'),
- ('ip', '-f', 'inet6', 'addr', 'change',
- '2001:db8::/64', 'dev', 'eth0'),
- ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
- ]
- self._test_initialize_gateway(existing, expected, routes)
-
- def test_initialize_gateway_no_move_right_ip(self):
- existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
- " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
- " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
- " inet 192.168.1.1/24 brd 192.168.1.255 scope global eth0\n"
- " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n"
- " inet6 dead::beef:dead:beef:dead/64 scope link\n"
- " valid_lft forever preferred_lft forever\n")
- expected = [
- ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
- ('ip', '-f', 'inet6', 'addr', 'change',
- '2001:db8::/64', 'dev', 'eth0'),
- ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
- ]
- self._test_initialize_gateway(existing, expected)
-
- def test_initialize_gateway_add_if_blank(self):
- existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> "
- " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n"
- " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n"
- " inet6 dead::beef:dead:beef:dead/64 scope link\n"
- " valid_lft forever preferred_lft forever\n")
- expected = [
- ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'),
- ('route', '-n'),
- ('ip', 'addr', 'add', '192.168.1.1/24',
- 'brd', '192.168.1.255', 'dev', 'eth0'),
- ('ip', '-f', 'inet6', 'addr', 'change',
- '2001:db8::/64', 'dev', 'eth0'),
- ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'),
- ]
- self._test_initialize_gateway(existing, expected)
+# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 NTT +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import os + +import mox + +from nova import db +from nova import flags +from nova import log as logging +from nova import test +from nova import utils +from nova.network import linux_net + + +FLAGS = flags.FLAGS + +LOG = logging.getLogger('nova.tests.network') + + +HOST = "testhost" + +instances = [{'id': 0, + 'host': 'fake_instance00', + 'hostname': 'fake_instance00'}, + {'id': 1, + 'host': 'fake_instance01', + 'hostname': 'fake_instance01'}] + + +addresses = [{"address": "10.0.0.1"}, + {"address": "10.0.0.2"}, + {"address": "10.0.0.3"}, + {"address": "10.0.0.4"}, + {"address": "10.0.0.5"}, + {"address": "10.0.0.6"}] + + +networks = [{'id': 0, + 'uuid': "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", + 'label': 'test0', + 'injected': False, + 'multi_host': False, + 'cidr': '192.168.0.0/24', + 'cidr_v6': '2001:db8::/64', + 'gateway_v6': '2001:db8::1', + 'netmask_v6': '64', + 'netmask': '255.255.255.0', + 'bridge': 'fa0', + 'bridge_interface': 'fake_fa0', + 'gateway': '192.168.0.1', + 'broadcast': '192.168.0.255', + 'dns1': '192.168.0.1', + 'dns2': '192.168.0.2', + 'dhcp_server': '0.0.0.0', + 'dhcp_start': '192.168.100.1', + 'vlan': None, + 'host': None, + 'project_id': 'fake_project', + 'vpn_public_address': '192.168.0.2'}, + {'id': 1, + 'uuid': "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", + 'label': 'test1', + 'injected': False, + 'multi_host': False, + 'cidr': '192.168.1.0/24', + 'cidr_v6': '2001:db9::/64', + 'gateway_v6': '2001:db9::1', + 'netmask_v6': '64', + 'netmask': '255.255.255.0', + 'bridge': 'fa1', + 'bridge_interface': 'fake_fa1', + 'gateway': '192.168.1.1', + 'broadcast': '192.168.1.255', + 'dns1': '192.168.0.1', + 'dns2': '192.168.0.2', + 'dhcp_server': '0.0.0.0', + 'dhcp_start': '192.168.100.1', + 'vlan': None, + 'host': None, + 'project_id': 'fake_project', + 'vpn_public_address': '192.168.1.2'}] + + +fixed_ips = [{'id': 0, + 'network_id': 0, + 'address': '192.168.0.100', + 'instance_id': 0, + 'allocated': True, + 'virtual_interface_id': 0, + 'virtual_interface': addresses[0], + 'instance': instances[0], + 'floating_ips': []}, + {'id': 1, + 'network_id': 1, + 'address': '192.168.1.100', + 'instance_id': 0, + 'allocated': True, + 'virtual_interface_id': 1, + 'virtual_interface': addresses[1], + 'instance': instances[0], + 'floating_ips': []}, + {'id': 2, + 'network_id': 1, + 'address': '192.168.0.101', + 'instance_id': 1, + 'allocated': True, + 'virtual_interface_id': 2, + 'virtual_interface': addresses[2], + 'instance': instances[1], + 'floating_ips': []}, + {'id': 3, + 'network_id': 0, + 'address': '192.168.1.101', + 'instance_id': 1, + 'allocated': True, + 'virtual_interface_id': 3, + 'virtual_interface': addresses[3], + 'instance': instances[1], + 'floating_ips': []}, + {'id': 4, + 'network_id': 0, + 'address': '192.168.0.102', + 'instance_id': 0, + 'allocated': True, + 'virtual_interface_id': 4, + 'virtual_interface': addresses[4], + 'instance': instances[0], + 'floating_ips': []}, + {'id': 5, + 'network_id': 1, + 'address': '192.168.1.102', + 'instance_id': 1, + 'allocated': True, + 'virtual_interface_id': 5, + 'virtual_interface': addresses[5], + 'instance': instances[1], + 'floating_ips': []}] + + +vifs = [{'id': 0, + 'address': 'DE:AD:BE:EF:00:00', + 'uuid': '00000000-0000-0000-0000-0000000000000000', + 'network_id': 0, + 'network': networks[0], + 'instance_id': 0}, + {'id': 1, + 'address': 'DE:AD:BE:EF:00:01', + 'uuid': '00000000-0000-0000-0000-0000000000000001', + 'network_id': 1, + 'network': networks[1], + 'instance_id': 0}, + {'id': 2, + 'address': 'DE:AD:BE:EF:00:02', + 'uuid': '00000000-0000-0000-0000-0000000000000002', + 'network_id': 1, + 'network': networks[1], + 'instance_id': 1}, + {'id': 3, + 'address': 'DE:AD:BE:EF:00:03', + 'uuid': '00000000-0000-0000-0000-0000000000000003', + 'network_id': 0, + 'network': networks[0], + 'instance_id': 1}, + {'id': 4, + 'address': 'DE:AD:BE:EF:00:04', + 'uuid': '00000000-0000-0000-0000-0000000000000004', + 'network_id': 0, + 'network': networks[0], + 'instance_id': 0}, + {'id': 5, + 'address': 'DE:AD:BE:EF:00:05', + 'uuid': '00000000-0000-0000-0000-0000000000000005', + 'network_id': 1, + 'network': networks[1], + 'instance_id': 1}] + + +class LinuxNetworkTestCase(test.TestCase): + + def setUp(self): + super(LinuxNetworkTestCase, self).setUp() + network_driver = FLAGS.network_driver + self.driver = utils.import_object(network_driver) + self.driver.db = db + + def test_update_dhcp_for_nw00(self): + self.flags(use_single_default_gateway=True) + + self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips') + self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance') + self.mox.StubOutWithMock(self.driver, 'write_to_file') + self.mox.StubOutWithMock(self.driver, 'ensure_path') + self.mox.StubOutWithMock(os, 'chmod') + + db.network_get_associated_fixed_ips(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([fixed_ips[0], + fixed_ips[3]]) + + db.network_get_associated_fixed_ips(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([fixed_ips[0], + fixed_ips[3]]) + db.virtual_interface_get_by_instance(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([vifs[0], vifs[1]]) + db.virtual_interface_get_by_instance(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([vifs[2], vifs[3]]) + self.driver.write_to_file(mox.IgnoreArg(), mox.IgnoreArg()) + self.driver.write_to_file(mox.IgnoreArg(), mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + os.chmod(mox.IgnoreArg(), mox.IgnoreArg()) + os.chmod(mox.IgnoreArg(), mox.IgnoreArg()) + + self.mox.ReplayAll() + + self.driver.update_dhcp(None, "eth0", networks[0]) + + def test_update_dhcp_for_nw01(self): + self.flags(use_single_default_gateway=True) + self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips') + self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance') + self.mox.StubOutWithMock(self.driver, 'write_to_file') + self.mox.StubOutWithMock(self.driver, 'ensure_path') + self.mox.StubOutWithMock(os, 'chmod') + + db.network_get_associated_fixed_ips(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([fixed_ips[1], + fixed_ips[2]]) + + db.network_get_associated_fixed_ips(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([fixed_ips[1], + fixed_ips[2]]) + db.virtual_interface_get_by_instance(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([vifs[0], vifs[1]]) + db.virtual_interface_get_by_instance(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([vifs[2], vifs[3]]) + self.driver.write_to_file(mox.IgnoreArg(), mox.IgnoreArg()) + self.driver.write_to_file(mox.IgnoreArg(), mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + self.driver.ensure_path(mox.IgnoreArg()) + os.chmod(mox.IgnoreArg(), mox.IgnoreArg()) + os.chmod(mox.IgnoreArg(), mox.IgnoreArg()) + + self.mox.ReplayAll() + + self.driver.update_dhcp(None, "eth0", networks[0]) + + def test_get_dhcp_hosts_for_nw00(self): + self.flags(use_single_default_gateway=True) + self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips') + + db.network_get_associated_fixed_ips(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([fixed_ips[0], + fixed_ips[3]]) + self.mox.ReplayAll() + + expected = \ + "10.0.0.1,fake_instance00.novalocal,"\ + "192.168.0.100,net:NW-i00000000-0\n"\ + "10.0.0.4,fake_instance01.novalocal,"\ + "192.168.1.101,net:NW-i00000001-0" + actual_hosts = self.driver.get_dhcp_hosts(None, networks[1]) + + self.assertEquals(actual_hosts, expected) + + def test_get_dhcp_hosts_for_nw01(self): + self.flags(use_single_default_gateway=True) + self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips') + + db.network_get_associated_fixed_ips(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([fixed_ips[1], + fixed_ips[2]]) + self.mox.ReplayAll() + + expected = \ + "10.0.0.2,fake_instance00.novalocal,"\ + "192.168.1.100,net:NW-i00000000-1\n"\ + "10.0.0.3,fake_instance01.novalocal,"\ + "192.168.0.101,net:NW-i00000001-1" + actual_hosts = self.driver.get_dhcp_hosts(None, networks[0]) + + self.assertEquals(actual_hosts, expected) + + def test_get_dhcp_opts_for_nw00(self): + self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips') + self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance') + + db.network_get_associated_fixed_ips(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([fixed_ips[0], + fixed_ips[3], + fixed_ips[4]]) + db.virtual_interface_get_by_instance(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([vifs[0], + vifs[1], + vifs[4]]) + db.virtual_interface_get_by_instance(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([vifs[2], + vifs[3], + vifs[5]]) + self.mox.ReplayAll() + + expected_opts = 'NW-i00000001-0,3' + actual_opts = self.driver.get_dhcp_opts(None, networks[0]) + + self.assertEquals(actual_opts, expected_opts) + + def test_get_dhcp_opts_for_nw01(self): + self.mox.StubOutWithMock(db, 'network_get_associated_fixed_ips') + self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance') + + db.network_get_associated_fixed_ips(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([fixed_ips[1], + fixed_ips[2], + fixed_ips[5]]) + db.virtual_interface_get_by_instance(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([vifs[0], + vifs[1], + vifs[4]]) + db.virtual_interface_get_by_instance(mox.IgnoreArg(), + mox.IgnoreArg())\ + .AndReturn([vifs[2], + vifs[3], + vifs[5]]) + self.mox.ReplayAll() + + expected_opts = "NW-i00000000-1,3" + actual_opts = self.driver.get_dhcp_opts(None, networks[1]) + + self.assertEquals(actual_opts, expected_opts) + + def test_dhcp_opts_not_default_gateway_network(self): + expected = "NW-i00000000-0,3" + actual = self.driver._host_dhcp_opts(fixed_ips[0]) + self.assertEquals(actual, expected) + + def test_host_dhcp_without_default_gateway_network(self): + expected = ("10.0.0.1,fake_instance00.novalocal,192.168.0.100") + actual = self.driver._host_dhcp(fixed_ips[0]) + self.assertEquals(actual, expected) + + def test_linux_bridge_driver_plug(self): + """Makes sure plug doesn't drop FORWARD by default. + + Ensures bug 890195 doesn't reappear.""" + + def fake_execute(*args, **kwargs): + return "", "" + self.stubs.Set(utils, 'execute', fake_execute) + + def verify_add_rule(chain, rule): + self.assertEqual(chain, 'FORWARD') + self.assertIn('ACCEPT', rule) + self.stubs.Set(linux_net.iptables_manager.ipv4['filter'], + 'add_rule', verify_add_rule) + driver = linux_net.LinuxBridgeInterfaceDriver() + driver.plug({"bridge": "br100", "bridge_interface": "eth0"}, + "fakemac") + + def _test_initialize_gateway(self, existing, expected, routes=''): + self.flags(fake_network=False) + executes = [] + + def fake_execute(*args, **kwargs): + executes.append(args) + if args[0] == 'ip' and args[1] == 'addr' and args[2] == 'show': + return existing, "" + if args[0] == 'route' and args[1] == '-n': + return routes, "" + self.stubs.Set(utils, 'execute', fake_execute) + network = {'dhcp_server': '192.168.1.1', + 'cidr': '192.168.1.0/24', + 'broadcast': '192.168.1.255', + 'cidr_v6': '2001:db8::/64'} + self.driver.initialize_gateway_device('eth0', network) + self.assertEqual(executes, expected) + + def test_initialize_gateway_moves_wrong_ip(self): + existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> " + " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n" + " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n" + " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n" + " inet6 dead::beef:dead:beef:dead/64 scope link\n" + " valid_lft forever preferred_lft forever\n") + expected = [ + ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'), + ('route', '-n'), + ('ip', 'addr', 'del', '192.168.0.1/24', + 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'), + ('ip', 'addr', 'add', '192.168.1.1/24', + 'brd', '192.168.1.255', 'dev', 'eth0'), + ('ip', 'addr', 'add', '192.168.0.1/24', + 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'), + ('ip', '-f', 'inet6', 'addr', 'change', + '2001:db8::/64', 'dev', 'eth0'), + ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'), + ] + self._test_initialize_gateway(existing, expected) + + def test_initialize_gateway_resets_route(self): + routes = "0.0.0.0 192.68.0.1 0.0.0.0 " \ + "UG 100 0 0 eth0" + existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> " + " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n" + " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n" + " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n" + " inet6 dead::beef:dead:beef:dead/64 scope link\n" + " valid_lft forever preferred_lft forever\n") + expected = [ + ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'), + ('route', '-n'), + ('route', 'del', 'default', 'gw', '192.68.0.1', 'dev', 'eth0'), + ('ip', 'addr', 'del', '192.168.0.1/24', + 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'), + ('ip', 'addr', 'add', '192.168.1.1/24', + 'brd', '192.168.1.255', 'dev', 'eth0'), + ('ip', 'addr', 'add', '192.168.0.1/24', + 'brd', '192.168.0.255', 'scope', 'global', 'dev', 'eth0'), + ('route', 'add', 'default', 'gw', '192.68.0.1'), + ('ip', '-f', 'inet6', 'addr', 'change', + '2001:db8::/64', 'dev', 'eth0'), + ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'), + ] + self._test_initialize_gateway(existing, expected, routes) + + def test_initialize_gateway_no_move_right_ip(self): + existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> " + " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n" + " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n" + " inet 192.168.1.1/24 brd 192.168.1.255 scope global eth0\n" + " inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0\n" + " inet6 dead::beef:dead:beef:dead/64 scope link\n" + " valid_lft forever preferred_lft forever\n") + expected = [ + ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'), + ('ip', '-f', 'inet6', 'addr', 'change', + '2001:db8::/64', 'dev', 'eth0'), + ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'), + ] + self._test_initialize_gateway(existing, expected) + + def test_initialize_gateway_add_if_blank(self): + existing = ("2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> " + " mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000\n" + " link/ether de:ad:be:ef:be:ef brd ff:ff:ff:ff:ff:ff\n" + " inet6 dead::beef:dead:beef:dead/64 scope link\n" + " valid_lft forever preferred_lft forever\n") + expected = [ + ('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'), + ('route', '-n'), + ('ip', 'addr', 'add', '192.168.1.1/24', + 'brd', '192.168.1.255', 'dev', 'eth0'), + ('ip', '-f', 'inet6', 'addr', 'change', + '2001:db8::/64', 'dev', 'eth0'), + ('ip', 'link', 'set', 'dev', 'eth0', 'promisc', 'on'), + ] + self._test_initialize_gateway(existing, expected) |
