From 2c55108ef44932523b3813a3e639a885c8c56979 Mon Sep 17 00:00:00 2001 From: Tong Liu Date: Wed, 6 Sep 2017 14:26:38 -0700 Subject: [PATCH] NSXv3: Fix L7 rule create/delete base on latest API The platform side finalized the API for LbRule including LbRuleAction, LbRuleCondition and LbRuleMatchType. Also it enforces LB rule deletion that the rule cannot be deleted with if it is still attached to a virtual server. This patch fix these based on platform changes. Change-Id: Id3709c480eb92a7d369851248f302267da0a64ef --- vmware_nsx/services/lbaas/lb_const.py | 2 + .../services/lbaas/nsx_v3/l7policy_mgr.py | 30 +++++++++++++- .../services/lbaas/nsx_v3/l7rule_mgr.py | 39 ++++++++----------- .../unit/services/lbaas/test_nsxv3_driver.py | 11 ++---- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/vmware_nsx/services/lbaas/lb_const.py b/vmware_nsx/services/lbaas/lb_const.py index a465226015..92e4cf8952 100644 --- a/vmware_nsx/services/lbaas/lb_const.py +++ b/vmware_nsx/services/lbaas/lb_const.py @@ -93,6 +93,8 @@ LB_STATS_MAP = {'active_connections': 'current_sessions', LB_SELECT_POOL_ACTION = 'LbSelectPoolAction' LB_HTTP_REDIRECT_ACTION = 'LbHttpRedirectAction' LB_REJECT_ACTION = 'LbHttpRejectAction' +LB_HTTP_REDIRECT_STATUS = '301' +LB_HTTP_REJECT_STATUS = '501' LR_ROUTER_TYPE = 'os-neutron-router-id' LR_PORT_TYPE = 'os-neutron-rport-id' DEFAULT_LB_SIZE = 'SMALL' diff --git a/vmware_nsx/services/lbaas/nsx_v3/l7policy_mgr.py b/vmware_nsx/services/lbaas/nsx_v3/l7policy_mgr.py index 92ec121dce..9f588ae465 100644 --- a/vmware_nsx/services/lbaas/nsx_v3/l7policy_mgr.py +++ b/vmware_nsx/services/lbaas/nsx_v3/l7policy_mgr.py @@ -18,7 +18,9 @@ from oslo_log import helpers as log_helpers from oslo_log import log as logging from vmware_nsx._i18n import _ +from vmware_nsx.db import db as nsx_db from vmware_nsx.services.lbaas import base_mgr +from vmware_nsxlib.v3 import exceptions as nsxlib_exc LOG = logging.getLogger(__name__) @@ -50,4 +52,30 @@ class EdgeL7PolicyManager(base_mgr.Nsxv3LoadbalancerBaseManager): @log_helpers.log_method_call def delete(self, context, policy): - self._l7policy_action(context, policy, 'delete', delete=True) + lb_id = policy.listener.loadbalancer_id + vs_client = self.core_plugin.nsxlib.load_balancer.virtual_server + rule_client = self.core_plugin.nsxlib.load_balancer.rule + for rule in policy.rules: + binding = nsx_db.get_nsx_lbaas_l7rule_binding( + context.session, lb_id, policy.id, rule.id) + if binding: + vs_id = binding['lb_vs_id'] + rule_id = binding['lb_rule_id'] + try: + # Update virtual server to remove lb rule + vs_client.remove_rule(vs_id, rule_id) + rule_client.delete(rule_id) + except nsxlib_exc.ResourceNotFound: + LOG.warning('LB rule %(rule)s is not found on NSX', + {'rule': rule_id}) + except nsxlib_exc.ManagerError: + self.lbv2_driver.l7policy.failed_completion( + context, policy) + msg = (_('Failed to delete lb rule: %(rule)s') % + {'rule': rule.id}) + raise n_exc.BadRequest(resource='lbaas-l7rule-delete', + msg=msg) + nsx_db.delete_nsx_lbaas_l7rule_binding( + context.session, lb_id, policy.id, rule.id) + self.lbv2_driver.l7policy.successful_completion( + context, policy, delete=True) diff --git a/vmware_nsx/services/lbaas/nsx_v3/l7rule_mgr.py b/vmware_nsx/services/lbaas/nsx_v3/l7rule_mgr.py index 40e329160f..fe2741b301 100644 --- a/vmware_nsx/services/lbaas/nsx_v3/l7rule_mgr.py +++ b/vmware_nsx/services/lbaas/nsx_v3/l7rule_mgr.py @@ -93,9 +93,11 @@ class EdgeL7RuleManager(base_mgr.Nsxv3LoadbalancerBaseManager): msg=msg) elif l7policy.action == lb_const.L7_POLICY_ACTION_REDIRECT_TO_URL: actions = [{'type': lb_const.LB_HTTP_REDIRECT_ACTION, - 'redirect_rul': l7policy.redirect_url}] + 'redirect_status': lb_const.LB_HTTP_REDIRECT_STATUS, + 'redirect_url': l7policy.redirect_url}] elif l7policy.action == lb_const.L7_POLICY_ACTION_REJECT: - actions = [{'type': lb_const.LB_REJECT_ACTION}] + actions = [{'type': lb_const.LB_REJECT_ACTION, + 'reply_status': lb_const.LB_HTTP_REJECT_STATUS}] else: msg = (_('Invalid l7policy action: %(action)s') % {'action': l7policy.action}) @@ -179,24 +181,7 @@ class EdgeL7RuleManager(base_mgr.Nsxv3LoadbalancerBaseManager): vs_id = binding['lb_vs_id'] rule_id = binding['lb_rule_id'] try: - rule_client.delete(rule_id) - except nsx_exc.NsxResourceNotFound: - msg = (_("LB rule cannot be found on nsx: %(rule)s") % - {'rule': rule_id}) - raise n_exc.BadRequest(resource='lbaas-l7rule-delete', - msg=msg) - except nsxlib_exc.ManagerError: - self.lbv2_driver.l7rule.failed_completion(context, - rule) - msg = (_('Failed to delete lb rule: %(rule)s') % - {'rule': rule.id}) - raise n_exc.BadRequest(resource='lbaas-l7rule-delete', - msg=msg) - try: - lb_vs = vs_client.get(vs_id) - if 'rule_ids' in lb_vs and rule_id in lb_vs['rule_ids']: - lb_vs['rule_ids'].remove(rule_id) - vs_client.update(vs_id, lb_vs) + vs_client.remove_rule(vs_id, rule_id) except nsx_exc.NsxResourceNotFound: msg = (_("virtual server cannot be found on nsx: %(vs)s") % {'vs': vs_id}) @@ -209,9 +194,19 @@ class EdgeL7RuleManager(base_mgr.Nsxv3LoadbalancerBaseManager): '%(vs)s') % {'rule': rule_id, 'vs': vs_id}) raise n_exc.BadRequest(resource='lbaas-l7rule-delete', msg=msg) - + try: + rule_client.delete(rule_id) + except nsx_exc.NsxResourceNotFound: + LOG.warning("LB rule cannot be found on nsx: %(rule)s", + {'rule': rule_id}) + except nsxlib_exc.ManagerError: + self.lbv2_driver.l7rule.failed_completion(context, + rule) + msg = (_('Failed to delete lb rule: %(rule)s') % + {'rule': rule.id}) + raise n_exc.BadRequest(resource='lbaas-l7rule-delete', + msg=msg) nsx_db.delete_nsx_lbaas_l7rule_binding( context.session, lb_id, rule.l7policy_id, rule.id) - self.lbv2_driver.l7rule.successful_completion(context, rule, delete=True) diff --git a/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py b/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py index e971ffe340..67b4224995 100644 --- a/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py +++ b/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py @@ -656,23 +656,18 @@ class TestEdgeLbaasV2L7Rule(BaseTestEdgeLbaasV2): def test_delete_pool_without_members(self): with mock.patch.object(nsx_db, 'get_nsx_lbaas_l7rule_binding', ) as mock_get_l7rule_binding, \ + mock.patch.object(self.vs_client, 'remove_rule' + ) as mock_remove_rule, \ mock.patch.object(self.rule_client, 'delete', ) as mock_delete_rule, \ - mock.patch.object(self.vs_client, 'get', - ) as mock_get_vs, \ - mock.patch.object(self.vs_client, 'update', - ) as mock_update_vs, \ mock.patch.object(nsx_db, 'delete_nsx_lbaas_l7rule_binding', ) as mock_delete_l7rule_binding: mock_get_l7rule_binding.return_value = L7RULE_BINDING - mock_get_vs.return_value = {'id': LB_VS_ID, - 'rule_ids': [LB_RULE_ID]} self.edge_driver.l7rule.delete(self.context, self.l7rule) + mock_remove_rule.assert_called_with(LB_VS_ID, LB_RULE_ID) mock_delete_rule.assert_called_with(LB_RULE_ID) - mock_update_vs.assert_called_with(LB_VS_ID, {'id': LB_VS_ID, - 'rule_ids': []}) mock_delete_l7rule_binding.assert_called_with( self.context.session, LB_ID, L7POLICY_ID, L7RULE_ID)