Adds provisioning block to APIC_AIM mech driver

This is per design from:

https://docs.openstack.org/neutron/pike/contributor/internals/provisioning_blocks.html

Change-Id: Ie5e866cc65235f4775fd076fc4bfcf1f73fce928
This commit is contained in:
Weiguo Sun 2018-02-16 14:24:19 -05:00 committed by Sumit Naiksatam
parent 70731da6f2
commit 3c6ecad766
2 changed files with 65 additions and 2 deletions

View File

@ -26,6 +26,7 @@ from aim.common import utils
from aim import context as aim_context
from aim import utils as aim_utils
from neutron.agent import securitygroups_rpc
from neutron.callbacks import resources
from neutron.common import rpc as n_rpc
from neutron.common import topics as n_topics
from neutron.db import api as db_api
@ -35,6 +36,7 @@ from neutron.db.models import l3 as l3_db
from neutron.db.models import securitygroup as sg_models
from neutron.db.models import segment as segments_model
from neutron.db import models_v2
from neutron.db import provisioning_blocks
from neutron.db import rbac_db_models
from neutron.db import segments_db
from neutron.extensions import external_net
@ -83,6 +85,9 @@ L3OUT_NODE_PROFILE_NAME = 'NodeProfile'
L3OUT_IF_PROFILE_NAME = 'IfProfile'
L3OUT_EXT_EPG = 'ExtEpg'
SUPPORTED_VNIC_TYPES = [portbindings.VNIC_NORMAL,
portbindings.VNIC_DIRECT]
AGENT_TYPE_DVS = 'DVS agent'
VIF_TYPE_DVS = 'dvs'
PROMISCUOUS_TYPES = [n_constants.DEVICE_OWNER_DHCP,
@ -1500,8 +1505,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
# Check the VNIC type.
vnic_type = port.get(portbindings.VNIC_TYPE,
portbindings.VNIC_NORMAL)
if vnic_type not in [portbindings.VNIC_NORMAL,
portbindings.VNIC_DIRECT]:
if vnic_type not in SUPPORTED_VNIC_TYPES:
LOG.debug("Refusing to bind due to unsupported vnic_type: %s",
vnic_type)
return
@ -1593,6 +1597,30 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
port = context.current
self._really_update_sg_rule_with_remote_group_set(
context, port, port['security_groups'], is_delete=False)
self._insert_provisioning_block(context)
def _insert_provisioning_block(self, context):
# we insert a status barrier to prevent the port from transitioning
# to active until the agent reports back that the wiring is done
port = context.current
if (not context.host or
port['status'] == n_constants.PORT_STATUS_ACTIVE):
# no point in putting in a block if the status is already ACTIVE
return
# Check the VNIC type.
vnic_type = port.get(portbindings.VNIC_TYPE,
portbindings.VNIC_NORMAL)
if vnic_type not in SUPPORTED_VNIC_TYPES:
LOG.debug("No provisioning_block due to unsupported vnic_type: %s",
vnic_type)
return
if (context.host_agents(ofcst.AGENT_TYPE_OPFLEX_OVS) or
context.host_agents(AGENT_TYPE_DVS)):
provisioning_blocks.add_provisioning_component(
context._plugin_context, port['id'], resources.PORT,
provisioning_blocks.L2_AGENT_ENTITY)
def update_port_precommit(self, context):
port = context.current
@ -1612,6 +1640,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
context.bottom_bound_segment[api.NETWORK_TYPE])):
self._associate_domain(context, is_vmm=True)
self._update_sg_rule_with_remote_group_set(context, port)
self._insert_provisioning_block(context)
def update_port_postcommit(self, context):
port = context.current

View File

@ -34,7 +34,9 @@ from aim import utils as aim_utils
from keystoneclient.v3 import client as ksc_client
from neutron.api import extensions
from neutron.db import api as db_api
from neutron.db import provisioning_blocks
from neutron.db import segments_db
from neutron.plugins.ml2 import driver_context
from neutron.tests.unit.api import test_extensions
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
from neutron.tests.unit.extensions import test_address_scope
@ -2893,6 +2895,38 @@ class TestAimMapping(ApicAimTestCase):
is_implicit=True)['subnetpool']
self.assertTrue(sp3['is_implicit'])
def test_dhcp_provisioning_blocks_inserted_on_update(self):
ctx = n_context.get_admin_context()
plugin = directory.get_plugin()
def _fake_dhcp_agent():
agent = mock.Mock()
plugin = directory.get_plugin()
return mock.patch.object(
plugin, 'get_dhcp_agents_hosting_networks',
return_value=[agent]).start()
dhcp_agt_mock = _fake_dhcp_agent()
update_dict = {'binding:host_id': 'newhost'}
def _host_agents(self, agent_type):
if agent_type == ofcst.AGENT_TYPE_OPFLEX_OVS:
fake_agent = {"alive": False}
return [fake_agent]
orig_host_agents = getattr(driver_context.PortContext, "host_agents")
setattr(driver_context.PortContext, "host_agents", _host_agents)
with self.port() as port:
with mock.patch.object(provisioning_blocks,
'add_provisioning_component') as ap:
port['port'].update(update_dict)
plugin.update_port(ctx, port['port']['id'], port)
ap.assert_called()
setattr(driver_context.PortContext, "host_agents", orig_host_agents)
dhcp_agt_mock.stop()
class TestSyncState(ApicAimTestCase):
@staticmethod