Merge "Update metadata proxy when subnet add/delete"

This commit is contained in:
Jenkins 2016-11-08 18:00:39 +00:00 committed by Gerrit Code Review
commit 475241834d
5 changed files with 68 additions and 24 deletions

View File

@ -271,14 +271,10 @@ class DhcpAgent(manager.Manager):
if not network.admin_state_up:
return
enable_metadata = self.dhcp_driver_cls.should_enable_metadata(
self.conf, network)
dhcp_network_enabled = False
for subnet in network.subnets:
if subnet.enable_dhcp:
if self.call_driver('enable', network):
dhcp_network_enabled = True
self.update_isolated_metadata_proxy(network)
self.cache.put(network)
# After enabling dhcp for network, mark all existing
# ports as ready. So that the status of ports which are
@ -286,18 +282,6 @@ class DhcpAgent(manager.Manager):
self.dhcp_ready_ports |= {p.id for p in network.ports}
break
if enable_metadata and dhcp_network_enabled:
for subnet in network.subnets:
if subnet.ip_version == 4 and subnet.enable_dhcp:
self.enable_isolated_metadata_proxy(network)
break
elif (not self.conf.force_metadata and
not self.conf.enable_isolated_metadata):
# In the case that the dhcp agent ran with metadata enabled,
# and dhcp agent now starts with metadata disabled, check and
# delete any metadata_proxy.
self.disable_isolated_metadata_proxy(network)
def disable_dhcp_helper(self, network_id):
"""Disable DHCP for a network known to the agent."""
network = self.cache.get_network_by_id(network_id)
@ -337,6 +321,9 @@ class DhcpAgent(manager.Manager):
elif self.call_driver('restart', network):
self.cache.put(network)
# Update the metadata proxy after the dhcp driver has been updated
self.update_isolated_metadata_proxy(network)
@utils.synchronized('dhcp-agent')
def network_create_end(self, context, payload):
"""Handle the network.create.end notification event."""
@ -436,6 +423,20 @@ class DhcpAgent(manager.Manager):
else:
self.call_driver('reload_allocations', network)
def update_isolated_metadata_proxy(self, network):
"""Spawn or kill metadata proxy.
According to return from driver class, spawn or kill the metadata
proxy process. Spawn an existing metadata proxy or kill a nonexistent
metadata proxy will just silently return.
"""
should_enable_metadata = self.dhcp_driver_cls.should_enable_metadata(
self.conf, network)
if should_enable_metadata:
self.enable_isolated_metadata_proxy(network)
else:
self.disable_isolated_metadata_proxy(network)
def enable_isolated_metadata_proxy(self, network):
# The proxy might work for either a single network

View File

@ -1070,7 +1070,9 @@ class Dnsmasq(DhcpLocalProcess):
with 3rd party backends.
"""
if conf.force_metadata:
return True
# Only ipv4 subnet, with dhcp enabled, will use metadata proxy.
return any(s for s in network.subnets
if s.ip_version == 4 and s.enable_dhcp)
if conf.enable_metadata_network and conf.enable_isolated_metadata:
# check if the network has a metadata subnet
@ -1083,7 +1085,10 @@ class Dnsmasq(DhcpLocalProcess):
return False
isolated_subnets = cls.get_isolated_subnets(network)
return any(isolated_subnets[subnet.id] for subnet in network.subnets)
# Only ipv4 isolated subnet, which has dhcp enabled, will use
# metadata proxy.
return any(isolated_subnets[s.id] for s in network.subnets
if s.ip_version == 4 and s.enable_dhcp)
class DeviceManager(object):

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import os.path
import eventlet
@ -314,6 +315,45 @@ class DHCPAgentOVSTestCase(DHCPAgentOVSTestFramework):
sleep=0.1,
exception=RuntimeError("Stale metadata proxy didn't get killed"))
def _test_metadata_proxy_spawn_kill_with_subnet_create_delete(self):
network = self.network_dict_for_dhcp(ip_version=6)
self.configure_dhcp_for_network(network=network)
pm = self._get_metadata_proxy_process(network)
# A newly created network with ipv6 subnet will not have metadata proxy
self.assertFalse(pm.active)
new_network = copy.deepcopy(network)
dhcp_enabled_ipv4_subnet = self.create_subnet_dict(network.id)
new_network.subnets.append(dhcp_enabled_ipv4_subnet)
self.mock_plugin_api.get_network_info.return_value = new_network
self.agent.refresh_dhcp_helper(network.id)
# Metadata proxy should be spawned for the newly added subnet
common_utils.wait_until_true(
lambda: pm.active,
timeout=5,
sleep=0.1,
exception=RuntimeError("Metadata proxy didn't spawn"))
self.mock_plugin_api.get_network_info.return_value = network
self.agent.refresh_dhcp_helper(network.id)
# Metadata proxy should be killed because network doesn't need it.
common_utils.wait_until_true(
lambda: not pm.active,
timeout=5,
sleep=0.1,
exception=RuntimeError("Metadata proxy didn't get killed"))
def test_enable_isolated_metadata_for_subnet_create_delete(self):
self.conf.set_override('force_metadata', False)
self.conf.set_override('enable_isolated_metadata', True)
self._test_metadata_proxy_spawn_kill_with_subnet_create_delete()
def test_force_metadata_for_subnet_create_delete(self):
self.conf.set_override('force_metadata', True)
self.conf.set_override('enable_isolated_metadata', False)
self._test_metadata_proxy_spawn_kill_with_subnet_create_delete()
def test_notify_port_ready_after_enable_dhcp(self):
network = self.network_dict_for_dhcp()
dhcp_port = self.create_port_dict(

View File

@ -667,12 +667,10 @@ class TestDhcpAgentEventHandler(base.BaseTestCase):
self.external_process.assert_has_calls([
self._process_manager_constructor_call(),
mock.call().enable()])
elif not enable_isolated_metadata:
else:
self.external_process.assert_has_calls([
self._process_manager_constructor_call(ns=None),
mock.call().disable()])
else:
self.assertFalse(self.external_process.call_count)
def test_enable_dhcp_helper_enable_metadata_isolated_network(self):
self._enable_dhcp_helper(isolated_network,

View File

@ -2148,8 +2148,8 @@ class TestDnsmasq(TestBase):
def test_should_force_metadata_returns_true(self):
self.conf.set_override("force_metadata", True)
self.assertTrue(dhcp.Dnsmasq.should_enable_metadata(self.conf,
mock.ANY))
self.assertTrue(dhcp.Dnsmasq.should_enable_metadata(
self.conf, FakeDualNetworkDualDHCP()))
def _test__generate_opts_per_subnet_helper(self, config_opts,
expected_mdt_ip):