Merge "Ensure kuryrnet does not perform multiple repopulations"
This commit is contained in:
commit
4c419f4d27
|
@ -114,7 +114,8 @@ class NetworkPolicyDriver(base.NetworkPolicyDriver):
|
||||||
e_rule["security_group_rule"]["id"] = sgr_id
|
e_rule["security_group_rule"]["id"] = sgr_id
|
||||||
# Annotate kuryrnetpolicy CRD with current policy and ruleset
|
# Annotate kuryrnetpolicy CRD with current policy and ruleset
|
||||||
pod_selector = policy['spec'].get('podSelector')
|
pod_selector = policy['spec'].get('podSelector')
|
||||||
driver_utils.patch_kuryr_crd(crd, i_rules, e_rules, pod_selector,
|
driver_utils.patch_kuryrnetworkpolicy_crd(crd, i_rules, e_rules,
|
||||||
|
pod_selector,
|
||||||
np_spec=policy['spec'])
|
np_spec=policy['spec'])
|
||||||
|
|
||||||
if existing_pod_selector != pod_selector:
|
if existing_pod_selector != pod_selector:
|
||||||
|
|
|
@ -442,8 +442,9 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
||||||
e_matched, e_rules = _parse_rules('egress', crd, pod=pod)
|
e_matched, e_rules = _parse_rules('egress', crd, pod=pod)
|
||||||
|
|
||||||
if i_matched or e_matched:
|
if i_matched or e_matched:
|
||||||
driver_utils.patch_kuryr_crd(crd, i_rules,
|
driver_utils.patch_kuryrnetworkpolicy_crd(crd, i_rules,
|
||||||
e_rules, crd_selector)
|
e_rules,
|
||||||
|
crd_selector)
|
||||||
crd_pod_selectors.append(crd_selector)
|
crd_pod_selectors.append(crd_selector)
|
||||||
return crd_pod_selectors
|
return crd_pod_selectors
|
||||||
|
|
||||||
|
@ -463,7 +464,8 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
||||||
egress_rule_list, "egress", pod_ip)
|
egress_rule_list, "egress", pod_ip)
|
||||||
|
|
||||||
if i_matched or e_matched:
|
if i_matched or e_matched:
|
||||||
driver_utils.patch_kuryr_crd(crd, i_rules, e_rules,
|
driver_utils.patch_kuryrnetworkpolicy_crd(crd, i_rules,
|
||||||
|
e_rules,
|
||||||
crd_selector)
|
crd_selector)
|
||||||
crd_pod_selectors.append(crd_selector)
|
crd_pod_selectors.append(crd_selector)
|
||||||
return crd_pod_selectors
|
return crd_pod_selectors
|
||||||
|
@ -492,7 +494,7 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
||||||
egress_rule_list, "egress", ns_name)
|
egress_rule_list, "egress", ns_name)
|
||||||
|
|
||||||
if i_matched or e_matched:
|
if i_matched or e_matched:
|
||||||
driver_utils.patch_kuryr_crd(
|
driver_utils.patch_kuryrnetworkpolicy_crd(
|
||||||
crd, i_rules, e_rules, crd_selector)
|
crd, i_rules, e_rules, crd_selector)
|
||||||
|
|
||||||
def create_namespace_sg_rules(self, namespace):
|
def create_namespace_sg_rules(self, namespace):
|
||||||
|
@ -511,8 +513,9 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
|
||||||
'egress', crd, namespace=namespace)
|
'egress', crd, namespace=namespace)
|
||||||
|
|
||||||
if i_matched or e_matched:
|
if i_matched or e_matched:
|
||||||
driver_utils.patch_kuryr_crd(crd, i_rules,
|
driver_utils.patch_kuryrnetworkpolicy_crd(crd, i_rules,
|
||||||
e_rules, crd_selector)
|
e_rules,
|
||||||
|
crd_selector)
|
||||||
|
|
||||||
def update_namespace_sg_rules(self, namespace):
|
def update_namespace_sg_rules(self, namespace):
|
||||||
LOG.debug("Updating sg rule for namespace: %s",
|
LOG.debug("Updating sg rule for namespace: %s",
|
||||||
|
|
|
@ -218,7 +218,20 @@ def delete_security_group_rule(security_group_rule_id):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def patch_kuryr_crd(crd, i_rules, e_rules, pod_selector, np_spec=None):
|
def patch_kuryrnet_crd(crd, populated=True):
|
||||||
|
kubernetes = clients.get_kubernetes_client()
|
||||||
|
crd_name = crd['metadata']['name']
|
||||||
|
LOG.debug('Patching KuryrNet CRD %s' % crd_name)
|
||||||
|
try:
|
||||||
|
kubernetes.patch_crd('spec', crd['metadata']['selfLink'],
|
||||||
|
{'populated': populated})
|
||||||
|
except k_exc.K8sClientException:
|
||||||
|
LOG.exception('Error updating kuryrnet CRD %s', crd_name)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def patch_kuryrnetworkpolicy_crd(crd, i_rules, e_rules, pod_selector,
|
||||||
|
np_spec=None):
|
||||||
kubernetes = clients.get_kubernetes_client()
|
kubernetes = clients.get_kubernetes_client()
|
||||||
crd_name = crd['metadata']['name']
|
crd_name = crd['metadata']['name']
|
||||||
if not np_spec:
|
if not np_spec:
|
||||||
|
|
|
@ -16,6 +16,8 @@ from oslo_log import log as logging
|
||||||
|
|
||||||
from kuryr_kubernetes import constants
|
from kuryr_kubernetes import constants
|
||||||
from kuryr_kubernetes.controller.drivers import base as drivers
|
from kuryr_kubernetes.controller.drivers import base as drivers
|
||||||
|
from kuryr_kubernetes.controller.drivers import utils as driver_utils
|
||||||
|
from kuryr_kubernetes import exceptions
|
||||||
from kuryr_kubernetes.handlers import k8s_base
|
from kuryr_kubernetes.handlers import k8s_base
|
||||||
from kuryr_kubernetes import utils
|
from kuryr_kubernetes import utils
|
||||||
|
|
||||||
|
@ -42,18 +44,37 @@ class KuryrNetHandler(k8s_base.ResourceEventHandler):
|
||||||
def on_added(self, kuryrnet_crd):
|
def on_added(self, kuryrnet_crd):
|
||||||
namespace = kuryrnet_crd['metadata']['annotations'].get(
|
namespace = kuryrnet_crd['metadata']['annotations'].get(
|
||||||
'namespaceName')
|
'namespaceName')
|
||||||
|
subnet_id = kuryrnet_crd['spec'].get('subnetId')
|
||||||
|
if kuryrnet_crd['spec'].get('populated'):
|
||||||
|
LOG.debug("Subnet %s already populated", subnet_id)
|
||||||
|
return
|
||||||
|
|
||||||
# NOTE(ltomasbo): using namespace name instead of object as it is not
|
# NOTE(ltomasbo): using namespace name instead of object as it is not
|
||||||
# required
|
# required
|
||||||
project_id = self._drv_project.get_project(namespace)
|
project_id = self._drv_project.get_project(namespace)
|
||||||
subnet_id = kuryrnet_crd['spec'].get('subnetId')
|
|
||||||
subnets = self._drv_subnets.get_namespace_subnet(namespace, subnet_id)
|
subnets = self._drv_subnets.get_namespace_subnet(namespace, subnet_id)
|
||||||
sg_id = kuryrnet_crd['spec'].get('sgId', [])
|
sg_id = kuryrnet_crd['spec'].get('sgId', [])
|
||||||
|
|
||||||
nodes = utils.get_nodes_ips()
|
nodes = utils.get_nodes_ips()
|
||||||
|
# NOTE(ltomasbo): Patching the kuryrnet_crd here instead of after
|
||||||
|
# populate_pool method to ensure initial repopulation is not happening
|
||||||
|
# twice upon unexpected problems, such as neutron failing to
|
||||||
|
# transition the ports to ACTIVE or being too slow replying.
|
||||||
|
# In such case, even though the repopulation actions got triggered,
|
||||||
|
# the pools will not get the ports loaded (as they are not ACTIVE)
|
||||||
|
# and new population actions may be triggered if the controller was
|
||||||
|
# restarted before performing the populated=true patching.
|
||||||
|
driver_utils.patch_kuryrnet_crd(kuryrnet_crd, populated=True)
|
||||||
# TODO(ltomasbo): Skip the master node where pods are not usually
|
# TODO(ltomasbo): Skip the master node where pods are not usually
|
||||||
# allocated.
|
# allocated.
|
||||||
for node_ip in nodes:
|
for node_ip in nodes:
|
||||||
LOG.debug("Populating subnet pool %s at node %s", subnet_id,
|
LOG.debug("Populating subnet pool %s at node %s", subnet_id,
|
||||||
node_ip)
|
node_ip)
|
||||||
|
try:
|
||||||
self._drv_vif_pool.populate_pool(node_ip, project_id, subnets,
|
self._drv_vif_pool.populate_pool(node_ip, project_id, subnets,
|
||||||
sg_id)
|
sg_id)
|
||||||
|
except exceptions.ResourceNotReady:
|
||||||
|
# Ensure the repopulation is retriggered if the system was not
|
||||||
|
# yet ready to perform the repopulation actions
|
||||||
|
driver_utils.patch_kuryrnet_crd(kuryrnet_crd, populated=False)
|
||||||
|
raise
|
||||||
|
|
|
@ -185,6 +185,11 @@ class NamespaceHandler(k8s_base.ResourceEventHandler):
|
||||||
kubernetes = clients.get_kubernetes_client()
|
kubernetes = clients.get_kubernetes_client()
|
||||||
net_crd_name = "ns-" + namespace
|
net_crd_name = "ns-" + namespace
|
||||||
spec = {k: v for k, v in net_crd_spec.items()}
|
spec = {k: v for k, v in net_crd_spec.items()}
|
||||||
|
# NOTE(ltomasbo): To know if the subnet has bee populated with pools.
|
||||||
|
# This is only needed by the kuryrnet handler to skip actions. But its
|
||||||
|
# addition does not have any impact if not used
|
||||||
|
spec['populated'] = False
|
||||||
|
|
||||||
net_crd = {
|
net_crd = {
|
||||||
'apiVersion': 'openstack.org/v1',
|
'apiVersion': 'openstack.org/v1',
|
||||||
'kind': 'KuryrNet',
|
'kind': 'KuryrNet',
|
||||||
|
|
|
@ -408,14 +408,14 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
||||||
self.assertEqual(matched, False)
|
self.assertEqual(matched, False)
|
||||||
|
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||||
'patch_kuryr_crd')
|
'patch_kuryrnetworkpolicy_crd')
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||||
'get_kuryrnetpolicy_crds')
|
'get_kuryrnetpolicy_crds')
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||||
'delete_security_group_rule')
|
'delete_security_group_rule')
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_pod_ip')
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.get_pod_ip')
|
||||||
def test_delete_sg_rules(self, m_get_pod_ip, m_delete_sg_rule,
|
def test_delete_sg_rules(self, m_get_pod_ip, m_delete_sg_rule,
|
||||||
m_get_knp_crds, m_patch_kuryr_crd):
|
m_get_knp_crds, m_patch_kuryrnetworkpolicy_crd):
|
||||||
crd = self._crd_with_rule
|
crd = self._crd_with_rule
|
||||||
i_rule = crd['spec'].get('ingressSgRules')[0]
|
i_rule = crd['spec'].get('ingressSgRules')[0]
|
||||||
sgr_id = i_rule['security_group_rule'].get('id')
|
sgr_id = i_rule['security_group_rule'].get('id')
|
||||||
|
@ -435,7 +435,7 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
||||||
m_get_knp_crds.assert_called_once()
|
m_get_knp_crds.assert_called_once()
|
||||||
m_get_pod_ip.assert_called_once_with(pod)
|
m_get_pod_ip.assert_called_once_with(pod)
|
||||||
m_delete_sg_rule.assert_called_once_with(sgr_id)
|
m_delete_sg_rule.assert_called_once_with(sgr_id)
|
||||||
m_patch_kuryr_crd.assert_called_with(
|
m_patch_kuryrnetworkpolicy_crd.assert_called_with(
|
||||||
crd, i_rules, e_rules, crd['spec'].get('podSelector'))
|
crd, i_rules, e_rules, crd['spec'].get('podSelector'))
|
||||||
|
|
||||||
@mock.patch('kuryr_kubernetes.config.CONF')
|
@mock.patch('kuryr_kubernetes.config.CONF')
|
||||||
|
@ -529,13 +529,13 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
||||||
self.assertEqual([str(self._sg_id), str(self._sg_id2)], resp)
|
self.assertEqual([str(self._sg_id), str(self._sg_id2)], resp)
|
||||||
|
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||||
'patch_kuryr_crd')
|
'patch_kuryrnetworkpolicy_crd')
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||||
'delete_security_group_rule')
|
'delete_security_group_rule')
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||||
'get_kuryrnetpolicy_crds')
|
'get_kuryrnetpolicy_crds')
|
||||||
def test_delete_namespace_sg_rule(self, m_get_knp_crd, m_delete_sg_rule,
|
def test_delete_namespace_sg_rule(self, m_get_knp_crd, m_delete_sg_rule,
|
||||||
m_patch_kuryr_crd):
|
m_patch_kuryrnetworkpolicy_crd):
|
||||||
cls = network_policy_security_groups.NetworkPolicySecurityGroupsDriver
|
cls = network_policy_security_groups.NetworkPolicySecurityGroupsDriver
|
||||||
m_driver = mock.MagicMock(spec=cls)
|
m_driver = mock.MagicMock(spec=cls)
|
||||||
i_rule = get_matched_crd_obj()['spec']['ingressSgRules'][0]
|
i_rule = get_matched_crd_obj()['spec']['ingressSgRules'][0]
|
||||||
|
@ -547,17 +547,17 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
||||||
|
|
||||||
m_get_knp_crd.assert_called_once()
|
m_get_knp_crd.assert_called_once()
|
||||||
m_delete_sg_rule.assert_called_once_with(sg_rule_id)
|
m_delete_sg_rule.assert_called_once_with(sg_rule_id)
|
||||||
m_patch_kuryr_crd.assert_called_once()
|
m_patch_kuryrnetworkpolicy_crd.assert_called_once()
|
||||||
|
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||||
'patch_kuryr_crd')
|
'patch_kuryrnetworkpolicy_crd')
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||||
'delete_security_group_rule')
|
'delete_security_group_rule')
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.utils.'
|
||||||
'get_kuryrnetpolicy_crds')
|
'get_kuryrnetpolicy_crds')
|
||||||
def test_delete_namespace_sg_rule_no_match(self, m_get_knp_crd,
|
def test_delete_namespace_sg_rule_no_match(self, m_get_knp_crd,
|
||||||
m_delete_sg_rule,
|
m_delete_sg_rule,
|
||||||
m_patch_kuryr_crd):
|
m_patch_kuryrnetworkpolicy_crd):
|
||||||
cls = network_policy_security_groups.NetworkPolicySecurityGroupsDriver
|
cls = network_policy_security_groups.NetworkPolicySecurityGroupsDriver
|
||||||
m_driver = mock.MagicMock(spec=cls)
|
m_driver = mock.MagicMock(spec=cls)
|
||||||
|
|
||||||
|
@ -568,7 +568,7 @@ class TestNetworkPolicySecurityGroupsDriver(test_base.TestCase):
|
||||||
|
|
||||||
m_get_knp_crd.assert_called_once()
|
m_get_knp_crd.assert_called_once()
|
||||||
m_delete_sg_rule.assert_not_called()
|
m_delete_sg_rule.assert_not_called()
|
||||||
m_patch_kuryr_crd.assert_not_called()
|
m_patch_kuryrnetworkpolicy_crd.assert_not_called()
|
||||||
|
|
||||||
@mock.patch('kuryr_kubernetes.controller.drivers.'
|
@mock.patch('kuryr_kubernetes.controller.drivers.'
|
||||||
'network_policy_security_groups._create_sg_rule')
|
'network_policy_security_groups._create_sg_rule')
|
||||||
|
|
|
@ -16,6 +16,7 @@ import mock
|
||||||
|
|
||||||
from kuryr_kubernetes.controller.drivers import base as drivers
|
from kuryr_kubernetes.controller.drivers import base as drivers
|
||||||
from kuryr_kubernetes.controller.drivers import namespace_subnet as subnet_drv
|
from kuryr_kubernetes.controller.drivers import namespace_subnet as subnet_drv
|
||||||
|
from kuryr_kubernetes.controller.drivers import utils as driver_utils
|
||||||
from kuryr_kubernetes.controller.drivers import vif_pool
|
from kuryr_kubernetes.controller.drivers import vif_pool
|
||||||
from kuryr_kubernetes.controller.handlers import kuryrnet
|
from kuryr_kubernetes.controller.handlers import kuryrnet
|
||||||
from kuryr_kubernetes.tests import base as test_base
|
from kuryr_kubernetes.tests import base as test_base
|
||||||
|
@ -76,8 +77,9 @@ class TestKuryrNetHandler(test_base.TestCase):
|
||||||
self.assertEqual(subnet_driver, handler._drv_subnets)
|
self.assertEqual(subnet_driver, handler._drv_subnets)
|
||||||
self.assertEqual(vif_pool_driver, handler._drv_vif_pool)
|
self.assertEqual(vif_pool_driver, handler._drv_vif_pool)
|
||||||
|
|
||||||
|
@mock.patch.object(driver_utils, 'patch_kuryrnet_crd')
|
||||||
@mock.patch.object(utils, 'get_nodes_ips')
|
@mock.patch.object(utils, 'get_nodes_ips')
|
||||||
def test_on_added(self, m_get_nodes_ips):
|
def test_on_added(self, m_get_nodes_ips, m_patch_kn_crd):
|
||||||
m_get_nodes_ips.return_value = ['node-ip']
|
m_get_nodes_ips.return_value = ['node-ip']
|
||||||
|
|
||||||
kuryrnet.KuryrNetHandler.on_added(self._handler, self._kuryrnet_crd)
|
kuryrnet.KuryrNetHandler.on_added(self._handler, self._kuryrnet_crd)
|
||||||
|
@ -90,3 +92,4 @@ class TestKuryrNetHandler(test_base.TestCase):
|
||||||
self._project_id,
|
self._project_id,
|
||||||
self._subnets,
|
self._subnets,
|
||||||
[])
|
[])
|
||||||
|
m_patch_kn_crd.assert_called_once()
|
||||||
|
|
Loading…
Reference in New Issue