Merge "Ensure pools population does not happen until pools are recovered"

This commit is contained in:
Zuul 2019-11-28 10:32:51 +00:00 committed by Gerrit Code Review
commit c0cb699ad1
2 changed files with 88 additions and 7 deletions

View File

@ -160,6 +160,7 @@ class BaseVIFPool(base.VIFPoolDriver):
def __init__(self):
# Note(ltomasbo) Execute the port recycling periodic actions in a
# background thread
self._recovered_pools = False
eventlet.spawn(self._return_ports_to_pool)
def set_vif_driver(self, driver):
@ -216,6 +217,9 @@ class BaseVIFPool(base.VIFPoolDriver):
# REVISIT(ltomasbo): Drop the subnets parameter and get the information
# from the pool_key, which will be required when multi-network is
# supported
if not self._recovered_pools:
LOG.info("Kuryr-controller not yet ready to populate pools.")
raise exceptions.ResourceNotReady(pod)
now = time.time()
last_update = 0
pool_updates = self._last_update.get(pool_key)
@ -350,10 +354,6 @@ class BaseVIFPool(base.VIFPoolDriver):
self._existing_vifs = collections.defaultdict()
self._recyclable_ports = collections.defaultdict()
self._last_update = collections.defaultdict()
# NOTE(ltomasbo): Ensure previously created ports are recovered into
# their respective pools
self._cleanup_leftover_ports()
self._recover_precreated_ports()
def _get_trunks_info(self):
"""Returns information about trunks and their subports.
@ -594,6 +594,14 @@ class NeutronVIFPool(BaseVIFPool):
except KeyError:
LOG.debug('Port already recycled: %s', port_id)
def sync_pools(self):
super(NeutronVIFPool, self).sync_pools()
# NOTE(ltomasbo): Ensure previously created ports are recovered into
# their respective pools
self._cleanup_leftover_ports()
self._recover_precreated_ports()
self._recovered_pools = True
def _recover_precreated_ports(self):
attrs = {'device_owner': kl_const.DEVICE_OWNER}
tags = config.CONF.neutron_defaults.resource_tags
@ -643,7 +651,7 @@ class NeutronVIFPool(BaseVIFPool):
self._create_healthcheck_file()
def delete_network_pools(self, net_id):
if not hasattr(self, '_available_ports_pools'):
if not self._recovered_pools:
LOG.info("Kuryr-controller not yet ready to delete network "
"pools.")
raise exceptions.ResourceNotReady(net_id)
@ -878,6 +886,14 @@ class NestedVIFPool(BaseVIFPool):
parent_port = neutron.show_port(port_id).get('port')
return parent_port['fixed_ips'][0]['ip_address']
def sync_pools(self):
super(NestedVIFPool, self).sync_pools()
# NOTE(ltomasbo): Ensure previously created ports are recovered into
# their respective pools
self._recover_precreated_ports()
self._recovered_pools = True
eventlet.spawn(self._cleanup_leftover_ports)
def _recover_precreated_ports(self):
self._precreated_ports(action='recover')
LOG.info("PORTS POOL: pools updated with pre-created ports")
@ -974,7 +990,7 @@ class NestedVIFPool(BaseVIFPool):
@lockutils.synchronized('return_to_pool_nested')
def populate_pool(self, trunk_ip, project_id, subnets, security_groups):
if not hasattr(self, '_available_ports_pools'):
if not self._recovered_pools:
LOG.info("Kuryr-controller not yet ready to populate pools.")
raise exceptions.ResourceNotReady(trunk_ip)
pool_key = self._get_pool_key(trunk_ip, project_id, None, subnets)
@ -1022,7 +1038,7 @@ class NestedVIFPool(BaseVIFPool):
self._remove_precreated_ports(trunk_ips)
def delete_network_pools(self, net_id):
if not hasattr(self, '_available_ports_pools'):
if not self._recovered_pools:
LOG.info("Kuryr-controller not yet ready to delete network "
"pools.")
raise exceptions.ResourceNotReady(net_id)

View File

@ -196,6 +196,7 @@ class BaseVIFPool(test_base.TestCase):
m_driver._existing_vifs = {}
m_driver._available_ports_pools = {}
m_driver._last_update = {pool_key: {tuple(security_groups): 1}}
m_driver._recovered_pools = True
oslo_cfg.CONF.set_override('ports_pool_min',
5,
@ -211,6 +212,28 @@ class BaseVIFPool(test_base.TestCase):
m_driver._get_pool_size.assert_called_once()
m_driver._drv_vif.request_vifs.assert_called_once()
@ddt.data((neutron_vif.NeutronPodVIFDriver),
(nested_vlan_vif.NestedVlanPodVIFDriver))
def test__populate_pool_not_ready(self, m_vif_driver):
cls = vif_pool.BaseVIFPool
m_driver = mock.MagicMock(spec=cls)
cls_vif_driver = m_vif_driver
vif_driver = mock.MagicMock(spec=cls_vif_driver)
m_driver._drv_vif = vif_driver
pod = mock.sentinel.pod
project_id = str(uuid.uuid4())
subnets = mock.sentinel.subnets
security_groups = 'test-sg'
pool_key = (mock.sentinel.host_addr, project_id)
m_driver._recovered_pools = False
self.assertRaises(exceptions.ResourceNotReady, cls._populate_pool,
m_driver, pool_key, pod, subnets,
tuple(security_groups))
m_driver._drv_vif.request_vifs.assert_not_called()
@mock.patch('time.time', return_value=0)
def test__populate_pool_no_update(self, m_time):
cls = vif_pool.BaseVIFPool
@ -226,6 +249,7 @@ class BaseVIFPool(test_base.TestCase):
15,
group='vif_pool')
m_driver._last_update = {pool_key: {tuple(security_groups): 1}}
m_driver._recovered_pools = True
cls._populate_pool(m_driver, pool_key, pod, subnets,
tuple(security_groups))
@ -256,6 +280,7 @@ class BaseVIFPool(test_base.TestCase):
group='vif_pool')
m_driver._last_update = {pool_key: {tuple(security_groups): 1}}
m_driver._get_pool_size.return_value = 10
m_driver._recovered_pools = True
cls._populate_pool(m_driver, pool_key, pod, subnets,
tuple(security_groups))
@ -933,6 +958,7 @@ class NeutronVIFPool(test_base.TestCase):
m_driver._available_ports_pools = {pool_key: {
tuple(['security_group']): [port_id]}}
m_driver._existing_vifs = {port_id: mock.sentinel.vif}
m_driver._recovered_pools = True
m_driver._get_pool_key_net.return_value = net_id
@ -942,6 +968,21 @@ class NeutronVIFPool(test_base.TestCase):
m_driver._get_pool_key_net.assert_called_once()
neutron.delete_port.assert_called_once_with(port_id)
def test_delete_network_pools_not_ready(self):
cls = vif_pool.NeutronVIFPool
m_driver = mock.MagicMock(spec=cls)
neutron = self.useFixture(k_fix.MockNeutronClient()).client
net_id = mock.sentinel.net_id
m_driver._recovered_pools = False
self.assertRaises(exceptions.ResourceNotReady,
cls.delete_network_pools, m_driver, net_id)
m_driver._trigger_return_to_pool.assert_not_called()
m_driver._get_pool_key_net.assert_not_called()
neutron.delete_port.assert_not_called()
def test_delete_network_pools_missing_port_id(self):
cls = vif_pool.NeutronVIFPool
m_driver = mock.MagicMock(spec=cls)
@ -954,6 +995,7 @@ class NeutronVIFPool(test_base.TestCase):
m_driver._available_ports_pools = {pool_key: {
tuple(['security_group']): [port_id]}}
m_driver._existing_vifs = {}
m_driver._recovered_pools = True
neutron.delete_port.side_effect = n_exc.PortNotFoundClient
m_driver._get_pool_key_net.return_value = net_id
@ -1807,6 +1849,7 @@ class NestedVIFPool(test_base.TestCase):
m_driver._available_ports_pools = {pool_key: {
tuple(['security_group']): [port_id]}}
m_driver._existing_vifs = {port_id: vif}
m_driver._recovered_pools = True
m_driver._get_trunk_id.return_value = trunk_id
m_driver._get_pool_key_net.return_value = net_id
@ -1822,6 +1865,26 @@ class NestedVIFPool(test_base.TestCase):
m_driver._drv_vif._release_vlan_id.assert_called_once_with(vlan_id)
neutron.delete_port.assert_called_once_with(port_id)
def test_delete_network_pools_not_ready(self):
cls = vif_pool.NestedVIFPool
m_driver = mock.MagicMock(spec=cls)
cls_vif_driver = nested_vlan_vif.NestedVlanPodVIFDriver
vif_driver = mock.MagicMock(spec=cls_vif_driver)
m_driver._drv_vif = vif_driver
neutron = self.useFixture(k_fix.MockNeutronClient()).client
net_id = mock.sentinel.net_id
m_driver._recovered_pools = False
self.assertRaises(exceptions.ResourceNotReady,
cls.delete_network_pools, m_driver, net_id)
m_driver._trigger_return_to_pool.assert_not_called()
m_driver._get_pool_key_net.assert_not_called()
m_driver._get_trunk_id.assert_not_called()
m_driver._drv_vif._remove_subports.assert_not_called()
neutron.delete_port.assert_not_called()
def test_delete_network_pools_exception(self):
cls = vif_pool.NestedVIFPool
m_driver = mock.MagicMock(spec=cls)
@ -1841,6 +1904,7 @@ class NestedVIFPool(test_base.TestCase):
m_driver._available_ports_pools = {pool_key: {
tuple(['security_group']): [port_id]}}
m_driver._existing_vifs = {port_id: vif}
m_driver._recovered_pools = True
m_driver._get_trunk_id.return_value = trunk_id
m_driver._get_pool_key_net.return_value = net_id
@ -1877,6 +1941,7 @@ class NestedVIFPool(test_base.TestCase):
m_driver._available_ports_pools = {pool_key: {
tuple(['security_group']): [port_id]}}
m_driver._existing_vifs = {}
m_driver._recovered_pools = True
m_driver._get_trunk_id.return_value = trunk_id
m_driver._get_pool_key_net.return_value = net_id