226 lines
9.0 KiB
Python
226 lines
9.0 KiB
Python
# Copyright 2016 Huawei Technologies India Pvt. Ltd.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import testscenarios
|
|
|
|
from oslo_utils import importutils
|
|
|
|
from neutron import context
|
|
from neutron.tests.unit import testlib_api
|
|
|
|
from neutron_dynamic_routing.db import bgp_db
|
|
from neutron_dynamic_routing.db import bgp_dragentscheduler_db as bgp_dras_db
|
|
from neutron_dynamic_routing.services.bgp.scheduler import bgp_dragent_scheduler as bgp_dras # noqa
|
|
from neutron_dynamic_routing.tests.common import helpers
|
|
|
|
# Required to generate tests from scenarios. Not compatible with nose.
|
|
load_tests = testscenarios.load_tests_apply_scenarios
|
|
|
|
|
|
class TestBgpDrAgentSchedulerBaseTestCase(testlib_api.SqlTestCase):
|
|
|
|
def setUp(self):
|
|
super(TestBgpDrAgentSchedulerBaseTestCase, self).setUp()
|
|
self.ctx = context.get_admin_context()
|
|
self.bgp_speaker = {'id': 'foo_bgp_speaker_id'}
|
|
self.bgp_speaker_id = 'foo_bgp_speaker_id'
|
|
self._save_bgp_speaker(self.bgp_speaker_id)
|
|
|
|
def _create_and_set_agents_down(self, hosts, down_agent_count=0,
|
|
admin_state_up=True):
|
|
agents = []
|
|
for i, host in enumerate(hosts):
|
|
is_alive = i >= down_agent_count
|
|
agents.append(helpers.register_bgp_dragent(
|
|
host,
|
|
admin_state_up=admin_state_up,
|
|
alive=is_alive))
|
|
return agents
|
|
|
|
def _save_bgp_speaker(self, bgp_speaker_id):
|
|
cls = bgp_db.BgpDbMixin()
|
|
bgp_speaker_body = {'bgp_speaker': {
|
|
'name': 'fake_bgp_speaker',
|
|
'ip_version': '4',
|
|
'local_as': '123',
|
|
'advertise_floating_ip_host_routes': '0',
|
|
'advertise_tenant_networks': '0',
|
|
'peers': [],
|
|
'networks': []}}
|
|
cls._save_bgp_speaker(self.ctx, bgp_speaker_body, uuid=bgp_speaker_id)
|
|
|
|
def _test_schedule_bind_bgp_speaker(self, agents, bgp_speaker_id):
|
|
scheduler = bgp_dras.ChanceScheduler()
|
|
scheduler.resource_filter.bind(self.ctx, agents, bgp_speaker_id)
|
|
results = self.ctx.session.query(
|
|
bgp_dras_db.BgpSpeakerDrAgentBinding).filter_by(
|
|
bgp_speaker_id=bgp_speaker_id).all()
|
|
|
|
for result in results:
|
|
self.assertEqual(bgp_speaker_id, result.bgp_speaker_id)
|
|
|
|
|
|
class TestBgpDrAgentScheduler(TestBgpDrAgentSchedulerBaseTestCase,
|
|
bgp_db.BgpDbMixin):
|
|
|
|
def test_schedule_bind_bgp_speaker_single_agent(self):
|
|
agents = self._create_and_set_agents_down(['host-a'])
|
|
self._test_schedule_bind_bgp_speaker(agents, self.bgp_speaker_id)
|
|
|
|
def test_schedule_bind_bgp_speaker_multi_agents(self):
|
|
agents = self._create_and_set_agents_down(['host-a', 'host-b'])
|
|
self._test_schedule_bind_bgp_speaker(agents, self.bgp_speaker_id)
|
|
|
|
|
|
class TestBgpAgentFilter(TestBgpDrAgentSchedulerBaseTestCase,
|
|
bgp_db.BgpDbMixin,
|
|
bgp_dras_db.BgpDrAgentSchedulerDbMixin):
|
|
|
|
def setUp(self):
|
|
super(TestBgpAgentFilter, self).setUp()
|
|
self.bgp_drscheduler = importutils.import_object(
|
|
'neutron_dynamic_routing.services.bgp.scheduler.'
|
|
'bgp_dragent_scheduler.ChanceScheduler'
|
|
)
|
|
self.plugin = self
|
|
|
|
def _test_filter_agents_helper(self, bgp_speaker,
|
|
expected_filtered_dragent_ids=None,
|
|
expected_num_agents=1):
|
|
filtered_agents = (
|
|
self.plugin.bgp_drscheduler.resource_filter.filter_agents(
|
|
self.plugin, self.ctx, bgp_speaker))
|
|
self.assertEqual(expected_num_agents,
|
|
filtered_agents['n_agents'])
|
|
actual_filtered_dragent_ids = [
|
|
agent.id for agent in filtered_agents['hostable_agents']]
|
|
if expected_filtered_dragent_ids is None:
|
|
expected_filtered_dragent_ids = []
|
|
self.assertEqual(len(expected_filtered_dragent_ids),
|
|
len(actual_filtered_dragent_ids))
|
|
for filtered_agent_id in actual_filtered_dragent_ids:
|
|
self.assertIn(filtered_agent_id, expected_filtered_dragent_ids)
|
|
|
|
def test_filter_agents_single_agent(self):
|
|
agents = self._create_and_set_agents_down(['host-a'])
|
|
expected_filtered_dragent_ids = [agents[0].id]
|
|
self._test_filter_agents_helper(
|
|
self.bgp_speaker,
|
|
expected_filtered_dragent_ids=expected_filtered_dragent_ids)
|
|
|
|
def test_filter_agents_no_agents(self):
|
|
expected_filtered_dragent_ids = []
|
|
self._test_filter_agents_helper(
|
|
self.bgp_speaker,
|
|
expected_filtered_dragent_ids=expected_filtered_dragent_ids,
|
|
expected_num_agents=0)
|
|
|
|
def test_filter_agents_two_agents(self):
|
|
agents = self._create_and_set_agents_down(['host-a', 'host-b'])
|
|
expected_filtered_dragent_ids = [agent.id for agent in agents]
|
|
self._test_filter_agents_helper(
|
|
self.bgp_speaker,
|
|
expected_filtered_dragent_ids=expected_filtered_dragent_ids)
|
|
|
|
def test_filter_agents_agent_already_scheduled(self):
|
|
agents = self._create_and_set_agents_down(['host-a', 'host-b'])
|
|
self._test_schedule_bind_bgp_speaker([agents[0]], self.bgp_speaker_id)
|
|
self._test_filter_agents_helper(self.bgp_speaker,
|
|
expected_num_agents=0)
|
|
|
|
def test_filter_agents_multiple_agents_bgp_speakers(self):
|
|
agents = self._create_and_set_agents_down(['host-a', 'host-b'])
|
|
self._test_schedule_bind_bgp_speaker([agents[0]], self.bgp_speaker_id)
|
|
bgp_speaker = {'id': 'bar-speaker-id'}
|
|
self._save_bgp_speaker(bgp_speaker['id'])
|
|
expected_filtered_dragent_ids = [agents[1].id]
|
|
self._test_filter_agents_helper(
|
|
bgp_speaker,
|
|
expected_filtered_dragent_ids=expected_filtered_dragent_ids)
|
|
|
|
|
|
class TestAutoScheduleBgpSpeakers(TestBgpDrAgentSchedulerBaseTestCase):
|
|
"""Unit test scenarios for schedule_unscheduled_bgp_speakers.
|
|
|
|
bgp_speaker_present
|
|
BGP speaker is present or not
|
|
|
|
scheduled_already
|
|
BGP speaker is already scheduled to the agent or not
|
|
|
|
agent_down
|
|
BGP DRAgent is down or alive
|
|
|
|
valid_host
|
|
If true, then an valid host is passed to schedule BGP speaker,
|
|
else an invalid host is passed.
|
|
"""
|
|
scenarios = [
|
|
('BGP speaker present',
|
|
dict(bgp_speaker_present=True,
|
|
scheduled_already=False,
|
|
agent_down=False,
|
|
valid_host=True,
|
|
expected_result=True)),
|
|
|
|
('No BGP speaker',
|
|
dict(bgp_speaker_present=False,
|
|
scheduled_already=False,
|
|
agent_down=False,
|
|
valid_host=True,
|
|
expected_result=False)),
|
|
|
|
('BGP speaker already scheduled',
|
|
dict(bgp_speaker_present=True,
|
|
scheduled_already=True,
|
|
agent_down=False,
|
|
valid_host=True,
|
|
expected_result=False)),
|
|
|
|
('BGP DR agent down',
|
|
dict(bgp_speaker_present=True,
|
|
scheduled_already=False,
|
|
agent_down=True,
|
|
valid_host=False,
|
|
expected_result=False)),
|
|
|
|
('Invalid host',
|
|
dict(bgp_speaker_present=True,
|
|
scheduled_already=False,
|
|
agent_down=False,
|
|
valid_host=False,
|
|
expected_result=False)),
|
|
]
|
|
|
|
def test_auto_schedule_bgp_speaker(self):
|
|
scheduler = bgp_dras.ChanceScheduler()
|
|
if self.bgp_speaker_present:
|
|
down_agent_count = 1 if self.agent_down else 0
|
|
agents = self._create_and_set_agents_down(
|
|
['host-a'], down_agent_count=down_agent_count)
|
|
if self.scheduled_already:
|
|
self._test_schedule_bind_bgp_speaker(agents,
|
|
self.bgp_speaker_id)
|
|
|
|
expected_hosted_agents = (1 if self.bgp_speaker_present and
|
|
self.valid_host else 0)
|
|
host = "host-a" if self.valid_host else "host-b"
|
|
observed_ret_value = scheduler.schedule_unscheduled_bgp_speakers(
|
|
self.ctx, host)
|
|
self.assertEqual(self.expected_result, observed_ret_value)
|
|
hosted_agents = self.ctx.session.query(
|
|
bgp_dras_db.BgpSpeakerDrAgentBinding).all()
|
|
self.assertEqual(expected_hosted_agents, len(hosted_agents))
|