[apic_aim] Fixes and tests for apic:synchronization_state
Fix SYNC_* constants, log exceptions from extend_*_dict methods, and add unit tests for apic:synchronization_state attribute. Change-Id: I71af9da7ac4ec34a7ec0ebc41f6dc52fdca5248e
This commit is contained in:
parent
77bc49a420
commit
5c22a9fdc0
|
@ -28,8 +28,8 @@ SUBNET = 'Subnet'
|
|||
VRF = 'VRF'
|
||||
|
||||
SYNC_SYNCED = 'synced'
|
||||
SYNC_PENDING = 'pending'
|
||||
SYNC_FAILED = 'failed'
|
||||
SYNC_BUILD = 'build'
|
||||
SYNC_ERROR = 'error'
|
||||
|
||||
APIC_ATTRIBUTES = {
|
||||
DIST_NAMES: {'allow_post': False, 'allow_put': False, 'is_visible': True},
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron._i18n import _LE
|
||||
from neutron._i18n import _LI
|
||||
from neutron.api import extensions
|
||||
from neutron import manager as n_manager
|
||||
from oslo_log import log
|
||||
from oslo_utils import excutils
|
||||
|
||||
from gbpservice.neutron import extensions as extensions_pkg
|
||||
from gbpservice.neutron.plugins.ml2plus import driver_api as api_plus
|
||||
|
@ -50,10 +52,22 @@ class ApicExtensionDriver(api_plus.ExtensionDriver):
|
|||
return "cisco-apic"
|
||||
|
||||
def extend_network_dict(self, session, base_model, result):
|
||||
self._md.extend_network_dict(session, base_model, result)
|
||||
try:
|
||||
self._md.extend_network_dict(session, base_model, result)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_LE("APIC AIM extend_network_dict failed"))
|
||||
|
||||
def extend_subnet_dict(self, session, base_model, result):
|
||||
self._md.extend_subnet_dict(session, base_model, result)
|
||||
try:
|
||||
self._md.extend_subnet_dict(session, base_model, result)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_LE("APIC AIM extend_subnet_dict failed"))
|
||||
|
||||
def extend_address_scope_dict(self, session, base_model, result):
|
||||
self._md.extend_address_scope_dict(session, base_model, result)
|
||||
try:
|
||||
self._md.extend_address_scope_dict(session, base_model, result)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_LE("APIC AIM extend_address_scope_dict failed"))
|
||||
|
|
|
@ -305,6 +305,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver):
|
|||
name=vrf_aname)
|
||||
dist_names[cisco_apic.VRF] = aim_vrf.dn
|
||||
sync_state = self._merge_status(aim_ctx, sync_state, aim_vrf)
|
||||
|
||||
result[cisco_apic.DIST_NAMES] = dist_names
|
||||
result[cisco_apic.SYNC_STATE] = sync_state
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron._i18n import _LE
|
||||
from neutron._i18n import _LI
|
||||
from neutron.api import extensions
|
||||
from neutron.db import common_db_mixin
|
||||
|
@ -22,6 +23,7 @@ from neutron.db import l3_gwmode_db
|
|||
from neutron.extensions import l3
|
||||
from neutron.plugins.common import constants
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
from sqlalchemy import inspect
|
||||
|
||||
from gbpservice.neutron import extensions as extensions_pkg
|
||||
|
@ -63,7 +65,11 @@ class ApicL3Plugin(common_db_mixin.CommonDbMixin,
|
|||
def _extend_router_dict_apic(self, router_res, router_db):
|
||||
LOG.debug("APIC AIM L3 Plugin extending router dict: %s", router_res)
|
||||
session = inspect(router_db).session
|
||||
self._md.extend_router_dict(session, router_db, router_res)
|
||||
try:
|
||||
self._md.extend_router_dict(session, router_db, router_res)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_LE("APIC AIM extend_router_dict failed"))
|
||||
|
||||
db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
|
||||
l3.ROUTERS, ['_extend_router_dict_apic'])
|
||||
|
|
|
@ -17,6 +17,7 @@ import mock
|
|||
|
||||
from aim import aim_manager
|
||||
from aim.api import resource as aim_resource
|
||||
from aim.api import status as aim_status
|
||||
from aim import config as aim_cfg
|
||||
from aim import context as aim_context
|
||||
from aim.db import model_base as aim_model_base
|
||||
|
@ -858,8 +859,218 @@ class TestAimMapping(ApicAimTestCase):
|
|||
|
||||
# TODO(rkukura): Test IPv6 and dual stack router interfaces.
|
||||
|
||||
# TODO(rkukura): Test synchronization_state attribute for each AIM
|
||||
# resource.
|
||||
|
||||
class TestSyncState(ApicAimTestCase):
|
||||
@staticmethod
|
||||
def _get_pending_status_for_type(resource, type):
|
||||
status = (isinstance(resource, type) and
|
||||
aim_status.AciStatus.SYNC_PENDING or
|
||||
aim_status.AciStatus.SYNCED)
|
||||
return aim_status.AciStatus(sync_status=status)
|
||||
|
||||
@staticmethod
|
||||
def _get_failed_status_for_type(resource, type):
|
||||
status = (isinstance(resource, type) and
|
||||
aim_status.AciStatus.SYNC_FAILED or
|
||||
aim_status.AciStatus.SYNC_PENDING)
|
||||
return aim_status.AciStatus(sync_status=status)
|
||||
|
||||
def _test_network(self, expected_state):
|
||||
net = self._make_network(self.fmt, 'net1', True)['network']
|
||||
self.assertEqual(expected_state, net['apic:synchronization_state'])
|
||||
|
||||
net = self._show('networks', net['id'])['network']
|
||||
self.assertEqual(expected_state, net['apic:synchronization_state'])
|
||||
|
||||
def test_network_synced(self):
|
||||
self._test_network('synced')
|
||||
|
||||
def test_network_bd_build(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_pending_status_for_type(
|
||||
resource, aim_resource.BridgeDomain)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_network('build')
|
||||
|
||||
def test_network_bd_error(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_failed_status_for_type(
|
||||
resource, aim_resource.BridgeDomain)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_network('error')
|
||||
|
||||
def test_network_epg_build(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_pending_status_for_type(
|
||||
resource, aim_resource.EndpointGroup)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_network('build')
|
||||
|
||||
def test_network_epg_error(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_failed_status_for_type(
|
||||
resource, aim_resource.EndpointGroup)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_network('error')
|
||||
|
||||
def test_network_vrf_build(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_pending_status_for_type(
|
||||
resource, aim_resource.VRF)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_network('build')
|
||||
|
||||
def test_network_vrf_error(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_failed_status_for_type(
|
||||
resource, aim_resource.VRF)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_network('error')
|
||||
|
||||
def _test_address_scope(self, expected_state):
|
||||
scope = self._make_address_scope(self.fmt, 4, name='scope1')[
|
||||
'address_scope']
|
||||
self.assertEqual(expected_state, scope['apic:synchronization_state'])
|
||||
|
||||
scope = self._show('address-scopes', scope['id'])['address_scope']
|
||||
self.assertEqual(expected_state, scope['apic:synchronization_state'])
|
||||
|
||||
def test_address_scope_synced(self):
|
||||
self._test_address_scope('synced')
|
||||
|
||||
def test_address_scope_vrf_build(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_pending_status_for_type(
|
||||
resource, aim_resource.VRF)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_address_scope('build')
|
||||
|
||||
def test_address_scope_vrf_error(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_failed_status_for_type(
|
||||
resource, aim_resource.VRF)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_address_scope('error')
|
||||
|
||||
def _test_router(self, expected_state):
|
||||
router = self._make_router(self.fmt, 'test-tenant', 'router1')[
|
||||
'router']
|
||||
self.assertEqual(expected_state, router['apic:synchronization_state'])
|
||||
|
||||
router = self._show('routers', router['id'])['router']
|
||||
self.assertEqual(expected_state, router['apic:synchronization_state'])
|
||||
|
||||
def test_router_synced(self):
|
||||
self._test_router('synced')
|
||||
|
||||
def test_router_contract_build(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_pending_status_for_type(
|
||||
resource, aim_resource.Contract)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_router('build')
|
||||
|
||||
def test_router_contract_error(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_failed_status_for_type(
|
||||
resource, aim_resource.Contract)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_router('error')
|
||||
|
||||
def test_router_subject_build(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_pending_status_for_type(
|
||||
resource, aim_resource.ContractSubject)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_router('build')
|
||||
|
||||
def test_router_subject_error(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_failed_status_for_type(
|
||||
resource, aim_resource.ContractSubject)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_router('error')
|
||||
|
||||
def _test_router_interface_vrf(self, expected_state):
|
||||
net_resp = self._make_network(self.fmt, 'net1', True)
|
||||
subnet = self._make_subnet(
|
||||
self.fmt, net_resp, '10.0.0.1', '10.0.0.0/24')['subnet']
|
||||
router = self._make_router(self.fmt, 'test-tenant', 'router1')[
|
||||
'router']
|
||||
self.l3_plugin.add_router_interface(
|
||||
context.get_admin_context(), router['id'],
|
||||
{'subnet_id': subnet['id']})
|
||||
|
||||
router = self._show('routers', router['id'])['router']
|
||||
self.assertEqual(expected_state, router['apic:synchronization_state'])
|
||||
|
||||
def test_router_interface_vrf_synced(self):
|
||||
self._test_router_interface_vrf('synced')
|
||||
|
||||
def test_router_interface_vrf_build(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_pending_status_for_type(
|
||||
resource, aim_resource.VRF)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_router_interface_vrf('build')
|
||||
|
||||
def test_router_interface_vrf_error(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_failed_status_for_type(
|
||||
resource, aim_resource.VRF)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_router_interface_vrf('error')
|
||||
|
||||
def _test_router_interface_subnet(self, expected_state):
|
||||
net_resp = self._make_network(self.fmt, 'net1', True)
|
||||
subnet = self._make_subnet(
|
||||
self.fmt, net_resp, '10.0.0.1', '10.0.0.0/24')['subnet']
|
||||
router = self._make_router(self.fmt, 'test-tenant', 'router1')[
|
||||
'router']
|
||||
self.l3_plugin.add_router_interface(
|
||||
context.get_admin_context(), router['id'],
|
||||
{'subnet_id': subnet['id']})
|
||||
|
||||
# TODO(rkukura): Enable when exposing Subnets on router is implemented.
|
||||
# router = self._show('routers', router['id'])['router']
|
||||
# self.assertEqual(expected_state,
|
||||
# router['apic:synchronization_state'])
|
||||
|
||||
subnet = self._show('subnets', subnet['id'])['subnet']
|
||||
self.assertEqual(expected_state, subnet['apic:synchronization_state'])
|
||||
|
||||
def test_router_interface_subnet_synced(self):
|
||||
self._test_router_interface_subnet('synced')
|
||||
|
||||
def test_router_interface_subnet_build(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_pending_status_for_type(
|
||||
resource, aim_resource.Subnet)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_router_interface_subnet('build')
|
||||
|
||||
def test_router_interface_subnet_error(self):
|
||||
def get_status(self, context, resource):
|
||||
return TestSyncState._get_failed_status_for_type(
|
||||
resource, aim_resource.Subnet)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status', get_status):
|
||||
self._test_router_interface_subnet('error')
|
||||
|
||||
|
||||
class TestPortBinding(ApicAimTestCase):
|
||||
|
|
Loading…
Reference in New Issue