Merge "[L3][QoS] L3 agent QoS extension to handle duplicated FIPs"
This commit is contained in:
commit
bcdabad1c8
@ -53,9 +53,12 @@ IP_DEFAULT_BURST = 0
|
||||
class RateLimitMaps(object):
|
||||
|
||||
def __init__(self, lock_name):
|
||||
self.qos_policy_resources = collections.defaultdict(dict)
|
||||
# qos_policy_2_resources = {qos_id_1: {res_1, res_2, res_3, ...} }
|
||||
self.qos_policy_2_resources = collections.defaultdict(set)
|
||||
# known_policies = {qos_id_1: qos_policy_1, ...}
|
||||
self.known_policies = {}
|
||||
self.resource_policies = {}
|
||||
# resource_2_qos_policies = {res1: qos_id_1, ...}
|
||||
self.resource_2_qos_policies = {}
|
||||
self.lock_name = lock_name
|
||||
|
||||
def update_policy(self, policy):
|
||||
@ -78,7 +81,7 @@ class RateLimitMaps(object):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _get_resources():
|
||||
return self.qos_policy_resources[policy.id].values()
|
||||
return self.qos_policy_2_resources[policy.id]
|
||||
|
||||
return _get_resources()
|
||||
|
||||
@ -86,7 +89,7 @@ class RateLimitMaps(object):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _get_resource_policy():
|
||||
policy_id = self.resource_policies.get(resource)
|
||||
policy_id = self.resource_2_qos_policies.get(resource)
|
||||
return self.known_policies.get(policy_id)
|
||||
|
||||
return _get_resource_policy()
|
||||
@ -99,13 +102,13 @@ class RateLimitMaps(object):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _set_resource_policy():
|
||||
policy_id = self.resource_policies.get(resource)
|
||||
policy_id = self.resource_2_qos_policies.get(resource)
|
||||
old_policy = self.known_policies.get(policy_id)
|
||||
self.known_policies[policy.id] = policy
|
||||
self.resource_policies[resource] = policy.id
|
||||
self.qos_policy_resources[policy.id][resource] = resource
|
||||
self.resource_2_qos_policies[resource] = policy.id
|
||||
self.qos_policy_2_resources[policy.id].add(resource)
|
||||
if old_policy and old_policy.id != policy.id:
|
||||
del self.qos_policy_resources[old_policy.id][resource]
|
||||
self.qos_policy_2_resources[old_policy.id].remove(resource)
|
||||
|
||||
_set_resource_policy()
|
||||
|
||||
@ -117,22 +120,21 @@ class RateLimitMaps(object):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _clean_by_resource():
|
||||
if resource in self.resource_policies:
|
||||
del self.resource_policies[resource]
|
||||
for (qos_policy_id,
|
||||
res_dict) in self.qos_policy_resources.items():
|
||||
if resource in res_dict:
|
||||
del res_dict[resource]
|
||||
if not res_dict:
|
||||
self._clean_policy_info(qos_policy_id)
|
||||
return
|
||||
LOG.debug("L3 QoS extension did not have "
|
||||
"information on floating IP %s", resource)
|
||||
qos_policy_id = self.resource_2_qos_policies.pop(resource, None)
|
||||
if not qos_policy_id:
|
||||
LOG.debug("L3 QoS extension did not have "
|
||||
"information on floating IP %s", resource)
|
||||
return
|
||||
|
||||
resources = self.qos_policy_2_resources[qos_policy_id]
|
||||
resources.discard(resource)
|
||||
if not resources:
|
||||
self._clean_policy_info(qos_policy_id)
|
||||
|
||||
_clean_by_resource()
|
||||
|
||||
def _clean_policy_info(self, qos_policy_id):
|
||||
del self.qos_policy_resources[qos_policy_id]
|
||||
del self.qos_policy_2_resources[qos_policy_id]
|
||||
del self.known_policies[qos_policy_id]
|
||||
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import collections
|
||||
|
||||
from neutron_lib.agent import l3_extension
|
||||
from neutron_lib import constants
|
||||
from neutron_lib.services.qos import constants as qos_consts
|
||||
@ -28,6 +30,8 @@ from neutron.common import coordination
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
FipResource = collections.namedtuple('FipResource', 'id ip_address')
|
||||
|
||||
|
||||
class RouterFipRateLimitMaps(qos_base.RateLimitMaps):
|
||||
LOCK_NAME = "fip-qos-cache"
|
||||
@ -35,14 +39,16 @@ class RouterFipRateLimitMaps(qos_base.RateLimitMaps):
|
||||
def __init__(self):
|
||||
"""Initialize RouterFipRateLimitMaps
|
||||
|
||||
The router_floating_ips will be:
|
||||
router_floating_ips = {
|
||||
router_id_1: set(fip1, fip2),
|
||||
router_id_2: set(), # default
|
||||
}
|
||||
"_router_2_fips" stores the FIP resources (``FipResource`` tuple) per
|
||||
router. The "_fips_2_router" dictionary stores the reverse lookup info.
|
||||
_router_2_fips = {router_id_1: {fip_res_1, fip_res_2, ...},
|
||||
router_id_2: {fip_res_3, fip_res_4, ...}, ... }
|
||||
_fips_2_router = {fip_res_1: router_id_1,
|
||||
fip_res_2: router_id_1,
|
||||
fip_res_3: router_id_2, ... }
|
||||
"""
|
||||
self.router_floating_ips = {}
|
||||
|
||||
self._router_2_fips = {}
|
||||
self._fips_2_router = {}
|
||||
"""
|
||||
The rate limits dict will be:
|
||||
xxx_ratelimits = {
|
||||
@ -56,64 +62,89 @@ class RouterFipRateLimitMaps(qos_base.RateLimitMaps):
|
||||
self.egress_ratelimits = {}
|
||||
super(RouterFipRateLimitMaps, self).__init__(self.LOCK_NAME)
|
||||
|
||||
def find_fip_router_id(self, fip):
|
||||
def get_router_id_by_fip(self, fip_res):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _find_fip_router_id():
|
||||
for router_id, ips in self.router_floating_ips.items():
|
||||
if fip in ips:
|
||||
return router_id
|
||||
def _find_router_id_by_fip_id():
|
||||
return self._fips_2_router.get(fip_res)
|
||||
|
||||
return _find_fip_router_id()
|
||||
return _find_router_id_by_fip_id()
|
||||
|
||||
def get_router_floating_ips(self, router_id):
|
||||
def get_fips_by_router_id(self, router_id):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _get_router_floating_ips():
|
||||
return self.router_floating_ips.pop(
|
||||
router_id, [])
|
||||
def _get_fips_by_router_id():
|
||||
return self._router_2_fips.get(router_id, set([]))
|
||||
|
||||
return _get_router_floating_ips()
|
||||
return _get_fips_by_router_id()
|
||||
|
||||
def remove_fip_ratelimit_cache(self, direction, fip):
|
||||
def set_fips(self, router_id, fips):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _set_fips():
|
||||
self._router_2_fips[router_id] = fips
|
||||
for fip_res in fips:
|
||||
self._fips_2_router[fip_res] = router_id
|
||||
|
||||
if not isinstance(fips, set):
|
||||
fips = set(fips)
|
||||
return _set_fips()
|
||||
|
||||
def delete_fips(self, fips):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _delete_fips():
|
||||
router_ids = set([])
|
||||
for fip_res in fips:
|
||||
router_id = self._fips_2_router.pop(fip_res, None)
|
||||
if router_id:
|
||||
router_ids.add(router_id)
|
||||
|
||||
for router_id in router_ids:
|
||||
stored_fips = self._router_2_fips.pop(router_id)
|
||||
current_fips = stored_fips - set(fips)
|
||||
if current_fips:
|
||||
self._router_2_fips[router_id] = current_fips
|
||||
|
||||
if not isinstance(fips, set):
|
||||
fips = set(fips)
|
||||
return _delete_fips()
|
||||
|
||||
def remove_fip_ratelimit_cache(self, direction, fip_id):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _remove_fip_ratelimit_cache():
|
||||
rate_limits = getattr(self, direction + "_ratelimits")
|
||||
rate_limits.pop(fip, None)
|
||||
rate_limits.pop(fip_id, None)
|
||||
|
||||
_remove_fip_ratelimit_cache()
|
||||
|
||||
def set_fip_ratelimit_cache(self, direction, fip, rate, burst):
|
||||
def set_fip_ratelimit_cache(self, direction, fip_id, rate, burst):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _set_fip_ratelimit_cache():
|
||||
rate_limits = getattr(self, direction + "_ratelimits")
|
||||
rate_limits[fip] = (rate, burst)
|
||||
rate_limits[fip_id] = (rate, burst)
|
||||
|
||||
_set_fip_ratelimit_cache()
|
||||
|
||||
def get_fip_ratelimit_cache(self, direction, fip):
|
||||
def get_fip_ratelimit_cache(self, direction, fip_id):
|
||||
|
||||
@lockutils.synchronized(self.lock_name)
|
||||
def _get_fip_ratelimit_cache():
|
||||
rate_limits = getattr(self, direction + "_ratelimits")
|
||||
rate, burst = rate_limits.get(fip, (qos_base.IP_DEFAULT_RATE,
|
||||
qos_base.IP_DEFAULT_BURST))
|
||||
rate, burst = rate_limits.get(fip_id, (qos_base.IP_DEFAULT_RATE,
|
||||
qos_base.IP_DEFAULT_BURST))
|
||||
return rate, burst
|
||||
|
||||
return _get_fip_ratelimit_cache()
|
||||
|
||||
def remove_fip_all_cache(self, fip):
|
||||
for direction in constants.VALID_DIRECTIONS:
|
||||
self.remove_fip_ratelimit_cache(direction, fip)
|
||||
self.clean_by_resource(fip)
|
||||
|
||||
def clean_router_all_fip_cache(self, router_id):
|
||||
floating_ips = self.router_floating_ips.pop(
|
||||
router_id, [])
|
||||
for fip in floating_ips:
|
||||
self.remove_fip_all_cache(fip)
|
||||
for fip_res in self._router_2_fips.pop(router_id, []):
|
||||
self._fips_2_router.pop(fip_res, None)
|
||||
for direction in constants.VALID_DIRECTIONS:
|
||||
self.remove_fip_ratelimit_cache(direction, fip_res.id)
|
||||
self.clean_by_resource(fip_res)
|
||||
|
||||
|
||||
class FipQosAgentExtension(qos_base.L3QosAgentExtensionBase,
|
||||
@ -133,26 +164,28 @@ class FipQosAgentExtension(qos_base.L3QosAgentExtensionBase,
|
||||
|
||||
def _process_update_policy(self, qos_policy):
|
||||
old_qos_policy = self.fip_qos_map.get_policy(qos_policy.id)
|
||||
if old_qos_policy:
|
||||
if self._policy_rules_modified(old_qos_policy, qos_policy):
|
||||
for fip in self.fip_qos_map.get_resources(qos_policy):
|
||||
router_id = self.fip_qos_map.find_fip_router_id(fip)
|
||||
router_info = self._get_router_info(router_id)
|
||||
if not router_info:
|
||||
continue
|
||||
device = self._get_rate_limit_ip_device(router_info)
|
||||
dvr_fip_device = self._get_dvr_fip_device(router_info)
|
||||
if not device and not dvr_fip_device:
|
||||
LOG.debug("Router %s does not have a floating IP "
|
||||
"related device, skipping.", router_id)
|
||||
continue
|
||||
rates = self.get_policy_rates(qos_policy)
|
||||
if device:
|
||||
self.process_ip_rates(fip, device, rates)
|
||||
if dvr_fip_device:
|
||||
self.process_ip_rates(
|
||||
fip, dvr_fip_device, rates, with_cache=False)
|
||||
self.fip_qos_map.update_policy(qos_policy)
|
||||
if not old_qos_policy:
|
||||
return
|
||||
|
||||
if self._policy_rules_modified(old_qos_policy, qos_policy):
|
||||
for fip_res in self.fip_qos_map.get_resources(qos_policy):
|
||||
router_id = self.fip_qos_map.get_router_id_by_fip(fip_res)
|
||||
router_info = self._get_router_info(router_id)
|
||||
if not router_info:
|
||||
continue
|
||||
device = self._get_rate_limit_ip_device(router_info)
|
||||
dvr_fip_device = self._get_dvr_fip_device(router_info)
|
||||
if not device and not dvr_fip_device:
|
||||
LOG.debug("Router %s does not have a floating IP "
|
||||
"related device, skipping.", router_id)
|
||||
continue
|
||||
rates = self.get_policy_rates(qos_policy)
|
||||
if device:
|
||||
self.process_ip_rates(fip_res, device, rates)
|
||||
if dvr_fip_device:
|
||||
self.process_ip_rates(
|
||||
fip_res, dvr_fip_device, rates, with_cache=False)
|
||||
self.fip_qos_map.update_policy(qos_policy)
|
||||
|
||||
@coordination.synchronized('qos-floating-ip-{ip}')
|
||||
def process_ip_rate_limit(self, ip, direction,
|
||||
@ -196,16 +229,16 @@ class FipQosAgentExtension(qos_base.L3QosAgentExtensionBase,
|
||||
namespace = router_info.get_gw_ns_name()
|
||||
return ip_lib.IPDevice(name, namespace=namespace)
|
||||
|
||||
def _remove_fip_rate_limit(self, device, fip_ip):
|
||||
def _remove_fip_rate_limit(self, device, fip_res):
|
||||
tc_wrapper = self._get_tc_wrapper(device)
|
||||
for direction in constants.VALID_DIRECTIONS:
|
||||
if device.exists():
|
||||
tc_wrapper.clear_ip_rate_limit(direction, fip_ip)
|
||||
self.fip_qos_map.remove_fip_ratelimit_cache(direction, fip_ip)
|
||||
tc_wrapper.clear_ip_rate_limit(direction, fip_res.ip_address)
|
||||
self.fip_qos_map.remove_fip_ratelimit_cache(direction, fip_res.id)
|
||||
|
||||
def get_fip_qos_rates(self, context, fip, policy_id):
|
||||
def get_fip_qos_rates(self, context, fip_res, policy_id):
|
||||
if policy_id is None:
|
||||
self.fip_qos_map.clean_by_resource(fip)
|
||||
self.fip_qos_map.clean_by_resource(fip_res)
|
||||
# process_ip_rate_limit will treat value 0 as
|
||||
# cleaning the tc filters if exits or no action.
|
||||
return {constants.INGRESS_DIRECTION: {
|
||||
@ -216,36 +249,36 @@ class FipQosAgentExtension(qos_base.L3QosAgentExtensionBase,
|
||||
"burst": qos_base.IP_DEFAULT_BURST}}
|
||||
policy = self.resource_rpc.pull(
|
||||
context, resources.QOS_POLICY, policy_id)
|
||||
self.fip_qos_map.set_resource_policy(fip, policy)
|
||||
self.fip_qos_map.set_resource_policy(fip_res, policy)
|
||||
return self.get_policy_rates(policy)
|
||||
|
||||
def process_ip_rates(self, fip, device, rates, with_cache=True):
|
||||
def process_ip_rates(self, fip_res, device, rates, with_cache=True):
|
||||
for direction in constants.VALID_DIRECTIONS:
|
||||
rate = rates.get(direction)
|
||||
if with_cache:
|
||||
|
||||
old_rate, old_burst = self.fip_qos_map.get_fip_ratelimit_cache(
|
||||
direction, fip)
|
||||
direction, fip_res.id)
|
||||
if old_rate == rate['rate'] and old_burst == rate['burst']:
|
||||
# Two possibilities here:
|
||||
# 1. Floating IP rate limit does not change.
|
||||
# 2. Floating IP bandwidth does not limit.
|
||||
continue
|
||||
|
||||
self.process_ip_rate_limit(
|
||||
fip, direction, device,
|
||||
rate['rate'], rate['burst'])
|
||||
self.process_ip_rate_limit(fip_res.ip_address, direction,
|
||||
device, rate['rate'], rate['burst'])
|
||||
|
||||
self.fip_qos_map.set_fip_ratelimit_cache(
|
||||
direction, fip, rate['rate'], rate['burst'])
|
||||
direction, fip_res.id, rate['rate'], rate['burst'])
|
||||
else:
|
||||
tc_wrapper = self._get_tc_wrapper(device)
|
||||
if (rate['rate'] == qos_base.IP_DEFAULT_RATE and
|
||||
rate['burst'] == qos_base.IP_DEFAULT_BURST):
|
||||
# Default value is no limit
|
||||
tc_wrapper.clear_ip_rate_limit(direction, fip)
|
||||
tc_wrapper.clear_ip_rate_limit(direction,
|
||||
fip_res.ip_address)
|
||||
else:
|
||||
tc_wrapper.set_ip_rate_limit(direction, fip,
|
||||
tc_wrapper.set_ip_rate_limit(direction, fip_res.ip_address,
|
||||
rate['rate'], rate['burst'])
|
||||
|
||||
def _get_dvr_fip_device(self, router_info):
|
||||
@ -301,17 +334,17 @@ class FipQosAgentExtension(qos_base.L3QosAgentExtensionBase,
|
||||
|
||||
floating_ips = (router_info.get_floating_ips() +
|
||||
router_info.get_port_forwarding_fips())
|
||||
current_fips = self.fip_qos_map.router_floating_ips.get(
|
||||
router_info.router_id, set())
|
||||
new_fips = set()
|
||||
current_fips = self.fip_qos_map.get_fips_by_router_id(
|
||||
router_info.router_id)
|
||||
new_fips = set([])
|
||||
for fip in floating_ips:
|
||||
fip_addr = fip['floating_ip_address']
|
||||
new_fips.add(fip_addr)
|
||||
fip_res = FipResource(fip['id'], fip['floating_ip_address'])
|
||||
new_fips.add(fip_res)
|
||||
rates = self.get_fip_qos_rates(context,
|
||||
fip_addr,
|
||||
fip_res,
|
||||
fip.get(qos_consts.QOS_POLICY_ID))
|
||||
if device:
|
||||
self.process_ip_rates(fip_addr, device, rates)
|
||||
self.process_ip_rates(fip_res, device, rates)
|
||||
|
||||
if dvr_fip_device:
|
||||
# NOTE(liuyulong): for scenario 4 (mixed dvr_snat and compute
|
||||
@ -320,16 +353,16 @@ class FipQosAgentExtension(qos_base.L3QosAgentExtensionBase,
|
||||
# already set. We just install the rules to the device in
|
||||
# qrouter-namesapce.
|
||||
self.process_ip_rates(
|
||||
fip_addr, dvr_fip_device, rates, with_cache=False)
|
||||
fip_res, dvr_fip_device, rates, with_cache=False)
|
||||
|
||||
self.fip_qos_map.router_floating_ips[router_info.router_id] = new_fips
|
||||
self.fip_qos_map.set_fips(router_info.router_id, new_fips)
|
||||
fips_removed = current_fips - new_fips
|
||||
for fip in fips_removed:
|
||||
for fip_res in fips_removed:
|
||||
if device:
|
||||
self._remove_fip_rate_limit(device, fip)
|
||||
self._remove_fip_rate_limit(device, fip_res)
|
||||
if dvr_fip_device:
|
||||
self._remove_fip_rate_limit(dvr_fip_device, fip)
|
||||
self.fip_qos_map.clean_by_resource(fip)
|
||||
self._remove_fip_rate_limit(dvr_fip_device, fip_res)
|
||||
self.fip_qos_map.clean_by_resource(fip_res)
|
||||
|
||||
def add_router(self, context, data):
|
||||
router_info = self._get_router_info(data['id'])
|
||||
|
@ -51,7 +51,7 @@ class RateLimitMapsTestCase(base.BaseTestCase):
|
||||
self.assertEqual(TEST_POLICY,
|
||||
self.policy_map.known_policies[TEST_POLICY.id])
|
||||
self.assertIn(TEST_RES_1,
|
||||
self.policy_map.qos_policy_resources[TEST_POLICY.id])
|
||||
self.policy_map.qos_policy_2_resources[TEST_POLICY.id])
|
||||
|
||||
def test_get_resource_policy(self):
|
||||
self._set_resources()
|
||||
@ -72,11 +72,13 @@ class RateLimitMapsTestCase(base.BaseTestCase):
|
||||
self._set_resources()
|
||||
self.policy_map.clean_by_resource(TEST_RES_1)
|
||||
self.assertNotIn(TEST_POLICY.id, self.policy_map.known_policies)
|
||||
self.assertNotIn(TEST_RES_1, self.policy_map.resource_policies)
|
||||
self.assertNotIn(TEST_RES_1, self.policy_map.resource_2_qos_policies)
|
||||
self.assertIn(TEST_POLICY2.id, self.policy_map.known_policies)
|
||||
|
||||
def test_clean_by_resource_for_unknown_resource(self):
|
||||
@mock.patch.object(qos_base, 'LOG')
|
||||
def test_clean_by_resource_for_unknown_resource(self, mock_log):
|
||||
self.policy_map._clean_policy_info = mock.Mock()
|
||||
self.policy_map.clean_by_resource(TEST_RES_1)
|
||||
|
||||
self.policy_map._clean_policy_info.assert_not_called()
|
||||
mock_log.debug.assert_called_once_with(
|
||||
'L3 QoS extension did not have information on floating IP %s',
|
||||
TEST_RES_1)
|
||||
|
@ -37,8 +37,12 @@ _uuid = uuidutils.generate_uuid
|
||||
|
||||
TEST_QOS_FIP = "3.3.3.3"
|
||||
|
||||
TEST_FIP = "1.1.1.1"
|
||||
TEST_FIP2 = "2.2.2.2"
|
||||
TEST_FIP_RES_NON_STORED = fip_qos.FipResource('fip_none', '8.8.8.8')
|
||||
# fip1/fip3 and fip2/fip4 have duplicated IP addresses on purpose
|
||||
TEST_FIP_RES_1 = fip_qos.FipResource('fip1', '1.1.1.1')
|
||||
TEST_FIP_RES_2 = fip_qos.FipResource('fip2', '2.2.2.2')
|
||||
TEST_FIP_RES_3 = fip_qos.FipResource('fip3', '1.1.1.1')
|
||||
TEST_FIP_RES_4 = fip_qos.FipResource('fip4', '2.2.2.2')
|
||||
|
||||
HOSTNAME = 'myhost'
|
||||
|
||||
@ -289,8 +293,9 @@ class FipQosExtensionTestCase(QosExtensionBaseTestCase):
|
||||
TEST_QOS_FIP, 3333, 4444)],
|
||||
any_order=True)
|
||||
self.fip_qos_ext.delete_router(self.context, self.router)
|
||||
self.assertIsNone(
|
||||
self.fip_qos_ext.fip_qos_map.router_floating_ips.get(
|
||||
self.assertEqual(
|
||||
set(),
|
||||
self.fip_qos_ext.fip_qos_map.get_fips_by_router_id(
|
||||
self.router_id))
|
||||
self.assertIsNone(
|
||||
self.fip_qos_ext.fip_qos_map.ingress_ratelimits.get(
|
||||
@ -374,7 +379,7 @@ class FipQosExtensionTestCase(QosExtensionBaseTestCase):
|
||||
def _test_process_ip_rates(self, with_cache):
|
||||
rates = {'egress': {'rate': 333, 'burst': 444},
|
||||
'ingress': {'rate': 111, 'burst': 222}}
|
||||
fip = '123.123.123.123'
|
||||
fip_res = fip_qos.FipResource('fip1', '123.123.123.123')
|
||||
device = mock.Mock()
|
||||
tc_wrapper = mock.Mock()
|
||||
with mock.patch.object(
|
||||
@ -383,7 +388,7 @@ class FipQosExtensionTestCase(QosExtensionBaseTestCase):
|
||||
with mock.patch.object(
|
||||
self.fip_qos_ext, 'process_ip_rate_limit') as process_ip:
|
||||
self.fip_qos_ext.process_ip_rates(
|
||||
fip, device, rates, with_cache=with_cache)
|
||||
fip_res, device, rates, with_cache=with_cache)
|
||||
if with_cache:
|
||||
self.assertEqual(2, process_ip.call_count)
|
||||
else:
|
||||
@ -404,21 +409,83 @@ class RouterFipRateLimitMapsTestCase(base.BaseTestCase):
|
||||
super(RouterFipRateLimitMapsTestCase, self).setUp()
|
||||
self.policy_map = fip_qos.RouterFipRateLimitMaps()
|
||||
|
||||
def test_find_fip_router_id(self):
|
||||
router_id = _uuid()
|
||||
self.policy_map.router_floating_ips[router_id] = set([TEST_FIP,
|
||||
TEST_FIP2])
|
||||
self.assertIsNone(self.policy_map.find_fip_router_id("8.8.8.8"))
|
||||
self.assertEqual(router_id,
|
||||
self.policy_map.find_fip_router_id(TEST_FIP))
|
||||
def _check_policy_map_fip(self, router_id, fip_res):
|
||||
if router_id is None:
|
||||
self.assertIsNone(self.policy_map.get_router_id_by_fip(fip_res))
|
||||
self.assertTrue(fip_res not in self.policy_map._fips_2_router)
|
||||
for router_fips in self.policy_map._router_2_fips.values():
|
||||
self.assertTrue(fip_res not in router_fips)
|
||||
else:
|
||||
self.assertEqual(router_id,
|
||||
self.policy_map.get_router_id_by_fip(fip_res))
|
||||
self.assertEqual(router_id,
|
||||
self.policy_map._fips_2_router[fip_res])
|
||||
self.assertTrue(fip_res in
|
||||
self.policy_map._router_2_fips[router_id])
|
||||
|
||||
def test_get_router_id_by_fip(self):
|
||||
router_id_1, router_id_2 = _uuid(), _uuid()
|
||||
self.policy_map.set_fips(router_id_1, [TEST_FIP_RES_1, TEST_FIP_RES_2])
|
||||
self.policy_map.set_fips(router_id_2, [TEST_FIP_RES_3, TEST_FIP_RES_4])
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_NON_STORED)
|
||||
self._check_policy_map_fip(router_id_1, TEST_FIP_RES_1)
|
||||
self._check_policy_map_fip(router_id_1, TEST_FIP_RES_2)
|
||||
self._check_policy_map_fip(router_id_2, TEST_FIP_RES_3)
|
||||
self._check_policy_map_fip(router_id_2, TEST_FIP_RES_4)
|
||||
|
||||
# Remove TEST_FIP_RES_1.
|
||||
self.policy_map.delete_fips([TEST_FIP_RES_1])
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_NON_STORED)
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_1)
|
||||
self._check_policy_map_fip(router_id_1, TEST_FIP_RES_2)
|
||||
self._check_policy_map_fip(router_id_2, TEST_FIP_RES_3)
|
||||
self._check_policy_map_fip(router_id_2, TEST_FIP_RES_4)
|
||||
|
||||
# Remove TEST_FIP_RES_2 and TEST_FIP_RES_3.
|
||||
self.policy_map.delete_fips([TEST_FIP_RES_2, TEST_FIP_RES_3])
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_NON_STORED)
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_1)
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_2)
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_3)
|
||||
self._check_policy_map_fip(router_id_2, TEST_FIP_RES_4)
|
||||
|
||||
# Remove TEST_FIP_RES_4.
|
||||
self.policy_map.delete_fips([TEST_FIP_RES_4])
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_NON_STORED)
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_1)
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_2)
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_3)
|
||||
self._check_policy_map_fip(None, TEST_FIP_RES_4)
|
||||
|
||||
def test_get_router_floating_ips(self):
|
||||
router_id = _uuid()
|
||||
test_ips = [TEST_FIP, TEST_FIP2]
|
||||
self.policy_map.router_floating_ips[router_id] = set([TEST_FIP,
|
||||
TEST_FIP2])
|
||||
get_ips = self.policy_map.get_router_floating_ips(router_id)
|
||||
self.assertEqual(len(test_ips), len(get_ips))
|
||||
router_id_1, router_id_2 = _uuid(), _uuid()
|
||||
self.policy_map.set_fips(router_id_1, [TEST_FIP_RES_1, TEST_FIP_RES_2])
|
||||
self.policy_map.set_fips(router_id_2, [TEST_FIP_RES_3, TEST_FIP_RES_4])
|
||||
fips_1 = self.policy_map.get_fips_by_router_id(router_id_1)
|
||||
self.assertEqual(2, len(fips_1))
|
||||
fips_2 = self.policy_map.get_fips_by_router_id(router_id_2)
|
||||
self.assertEqual(2, len(fips_2))
|
||||
|
||||
# Remove TEST_FIP_RES_1.
|
||||
self.policy_map.delete_fips([TEST_FIP_RES_1])
|
||||
fips_1 = self.policy_map.get_fips_by_router_id(router_id_1)
|
||||
self.assertEqual(1, len(fips_1))
|
||||
fips_2 = self.policy_map.get_fips_by_router_id(router_id_2)
|
||||
self.assertEqual(2, len(fips_2))
|
||||
|
||||
# Remove TEST_FIP_RES_2 and TEST_FIP_RES_3.
|
||||
self.policy_map.delete_fips([TEST_FIP_RES_2, TEST_FIP_RES_3])
|
||||
fips_1 = self.policy_map.get_fips_by_router_id(router_id_1)
|
||||
self.assertEqual(0, len(fips_1))
|
||||
fips_2 = self.policy_map.get_fips_by_router_id(router_id_2)
|
||||
self.assertEqual(1, len(fips_2))
|
||||
|
||||
# Remove TEST_FIP_RES_4.
|
||||
self.policy_map.delete_fips([TEST_FIP_RES_4])
|
||||
fips_1 = self.policy_map.get_fips_by_router_id(router_id_1)
|
||||
self.assertEqual(0, len(fips_1))
|
||||
fips_2 = self.policy_map.get_fips_by_router_id(router_id_2)
|
||||
self.assertEqual(0, len(fips_2))
|
||||
|
||||
def test_remove_fip_ratelimit_cache(self):
|
||||
fip = "1.1.1.1"
|
||||
|
@ -188,7 +188,7 @@ class RouterGatewayIPQosAgentExtensionTestCase(
|
||||
|
||||
self.assertEqual(
|
||||
{self.router_info.router_id: self.policy.id},
|
||||
self.gw_ip_qos_ext.gateway_ip_qos_map.resource_policies)
|
||||
self.gw_ip_qos_ext.gateway_ip_qos_map.resource_2_qos_policies)
|
||||
|
||||
def test_add_router(self):
|
||||
self._test_gateway_ip_add(self.gw_ip_qos_ext.add_router)
|
||||
@ -229,7 +229,7 @@ class RouterGatewayIPQosAgentExtensionTestCase(
|
||||
self.gw_ip_qos_ext._process_update_policy(new_policy)
|
||||
self.assertEqual(
|
||||
{self.router_info.router_id: self.policy.id},
|
||||
self.gw_ip_qos_ext.gateway_ip_qos_map.resource_policies)
|
||||
self.gw_ip_qos_ext.gateway_ip_qos_map.resource_2_qos_policies)
|
||||
tc_wrapper.set_ip_rate_limit.assert_has_calls(
|
||||
[mock.call(lib_const.INGRESS_DIRECTION,
|
||||
TEST_QOS_GW_IP, 5555, 6666),
|
||||
|
Loading…
x
Reference in New Issue
Block a user