DVR: Ignore DHCP port during DVR host query
For large scale deployment, the dvr router will be installed to
the scheduled DHCP host. This will definitely increase the l3
agent service pressure, especially in large number of concurrent
updates, creation, or agent restart.
This patch adds a config ``host_dvr_for_dhcp`` for the DHCP port
device_owner filter during DVR host query. Then if we set
``host_dvr_for_dhcp = False``, L3-agent will not host the DVR router
namespace in its connected networks' DHCP agent hosts.
Closes-Bug: #1609217
Change-Id: I53e20be9b306bf9d3b34ec6a31e3afabd5a0fd6f
(cherry picked from commit 8f057fb49a
)
This commit is contained in:
parent
ec395e44e6
commit
50fdc6505f
@ -75,6 +75,15 @@ Controller node
|
||||
[DEFAULT]
|
||||
router_distributed = True
|
||||
|
||||
.. note::
|
||||
|
||||
For a large scale cloud, if your deployment is running DVR with DHCP,
|
||||
we recommend you set ``host_dvr_for_dhcp=False`` to achieve higher
|
||||
L3 agent router processing performance. When this is set to False,
|
||||
DNS functionality will not be available via the DHCP namespace (dnsmasq)
|
||||
however, a different nameserver will have to be configured, for
|
||||
example, by specifying a value in ``dns_nameservers`` for subnets.
|
||||
|
||||
#. Restart the following services:
|
||||
|
||||
* Server
|
||||
|
@ -162,16 +162,18 @@ class exception_logger(object):
|
||||
return call
|
||||
|
||||
|
||||
def get_other_dvr_serviced_device_owners():
|
||||
def get_other_dvr_serviced_device_owners(host_dvr_for_dhcp=True):
|
||||
"""Return device_owner names for ports that should be serviced by DVR
|
||||
|
||||
This doesn't return DEVICE_OWNER_COMPUTE_PREFIX since it is a
|
||||
prefix, not a complete device_owner name, so should be handled
|
||||
separately (see is_dvr_serviced() below)
|
||||
"""
|
||||
return [n_const.DEVICE_OWNER_LOADBALANCER,
|
||||
n_const.DEVICE_OWNER_LOADBALANCERV2,
|
||||
n_const.DEVICE_OWNER_DHCP]
|
||||
device_owners = [n_const.DEVICE_OWNER_LOADBALANCER,
|
||||
n_const.DEVICE_OWNER_LOADBALANCERV2]
|
||||
if host_dvr_for_dhcp:
|
||||
device_owners.append(n_const.DEVICE_OWNER_DHCP)
|
||||
return device_owners
|
||||
|
||||
|
||||
def get_dvr_allowed_address_pair_device_owners():
|
||||
|
@ -25,6 +25,12 @@ ROUTER_DISTRIBUTED_OPTS = [
|
||||
default=True,
|
||||
help=_("Determine if setup is configured for DVR. If False, "
|
||||
"DVR API extension will be disabled.")),
|
||||
cfg.BoolOpt('host_dvr_for_dhcp',
|
||||
default=True,
|
||||
help=_("Flag to determine if hosting a DVR local router to "
|
||||
"the DHCP agent is desired. If False, any L3 function "
|
||||
"supported by the DHCP agent instance will not be "
|
||||
"possible, for instance: DNS.")),
|
||||
]
|
||||
|
||||
|
||||
|
@ -33,6 +33,7 @@ from sqlalchemy import or_
|
||||
|
||||
from neutron.common import utils
|
||||
from neutron.conf.db import dvr_mac_db
|
||||
from neutron.conf.db import l3_dvr_db
|
||||
from neutron.db import models_v2
|
||||
from neutron.extensions import dvr as ext_dvr
|
||||
from neutron.objects import router
|
||||
@ -42,6 +43,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
dvr_mac_db.register_db_dvr_mac_opts()
|
||||
l3_dvr_db.register_db_l3_dvr_opts()
|
||||
|
||||
|
||||
@registry.has_registry_receivers
|
||||
@ -151,6 +153,7 @@ class DVRDbMixin(ext_dvr.DVRMacAddressPluginBase):
|
||||
:param subnet: subnet id to match and extract ports of interest
|
||||
:returns: list -- Ports on the given subnet in the input host
|
||||
"""
|
||||
host_dvr_for_dhcp = cfg.CONF.host_dvr_for_dhcp
|
||||
filters = {'fixed_ips': {'subnet_id': [subnet]},
|
||||
portbindings.HOST_ID: [host]}
|
||||
ports_query = self.plugin._get_ports_query(context, filters=filters)
|
||||
@ -158,7 +161,7 @@ class DVRDbMixin(ext_dvr.DVRMacAddressPluginBase):
|
||||
models_v2.Port.device_owner.startswith(
|
||||
constants.DEVICE_OWNER_COMPUTE_PREFIX),
|
||||
models_v2.Port.device_owner.in_(
|
||||
utils.get_other_dvr_serviced_device_owners()))
|
||||
utils.get_other_dvr_serviced_device_owners(host_dvr_for_dhcp)))
|
||||
ports_query = ports_query.filter(owner_filter)
|
||||
ports = [
|
||||
self.plugin._make_port_dict(port, process_extensions=False)
|
||||
|
@ -22,11 +22,12 @@ from neutron_lib import constants as n_const
|
||||
from neutron_lib.exceptions import l3 as l3_exc
|
||||
from neutron_lib.plugins import constants as plugin_constants
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from sqlalchemy import or_
|
||||
|
||||
from neutron.common import utils as n_utils
|
||||
|
||||
from neutron.conf.db import l3_dvr_db as l3_dvr_db_conf
|
||||
from neutron.db import agentschedulers_db
|
||||
from neutron.db import l3_agentschedulers_db as l3agent_sch_db
|
||||
from neutron.db import l3_dvr_db
|
||||
@ -37,6 +38,7 @@ from neutron.plugins.ml2 import db as ml2_db
|
||||
from neutron.plugins.ml2 import models as ml2_models
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
l3_dvr_db_conf.register_db_l3_dvr_opts()
|
||||
|
||||
|
||||
class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin):
|
||||
@ -334,6 +336,7 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin):
|
||||
|
||||
def _get_dvr_hosts_for_subnets(self, context, subnet_ids):
|
||||
"""Get a list of hosts with DVR servicable ports on subnet_ids."""
|
||||
host_dvr_dhcp = cfg.CONF.host_dvr_for_dhcp
|
||||
Binding = ml2_models.PortBinding
|
||||
Port = models_v2.Port
|
||||
IPAllocation = models_v2.IPAllocation
|
||||
@ -345,12 +348,13 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin):
|
||||
owner_filter = or_(
|
||||
Port.device_owner.startswith(n_const.DEVICE_OWNER_COMPUTE_PREFIX),
|
||||
Port.device_owner.in_(
|
||||
n_utils.get_other_dvr_serviced_device_owners()))
|
||||
n_utils.get_other_dvr_serviced_device_owners(host_dvr_dhcp)))
|
||||
query = query.filter(owner_filter)
|
||||
hosts = [item[0] for item in query if item[0] != '']
|
||||
return hosts
|
||||
|
||||
def _get_dvr_subnet_ids_on_host_query(self, context, host):
|
||||
host_dvr_dhcp = cfg.CONF.host_dvr_for_dhcp
|
||||
query = context.session.query(
|
||||
models_v2.IPAllocation.subnet_id).distinct()
|
||||
query = query.join(models_v2.IPAllocation.port)
|
||||
@ -360,7 +364,7 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin):
|
||||
models_v2.Port.device_owner.startswith(
|
||||
n_const.DEVICE_OWNER_COMPUTE_PREFIX),
|
||||
models_v2.Port.device_owner.in_(
|
||||
n_utils.get_other_dvr_serviced_device_owners()))
|
||||
n_utils.get_other_dvr_serviced_device_owners(host_dvr_dhcp)))
|
||||
query = query.filter(owner_filter)
|
||||
return query
|
||||
|
||||
@ -458,6 +462,7 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin):
|
||||
IPAllocation = models_v2.IPAllocation
|
||||
Port = models_v2.Port
|
||||
|
||||
host_dvr_dhcp = cfg.CONF.host_dvr_for_dhcp
|
||||
query = context.session.query(Binding)
|
||||
query = query.join(Binding.port)
|
||||
query = query.join(Port.fixed_ips)
|
||||
@ -469,7 +474,7 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin):
|
||||
models_v2.Port.device_owner.startswith(
|
||||
n_const.DEVICE_OWNER_COMPUTE_PREFIX),
|
||||
models_v2.Port.device_owner.in_(
|
||||
n_utils.get_other_dvr_serviced_device_owners()))
|
||||
n_utils.get_other_dvr_serviced_device_owners(host_dvr_dhcp)))
|
||||
query = query.filter(device_filter)
|
||||
host_filter = or_(
|
||||
ml2_models.PortBinding.host == host,
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
other:
|
||||
- |
|
||||
A new config option, ``host_dvr_for_dhcp``, was added to neutron.conf
|
||||
for DVR to determine whether to host the DVR local router to the
|
||||
scheduled DHCP node(s).
|
Loading…
Reference in New Issue
Block a user