Commit 879380a3 authored by Carlos Goncalves's avatar Carlos Goncalves

Fix setting of VIP QoS policy

Load balancers were going in to ERROR when updating vip_qos_policy_id in
two different cases:

- QoS extension enabled: the VIP DB data model was incorrectly
  constructed ('vip_qos_policy_id' where it should have been
  'qos_policy_id')
- QoS extension disabled: setting an UUID or None would fail in the LB
  update flow as the extension is disabled, and the API would return
  HTTP 202 to the user.

Conflicts:
    octavia/api/v2/controllers/load_balancer.py
    octavia/tests/unit/api/drivers/amphora_driver/test_amphora_driver.py

Story: 2004602
Task: 28512

Change-Id: Ie974afa52fe70cbab72b7e7f75bf7ee1015e148c
(cherry picked from commit e0c45ce4d288aa0a8c855754245cd3949e54fa3d)
(cherry picked from commit 86e3eb4c)
(cherry picked from commit 4d9b818b73e256645c3964e311c225f12f3aa0ea)
parent 9808720b
......@@ -444,11 +444,12 @@ class LoadBalancersController(base.BaseController):
self._auth_validate_action(context, db_lb.project_id,
constants.RBAC_PUT)
if (load_balancer.vip_qos_policy_id and
not isinstance(load_balancer.vip_qos_policy_id,
wtypes.UnsetType) and
db_lb.vip.qos_policy_id != load_balancer.vip_qos_policy_id):
validate.qos_policy_exists(load_balancer.vip_qos_policy_id)
if not isinstance(load_balancer.vip_qos_policy_id, wtypes.UnsetType):
network_driver = utils.get_network_driver()
validate.qos_extension_enabled(network_driver)
if load_balancer.vip_qos_policy_id is not None:
if db_lb.vip.qos_policy_id != load_balancer.vip_qos_policy_id:
validate.qos_policy_exists(load_balancer.vip_qos_policy_id)
self._test_lb_status(context.session, id)
try:
LOG.info("Sending updated Load Balancer %s to the handler", id)
......
......@@ -258,6 +258,7 @@ def subnet_exists(subnet_id):
def qos_policy_exists(qos_policy_id):
network_driver = utils.get_network_driver()
qos_extension_enabled(network_driver)
try:
qos_policy = network_driver.get_qos_policy(qos_policy_id)
except Exception:
......@@ -266,6 +267,12 @@ def qos_policy_exists(qos_policy_id):
return qos_policy
def qos_extension_enabled(network_driver):
if not network_driver.qos_enabled():
raise exceptions.ValidationException(detail=_(
"VIP QoS policy is not allowed in this deployment."))
def network_exists_optionally_contains_subnet(network_id, subnet_id=None):
"""Raises an exception when a network does not exist.
......
......@@ -322,3 +322,10 @@ class AbstractNetworkDriver(object):
:raises PortNotFound: Port was not found by neutron.
"""
pass
@abc.abstractmethod
def qos_enabled(self):
"""Whether QoS is enabled
:return: Boolean
"""
......@@ -27,6 +27,7 @@ from octavia.network.drivers.neutron import utils
LOG = logging.getLogger(__name__)
DNS_INT_EXT_ALIAS = 'dns-integration'
SEC_GRP_EXT_ALIAS = 'security-group'
QOS_EXT_ALIAS = 'qos'
CONF = cfg.CONF
......@@ -46,6 +47,7 @@ class BaseNeutronDriver(base.AbstractNetworkDriver):
self.sec_grp_enabled = self._check_extension_enabled(SEC_GRP_EXT_ALIAS)
self.dns_integration_enabled = self._check_extension_enabled(
DNS_INT_EXT_ALIAS)
self._qos_enabled = self._check_extension_enabled(QOS_EXT_ALIAS)
self.project_id = self.neutron_client.get_auth_info().get(
'auth_tenant_id')
......@@ -248,3 +250,6 @@ class BaseNeutronDriver(base.AbstractNetworkDriver):
def get_qos_policy(self, qos_policy_id):
return self._get_resource('qos_policy', qos_policy_id)
def qos_enabled(self):
return self._qos_enabled
......@@ -26,6 +26,7 @@ class NoopManager(object):
def __init__(self):
super(NoopManager, self).__init__()
self.networkconfigconfig = {}
self._qos_extension_enabled = True
def allocate_vip(self, loadbalancer):
LOG.debug("Network %s no-op, allocate_vip loadbalancer %s",
......@@ -220,6 +221,9 @@ class NoopManager(object):
self.networkconfigconfig[(qos_id, port_id)] = (
qos_id, port_id, 'apply_qos_on_port')
def qos_enabled(self):
return self._qos_extension_enabled
class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
def __init__(self):
......@@ -289,3 +293,6 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
def apply_qos_on_port(self, qos_id, port_id):
self.driver.apply_qos_on_port(qos_id, port_id)
def qos_enabled(self):
return self.driver.qos_enabled()
......@@ -1300,6 +1300,20 @@ class TestLoadBalancer(base.BaseAPITest):
self.put(self.LB_PATH.format(lb_id=lb_dict.get('id')),
lb_json, status=400)
def test_update_with_qos_ext_disabled(self):
project_id = uuidutils.generate_uuid()
lb = self.create_load_balancer(uuidutils.generate_uuid(),
name='lb1',
project_id=project_id)
lb_dict = lb.get(self.root_tag)
self.set_lb_status(lb_dict.get('id'))
vip_qos_policy_id = uuidutils.generate_uuid()
lb_json = self._build_body({'vip_qos_policy_id': vip_qos_policy_id})
with mock.patch("octavia.network.drivers.noop_driver.driver"
".NoopManager.qos_enabled", return_value=False):
self.put(self.LB_PATH.format(lb_id=lb_dict.get('id')),
lb_json, status=400)
def test_update_bad_lb_id(self):
path = self.LB_PATH.format(lb_id='SEAN-CONNERY')
self.put(path, body={}, status=404)
......
......@@ -374,6 +374,18 @@ class TestValidations(base.TestCase):
validate.qos_policy_exists,
qos_policy_id)
def test_qos_extension_enabled(self):
network_driver = mock.Mock()
network_driver.qos_enabled.return_value = True
self.assertIsNone(validate.qos_extension_enabled(network_driver))
def test_qos_extension_disabled(self):
network_driver = mock.Mock()
network_driver.qos_enabled.return_value = False
self.assertRaises(exceptions.ValidationException,
validate.qos_extension_enabled,
network_driver)
def test_check_session_persistence(self):
valid_cookie_name_dict = {'type': 'APP_COOKIE',
'cookie_name': 'chocolate_chip'}
......
---
fixes:
- Fixed an issue where trying to set a QoS policy on a VIP while the QoS
extension is disabled would bring the load balancer to ERROR. Should the
QoS extension be disabled, the API will now return HTTP 400 to the user.
- Fixed an issue where setting a QoS policy on the VIP would bring the load
balancer to ERROR when the QoS extension is enabled.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment