Arista drivers for ML2 and L3 Service Plugin
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

190 lines
7.9 KiB

# Copyright (c) 2013 OpenStack Foundation
#
# 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.
from eventlet import greenthread
from eventlet import queue
import mock
import time
from neutron_lib.plugins import constants as plugin_constants
from neutron_lib.plugins import directory
from oslo_config import cfg
from oslo_utils import importutils
from neutron.tests.unit import testlib_api
from networking_arista.common import constants as a_const
from networking_arista.common import exceptions as arista_exc
from networking_arista.ml2 import arista_sync
from networking_arista.ml2.mechanism_arista import MechResource
from networking_arista.tests.unit import utils
class SyncServiceTest(testlib_api.SqlTestCase):
"""Test cases for the sync service."""
def setUp(self):
super(SyncServiceTest, self).setUp()
utils.setup_arista_wrapper_config(cfg)
plugin_klass = importutils.import_class(
"neutron.db.db_base_plugin_v2.NeutronDbPluginV2")
directory.add_plugin(plugin_constants.CORE, plugin_klass())
utils.setup_scenario()
self.mech_queue = queue.LightQueue()
self.sync_service = arista_sync.AristaSyncWorker(self.mech_queue)
self.sync_service._rpc = utils.MockCvx('region')
def tearDown(self):
if self.sync_service._running:
self.sync_service.stop()
self.sync_service.wait()
super(SyncServiceTest, self).tearDown()
def test_start(self):
self.sync_service.start()
self.assertTrue(self.sync_service._running)
self.assertIsNotNone(self.sync_service._thread)
self.assertIsNotNone(self.sync_service.sync_order)
self.assertIsNotNone(self.sync_service.done)
def test_start_twice(self):
self.sync_service.start()
current_thread = self.sync_service._thread
self.sync_service.start()
self.assertEqual(self.sync_service._thread, current_thread)
def test_stop_graceful(self):
self.test_start()
running_thread = self.sync_service._thread
self.sync_service.stop()
self.sync_service.wait()
self.assertFalse(self.sync_service._running)
self.assertTrue(running_thread.dead)
self.assertIsNone(self.sync_service._thread)
def test_stop_ungraceful(self):
self.test_start()
running_thread = self.sync_service._thread
self.sync_service.stop(graceful=False)
self.assertTrue(running_thread.dead)
self.assertIsNone(self.sync_service._thread)
def test_reset(self):
self.test_start()
old_thread = self.sync_service._thread
self.sync_service.reset()
self.assertNotEqual(self.sync_service._thread, old_thread)
def test_resource_class_full_coverage(self):
self.sync_service.initialize()
for i in range(len(self.sync_service.sync_order)):
self.sync_service.sync_order[i] = mock.MagicMock()
self.sync_service.synchronize_resources()
for resource_type in self.sync_service.sync_order:
resource_type.delete_cvx_resources.assert_called_once()
resource_type.create_cvx_resources.assert_called_once()
def test_full_sync_cvx_populated(self):
self.sync_service.initialize()
self.sync_service.synchronize_resources()
for endpoint, data in self.sync_service._rpc.endpoint_data.items():
self.assertNotEqual(data, {})
def test_process_mech_update(self):
self.sync_service.initialize()
for resource_type in a_const.ALL_RESOURCE_TYPES:
res_cls = mock.MagicMock()
with mock.patch.object(self.sync_service,
'get_resource_class') as get:
get.return_value = res_cls
res = MechResource('id', resource_type, a_const.CREATE)
self.sync_service.update_neutron_resource(res)
get.assert_called_once_with(resource_type)
res_cls.update_neutron_resource.assert_called_once_with(
'id', a_const.CREATE)
get.reset_mock()
get.return_value = res_cls
res = MechResource('id', resource_type, a_const.DELETE)
self.sync_service.update_neutron_resource(res)
get.assert_called_once_with(resource_type)
res_cls.update_neutron_resource.assert_called_once_with(
'id', a_const.DELETE)
def test_force_full_sync(self):
self.sync_service.initialize()
for i in range(len(self.sync_service.sync_order)):
self.sync_service.sync_order[i] = mock.MagicMock()
self.sync_service.force_full_sync()
for resource_type in self.sync_service.sync_order:
resource_type.clear_all_data.assert_called_once()
def test_sync_timeout(self):
self.sync_service.initialize()
with mock.patch.object(
self.sync_service, 'check_if_out_of_sync') as oos:
self.sync_service.wait_for_sync_required()
oos.assert_called_once()
def test_full_sync_required(self):
self.sync_service.initialize()
self.sync_service._cvx_uuid = 'old-id'
self.sync_service._rpc = mock.MagicMock()
self.sync_service._rpc.get_cvx_uuid.return_value = 'new-id'
with mock.patch.object(self.sync_service, 'force_full_sync') as ffs:
self.assertTrue(self.sync_service.check_if_out_of_sync())
ffs.assert_called_once()
self.assertEqual(self.sync_service._synchronizing_uuid, 'new-id')
self.assertNotEqual(self.sync_service._last_sync_time, 0)
def test_mech_queue_timeout(self):
self.sync_service.initialize()
self.assertFalse(self.sync_service.wait_for_mech_driver_update(1))
def test_mech_queue_updated(self):
self.sync_service.initialize()
resource = MechResource('tid', a_const.TENANT_RESOURCE, a_const.CREATE)
self.mech_queue.put(resource)
# Must yield to allow resource to be available on the queue
greenthread.sleep(0)
self.assertTrue(self.sync_service.wait_for_mech_driver_update(1))
self.assertEqual(self.sync_service._resources_to_update, [resource])
def test_sync_start_fail(self):
self.sync_service.initialize()
self.sync_service._rpc = mock.MagicMock()
self.sync_service._rpc.sync_start.return_value = False
self.assertEqual(self.sync_service._last_sync_time, 0)
for i in range(len(self.sync_service.sync_order)):
self.sync_service.sync_order[i] = mock.MagicMock()
self.sync_service.synchronize_resources()
for resource_type in self.sync_service.sync_order:
resource_type.delete_cvx_resources.assert_not_called()
resource_type.create_cvx_resources.assert_not_called()
self.sync_service._rpc.sync_end.assert_not_called()
def test_sync_lock_release_on_failure(self):
self.sync_service.initialize()
self.sync_service._rpc = mock.MagicMock()
self.sync_service.update_neutron_resource = mock.Mock(
side_effect=arista_exc.AristaRpcError(msg='fail'))
resource = MechResource('tid', a_const.TENANT_RESOURCE, a_const.CREATE)
self.sync_service.start()
self.sync_service._last_sync_time = time.time()
self.sync_service._cvx_uuid = 'cvx-id'
self.mech_queue.put(resource)
greenthread.sleep(0)
self.sync_service.stop()
self.sync_service.wait()
self.sync_service._rpc.sync_end.assert_called_once()