diff options
-rw-r--r-- | nova/network/l3.py | 10 | ||||
-rw-r--r-- | nova/network/manager.py | 23 | ||||
-rw-r--r-- | nova/tests/network/test_manager.py | 201 |
3 files changed, 229 insertions, 5 deletions
diff --git a/nova/network/l3.py b/nova/network/l3.py index 9ca6b6a43..7511f7ba4 100644 --- a/nova/network/l3.py +++ b/nova/network/l3.py @@ -79,7 +79,13 @@ class LinuxNetL3(L3Driver): if self.initialized: return LOG.debug("Initializing linux_net L3 driver") - linux_net.init_host() + fixed_range = kwargs.get('fixed_range', False) + networks = kwargs.get('networks', None) + if not fixed_range and networks is not None: + for network in networks: + self.initialize_network(network['cidr']) + else: + linux_net.init_host() linux_net.ensure_metadata_ip() linux_net.metadata_forward() self.initialized = True @@ -88,7 +94,7 @@ class LinuxNetL3(L3Driver): return self.initialized def initialize_network(self, cidr): - linux_net.add_snat_rule(cidr) + linux_net.init_host(cidr) def initialize_gateway(self, network_ref): mac_address = utils.generate_mac_address() diff --git a/nova/network/manager.py b/nova/network/manager.py index 482744a8b..f1a3c45d2 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -106,9 +106,12 @@ network_opts = [ cfg.IntOpt('network_size', default=256, help='Number of addresses in each private subnet'), + # TODO(mathrock): Deprecate in Grizzly, remove in Havana cfg.StrOpt('fixed_range', default='10.0.0.0/8', - help='Fixed IP address block'), + help='DEPRECATED - Fixed IP address block.' + 'If set to an empty string, the subnet range(s) will be ' + 'automatically determined and configured.'), cfg.StrOpt('fixed_range_v6', default='fd00::/48', help='Fixed IPv6 address block'), @@ -1559,7 +1562,12 @@ class FlatDHCPManager(RPCAllocateFixedIP, floating_ips.FloatingIP, """Do any initialization that needs to be run if this is a standalone service. """ - self.l3driver.initialize() + if not CONF.fixed_range: + ctxt = context.get_admin_context() + networks = self.db.network_get_all_by_host(ctxt, self.host) + self.l3driver.initialize(fixed_range=False, networks=networks) + else: + self.l3driver.initialize(fixed_range=CONF.fixed_range) super(FlatDHCPManager, self).init_host() self.init_host_floating_ips() @@ -1567,6 +1575,8 @@ class FlatDHCPManager(RPCAllocateFixedIP, floating_ips.FloatingIP, """Sets up network on this host.""" network['dhcp_server'] = self._get_dhcp_ip(context, network) + if not CONF.fixed_range: + self.l3driver.initialize_network(network.get('cidr')) self.l3driver.initialize_gateway(network) if not CONF.fake_network: @@ -1630,7 +1640,12 @@ class VlanManager(RPCAllocateFixedIP, floating_ips.FloatingIP, NetworkManager): standalone service. """ - self.l3driver.initialize() + if not CONF.fixed_range: + ctxt = context.get_admin_context() + networks = self.db.network_get_all_by_host(ctxt, self.host) + self.l3driver.initialize(fixed_range=False, networks=networks) + else: + self.l3driver.initialize(fixed_range=CONF.fixed_range) NetworkManager.init_host(self) self.init_host_floating_ips() @@ -1773,6 +1788,8 @@ class VlanManager(RPCAllocateFixedIP, floating_ips.FloatingIP, NetworkManager): address = network['vpn_public_address'] network['dhcp_server'] = self._get_dhcp_ip(context, network) + if not CONF.fixed_range: + self.l3driver.initialize_network(network.get('cidr')) self.l3driver.initialize_gateway(network) # NOTE(vish): only ensure this forward if the address hasn't been set diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py index 92b8e1d91..6121ae8ac 100644 --- a/nova/tests/network/test_manager.py +++ b/nova/tests/network/test_manager.py @@ -1601,6 +1601,207 @@ class CommonNetworkTestCase(test.TestCase): self.assertRaises(exception.NetworkNotFound, manager.disassociate_network, fake_context, uuid) + def _test_init_host_static_fixed_range(self, net_manager): + self.flags(fake_network=True, + fixed_range='10.0.0.0/22', + routing_source_ip='192.168.0.1', + metadata_host='192.168.0.1', + public_interface='eth1', + dmz_cidr=['10.0.3.0/24']) + binary_name = linux_net.get_binary_name() + + # Stub out calls we don't want to really run + self.stubs.Set(linux_net.iptables_manager, '_apply', lambda: None) + self.stubs.Set(floating_ips.FloatingIP, 'init_host_floating_ips', + lambda *args: None) + + # Call the network manager init code to configure the fixed_range + net_manager.init_host() + + # Get the iptables rules that got created + current_lines = [] + new_lines = linux_net.iptables_manager._modify_rules(current_lines, + linux_net.iptables_manager.ipv4['nat'], + table_name='nat') + + # The expected rules that should be configured based on the fixed_range + expected_lines = ['[0:0] -A %s-snat -s %s -j SNAT --to-source %s -o %s' + % (binary_name, CONF.fixed_range, + CONF.routing_source_ip, + CONF.public_interface), + '[0:0] -A %s-POSTROUTING -s %s -d %s/32 -j ACCEPT' + % (binary_name, CONF.fixed_range, + CONF.metadata_host), + '[0:0] -A %s-POSTROUTING -s %s -d %s -j ACCEPT' + % (binary_name, CONF.fixed_range, CONF.dmz_cidr[0]), + '[0:0] -A %s-POSTROUTING -s %s -d %s -m conntrack ! ' + '--ctstate DNAT -j ACCEPT' % (binary_name, + CONF.fixed_range, + CONF.fixed_range)] + + # Finally, compare the expected rules against the actual ones + for line in expected_lines: + self.assertTrue(line in new_lines) + + def _test_init_host_dynamic_fixed_range(self, net_manager): + self.flags(fake_network=True, + fixed_range='', + routing_source_ip='172.16.0.1', + metadata_host='172.16.0.1', + public_interface='eth1', + dmz_cidr=['10.0.3.0/24']) + binary_name = linux_net.get_binary_name() + + # Stub out calls we don't want to really run, mock the db + self.stubs.Set(linux_net.iptables_manager, '_apply', lambda: None) + self.stubs.Set(floating_ips.FloatingIP, 'init_host_floating_ips', + lambda *args: None) + self.stubs.Set(net_manager.l3driver, 'initialize_gateway', + lambda *args: None) + self.mox.StubOutWithMock(db, 'network_get_all_by_host') + db.network_get_all_by_host(mox.IgnoreArg(), + mox.IgnoreArg()).MultipleTimes().AndReturn(networks) + self.mox.ReplayAll() + + # Call the network manager init code to configure the fixed_range + net_manager.init_host() + + # Get the iptables rules that got created + current_lines = [] + new_lines = linux_net.iptables_manager._modify_rules(current_lines, + linux_net.iptables_manager.ipv4['nat'], + table_name='nat') + + # The expected rules that should be configured based on the fixed_range + expected_lines = ['[0:0] -A %s-snat -s %s -j SNAT --to-source %s -o %s' + % (binary_name, networks[0]['cidr'], + CONF.routing_source_ip, + CONF.public_interface), + '[0:0] -A %s-POSTROUTING -s %s -d %s/32 -j ACCEPT' + % (binary_name, networks[0]['cidr'], + CONF.metadata_host), + '[0:0] -A %s-POSTROUTING -s %s -d %s -j ACCEPT' + % (binary_name, networks[0]['cidr'], + CONF.dmz_cidr[0]), + '[0:0] -A %s-POSTROUTING -s %s -d %s -m conntrack ! ' + '--ctstate DNAT -j ACCEPT' % (binary_name, + networks[0]['cidr'], + networks[0]['cidr']), + '[0:0] -A %s-snat -s %s -j SNAT --to-source %s -o %s' + % (binary_name, networks[1]['cidr'], + CONF.routing_source_ip, + CONF.public_interface), + '[0:0] -A %s-POSTROUTING -s %s -d %s/32 -j ACCEPT' + % (binary_name, networks[1]['cidr'], + CONF.metadata_host), + '[0:0] -A %s-POSTROUTING -s %s -d %s -j ACCEPT' + % (binary_name, networks[1]['cidr'], + CONF.dmz_cidr[0]), + '[0:0] -A %s-POSTROUTING -s %s -d %s -m conntrack ! ' + '--ctstate DNAT -j ACCEPT' % (binary_name, + networks[1]['cidr'], + networks[1]['cidr'])] + + # Compare the expected rules against the actual ones + for line in expected_lines: + self.assertTrue(line in new_lines) + + # Add an additional network and ensure the rules get configured + new_network = {'id': 2, + 'uuid': 'cccccccc-cccc-cccc-cccc-cccccccc', + 'label': 'test2', + 'injected': False, + 'multi_host': False, + 'cidr': '192.168.2.0/24', + 'cidr_v6': '2001:dba::/64', + 'gateway_v6': '2001:dba::1', + 'netmask_v6': '64', + 'netmask': '255.255.255.0', + 'bridge': 'fa1', + 'bridge_interface': 'fake_fa1', + 'gateway': '192.168.2.1', + 'broadcast': '192.168.2.255', + 'dns1': '192.168.2.1', + 'dns2': '192.168.2.2', + 'vlan': None, + 'host': HOST, + 'project_id': 'fake_project', + 'vpn_public_address': '192.168.2.2', + 'vpn_public_port': '22', + 'vpn_private_address': '10.0.0.2'} + + # Call the network manager init code to configure the fixed_range + ctxt = context.get_admin_context() + net_manager._setup_network_on_host(ctxt, new_network) + + # Get the new iptables rules that got created from adding a new network + current_lines = [] + new_lines = linux_net.iptables_manager._modify_rules(current_lines, + linux_net.iptables_manager.ipv4['nat'], + table_name='nat') + + # Add the new expected rules to the old ones + expected_lines += ['[0:0] -A %s-snat -s %s -j SNAT --to-source %s -o ' + '%s' % (binary_name, new_network['cidr'], + CONF.routing_source_ip, + CONF.public_interface), + '[0:0] -A %s-POSTROUTING -s %s -d %s/32 -j ACCEPT' + % (binary_name, new_network['cidr'], + CONF.metadata_host), + '[0:0] -A %s-POSTROUTING -s %s -d %s -j ACCEPT' + % (binary_name, new_network['cidr'], + CONF.dmz_cidr[0]), + '[0:0] -A %s-POSTROUTING -s %s -d %s -m conntrack ' + '! --ctstate DNAT -j ACCEPT' % (binary_name, + new_network['cidr'], + new_network['cidr'])] + + # Compare the expected rules (with new network) against the actual ones + for line in expected_lines: + self.assertTrue(line in new_lines) + + def test_flatdhcpmanager_static_fixed_range(self): + """Test FlatDHCPManager NAT rules for fixed_range.""" + # Set the network manager + self.network = network_manager.FlatDHCPManager(host=HOST) + self.network.db = db + + # Test existing behavior: + # CONF.fixed_range is set, NAT based on CONF.fixed_range + self._test_init_host_static_fixed_range(self.network) + + def test_flatdhcpmanager_dynamic_fixed_range(self): + """Test FlatDHCPManager NAT rules for fixed_range.""" + # Set the network manager + self.network = network_manager.FlatDHCPManager(host=HOST) + self.network.db = db + + # Test new behavior: + # CONF.fixed_range is not set, defaults to None + # Determine networks to NAT based on lookup + self._test_init_host_dynamic_fixed_range(self.network) + + def test_vlanmanager_static_fixed_range(self): + """Test VlanManager NAT rules for fixed_range.""" + # Set the network manager + self.network = network_manager.VlanManager(host=HOST) + self.network.db = db + + # Test existing behavior: + # CONF.fixed_range is set, NAT based on CONF.fixed_range + self._test_init_host_static_fixed_range(self.network) + + def test_vlanmanager_dynamic_fixed_range(self): + """Test VlanManager NAT rules for fixed_range.""" + # Set the network manager + self.network = network_manager.VlanManager(host=HOST) + self.network.db = db + + # Test new behavior: + # CONF.fixed_range is not set, defaults to None + # Determine networks to NAT based on lookup + self._test_init_host_dynamic_fixed_range(self.network) + class TestRPCFixedManager(network_manager.RPCAllocateFixedIP, network_manager.NetworkManager): |