[L2] no provisioning block for internal service port
Provisioning Blocks [1] was introduced to manage composite object status. Port object is the one Neutron sets provisioning block during the port processing life cycle. Here is the compute port (VM's NIC port) processing procedure: 1. nova creates port 2. the 'openvswitch' mechinism driver inserts provisioning block for this port 3. nova calls related interface to plug the device 4. L2-agent sets the flows (or rules/devices) for the port and call update_device_list to neutron-server 5. neutron-server try to set port status to ACTIVE 6. neutron-server notify nova that "vif-plugged" success This works fine for VM with its ports. But for neutron service port, like router_gateway, router_interface and dhcp, it is unnecessary. Because there is no dependency among neutron resources. Neutron just knows that the ports had been set properly. And another thing is, for most of these internal service port, there is no need of DHCP, security group or port security. So for neutron internal service ports, the procesure can be: 1. neutron L3/DHCP/X related service plugin creates port 2. no provisioning_block 3. L3/DHCP/X related agent plug the port 4. L2-agent sets the flows (or rules/devices) for the port and call update_device_list to neutron-server 5. neutron-server sets port status to ACTIVE directly, then done! This patch will set neutron *AgentMechanismDrver (including built-in drivers: linuxbridge, macvtap, sriov, openvswitch) to skip inserting the provisioning_block for Neutron internal service ports. [1] https://docs.openstack.org/neutron/latest/contributor/internals/provisioning_blocks.html Closes-Bug: #1930432 Change-Id: Iaf7788bf0cba19a693cbf456f98e50d7b5de9e41
This commit is contained in:
parent
3127bd1d57
commit
e0ea4a51ba
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# 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 neutron_lib import constants
|
||||
|
||||
DEFAULT_DEVICE_OWNER = ''
|
||||
|
||||
# TODO(liuyulong): move to neutron-lib or common constants
|
||||
NO_PBLOCKS_TYPES = [
|
||||
DEFAULT_DEVICE_OWNER,
|
||||
constants.DEVICE_OWNER_DVR_INTERFACE,
|
||||
constants.DEVICE_OWNER_HA_REPLICATED_INT,
|
||||
constants.DEVICE_OWNER_ROUTER_INTF,
|
||||
constants.DEVICE_OWNER_ROUTER_GW,
|
||||
constants.DEVICE_OWNER_ROUTER_SNAT,
|
||||
constants.DEVICE_OWNER_DHCP,
|
||||
constants.DEVICE_OWNER_AGENT_GW,
|
||||
constants.DEVICE_OWNER_ROUTER_HA_INTF,
|
||||
constants.DEVICE_OWNER_FLOATINGIP,
|
||||
]
|
|
@ -25,6 +25,7 @@ from oslo_log import log
|
|||
|
||||
from neutron._i18n import _
|
||||
from neutron.db import provisioning_blocks
|
||||
from neutron.plugins.ml2.common import constants as ml2_consts
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
@ -71,6 +72,11 @@ class AgentMechanismDriverBase(api.MechanismDriver, metaclass=abc.ABCMeta):
|
|||
if not context.host or port['status'] == const.PORT_STATUS_ACTIVE:
|
||||
# no point in putting in a block if the status is already ACTIVE
|
||||
return
|
||||
|
||||
if port['device_owner'] in ml2_consts.NO_PBLOCKS_TYPES:
|
||||
# do not set provisioning_block if it is neutron service port
|
||||
return
|
||||
|
||||
vnic_type = context.current.get(portbindings.VNIC_TYPE,
|
||||
portbindings.VNIC_NORMAL)
|
||||
if vnic_type not in self.supported_vnic_types:
|
||||
|
|
|
@ -125,6 +125,7 @@ from neutron.extensions import vlantransparent
|
|||
from neutron.ipam import exceptions as ipam_exc
|
||||
from neutron.objects import base as base_obj
|
||||
from neutron.objects import ports as ports_obj
|
||||
from neutron.plugins.ml2.common import constants as ml2_consts
|
||||
from neutron.plugins.ml2.common import exceptions as ml2_exc
|
||||
from neutron.plugins.ml2 import db
|
||||
from neutron.plugins.ml2 import driver_context
|
||||
|
@ -1405,6 +1406,11 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
def _setup_dhcp_agent_provisioning_component(self, context, port):
|
||||
if not cfg.CONF.enable_traditional_dhcp:
|
||||
return
|
||||
|
||||
if port['device_owner'] in ml2_consts.NO_PBLOCKS_TYPES:
|
||||
# do not set provisioning_block if it is neutron service port
|
||||
return
|
||||
|
||||
subnet_ids = [f['subnet_id'] for f in port['fixed_ips']]
|
||||
if (db.is_dhcp_active_on_any_subnet(context, subnet_ids) and
|
||||
len(self.get_dhcp_agents_hosting_networks(context,
|
||||
|
|
|
@ -55,6 +55,7 @@ from neutron.db import segments_db
|
|||
from neutron.objects import base as base_obj
|
||||
from neutron.objects import ports as port_obj
|
||||
from neutron.objects import router as l3_obj
|
||||
from neutron.plugins.ml2.common import constants as ml2_consts
|
||||
from neutron.plugins.ml2.common import exceptions as ml2_exc
|
||||
from neutron.plugins.ml2 import db as ml2_db
|
||||
from neutron.plugins.ml2 import driver_context
|
||||
|
@ -1204,7 +1205,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
|
|||
self._add_fake_dhcp_agent()
|
||||
with mock.patch.object(provisioning_blocks,
|
||||
'add_provisioning_component') as ap:
|
||||
with self.port():
|
||||
with self.port(device_owner="fake:test"):
|
||||
self.assertTrue(ap.called)
|
||||
|
||||
def test_dhcp_provisioning_blocks_skipped_on_create_with_no_dhcp(self):
|
||||
|
@ -1220,7 +1221,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
|
|||
ctx = context.get_admin_context()
|
||||
plugin = directory.get_plugin()
|
||||
self._add_fake_dhcp_agent()
|
||||
with self.port() as port:
|
||||
with self.port(device_owner="fake:test") as port:
|
||||
with mock.patch.object(provisioning_blocks,
|
||||
'add_provisioning_component') as ap:
|
||||
port['port'].update(update_dict)
|
||||
|
@ -1239,9 +1240,34 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
|
|||
def test_dhcp_provisioning_blocks_removed_without_dhcp_agents(self):
|
||||
with mock.patch.object(provisioning_blocks,
|
||||
'remove_provisioning_component') as cp:
|
||||
with self.port():
|
||||
with self.port(device_owner="fake:test"):
|
||||
self.assertTrue(cp.called)
|
||||
|
||||
def _test_no_dhcp_provisioning_blocks_removed_empty_device_owner(
|
||||
self, device_owner):
|
||||
with mock.patch.object(provisioning_blocks,
|
||||
'remove_provisioning_component') as cp:
|
||||
with self.port(device_owner=device_owner):
|
||||
self.assertFalse(cp.called)
|
||||
|
||||
def _test_no_dhcp_provisioning_blocks_added_empty_device_owner(
|
||||
self, device_owner):
|
||||
with mock.patch.object(provisioning_blocks,
|
||||
'add_provisioning_component') as cp:
|
||||
with self.port(device_owner=device_owner):
|
||||
self.assertFalse(cp.called)
|
||||
|
||||
def test_no_dhcp_provisioning_blocks_removed_for_empty_or_service_port(
|
||||
self):
|
||||
for device_owner in ml2_consts.NO_PBLOCKS_TYPES:
|
||||
self._test_no_dhcp_provisioning_blocks_removed_empty_device_owner(
|
||||
device_owner)
|
||||
|
||||
def test_no_dhcp_provisioning_blocks_added_for_empty_or_service_port(self):
|
||||
for device_owner in ml2_consts.NO_PBLOCKS_TYPES:
|
||||
self._test_no_dhcp_provisioning_blocks_added_empty_device_owner(
|
||||
device_owner)
|
||||
|
||||
def test_create_update_get_port_same_fixed_ips_order(self):
|
||||
ctx = context.get_admin_context()
|
||||
plugin = directory.get_plugin()
|
||||
|
|
Loading…
Reference in New Issue