diff --git a/neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py b/neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py index ced6a023bf8..e0e15092641 100644 --- a/neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py +++ b/neutron/api/rpc/agentnotifiers/dhcp_rpc_agent_api.py @@ -220,7 +220,7 @@ class DhcpAgentNotifyAPI(object): enabled_agents = self._get_enabled_agents( context, network, agents, method, payload) - if method == 'port_create_end': + if method == 'port_create_end' and enabled_agents: high_agent = enabled_agents.pop( random.randint(0, len(enabled_agents) - 1)) self._notify_high_priority_agent( diff --git a/neutron/api/rpc/handlers/dhcp_rpc.py b/neutron/api/rpc/handlers/dhcp_rpc.py index 232d6f71eb5..cc34c0b1d23 100644 --- a/neutron/api/rpc/handlers/dhcp_rpc.py +++ b/neutron/api/rpc/handlers/dhcp_rpc.py @@ -23,6 +23,7 @@ from neutron_lib.callbacks import resources from neutron_lib import constants from neutron_lib.db import api as db_api from neutron_lib import exceptions +from neutron_lib.exceptions import agent as agent_exc from neutron_lib.plugins import directory from neutron_lib.plugins import utils as p_utils from oslo_config import cfg @@ -88,6 +89,20 @@ class DhcpRpcCallback(object): nets = plugin.list_active_networks_on_active_dhcp_agent( context, host) else: + # If no active DHCP agent or agent admin state is DOWN, + # return empty network list for RPC to avoid unexpected + # resource creation on remote host when the DHCP agent + # scheduler extension is not supported. + try: + agent = plugin._get_agent_by_type_and_host( + context, constants.AGENT_TYPE_DHCP, host) + except agent_exc.AgentNotFoundByTypeHost: + LOG.debug("DHCP Agent not found on host %s", host) + return [] + if not agent.admin_state_up: + LOG.debug("DHCP Agent admin state is down on host %s", host) + return [] + filters = dict(admin_state_up=[True]) nets = plugin.get_networks(context, filters=filters) return nets diff --git a/neutron/conf/common.py b/neutron/conf/common.py index b44d09dd568..a2047944b19 100644 --- a/neutron/conf/common.py +++ b/neutron/conf/common.py @@ -145,7 +145,14 @@ core_opts = [ "Setting to any positive integer means that on failure " "the connection is retried that many times. " "For example, setting to 3 means total attempts to " - "connect will be 4.")) + "connect will be 4.")), + cfg.BoolOpt('enable_traditional_dhcp', default=True, + help=_('If False, neutron-server will disable the following ' + 'DHCP-agent related functions:' + '1. DHCP provisioning block ' + '2. DHCP scheduler API extension ' + '3. Network scheduling mechanism ' + '4. DHCP RPC/notification')), ] core_cli_opts = [ diff --git a/neutron/extensions/dhcpagentscheduler.py b/neutron/extensions/dhcpagentscheduler.py index e84b42502a0..53f984ad41e 100644 --- a/neutron/extensions/dhcpagentscheduler.py +++ b/neutron/extensions/dhcpagentscheduler.py @@ -22,12 +22,16 @@ from neutron_lib.api import extensions as api_extensions from neutron_lib.api import faults from neutron_lib.plugins import directory from neutron_lib import rpc as n_rpc +from oslo_config import cfg +from oslo_log import log as logging from neutron.api import extensions from neutron.api.v2 import resource from neutron import policy from neutron import wsgi +LOG = logging.getLogger(__name__) + class NetworkSchedulerController(wsgi.Controller): def index(self, request, **kwargs): @@ -126,3 +130,10 @@ def notify(context, action, network_id, agent_id): info = {'id': agent_id, 'network_id': network_id} notifier = n_rpc.get_notifier('network') notifier.info(context, action, {'agent': info}) + + +def disable_extension_by_config(aliases): + if not cfg.CONF.enable_traditional_dhcp: + if 'dhcp_agent_scheduler' in aliases: + aliases.remove('dhcp_agent_scheduler') + LOG.info('Disabled dhcp_agent_scheduler extension.') diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index 0eba6eb0ae9..889dae77fa2 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -119,6 +119,7 @@ from neutron.db import securitygroups_rpc_base as sg_db_rpc from neutron.db import segments_db from neutron.db import subnet_service_type_mixin from neutron.db import vlantransparent_db +from neutron.extensions import dhcpagentscheduler as dhcp_ext from neutron.extensions import filter_validation from neutron.extensions import vlantransparent from neutron.ipam import exceptions as ipam_exc @@ -239,6 +240,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, sg_rpc.disable_security_group_extension_by_config(aliases) vlantransparent._disable_extension_by_config(aliases) filter_validation._disable_extension_by_config(aliases) + dhcp_ext.disable_extension_by_config(aliases) self._aliases = self._filter_extensions_by_mech_driver(aliases) return self._aliases @@ -288,6 +290,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, def _setup_dhcp(self): """Initialize components to support DHCP.""" + if not cfg.CONF.enable_traditional_dhcp: + return self.network_scheduler = importutils.import_object( cfg.CONF.network_scheduler_driver ) @@ -366,9 +370,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, """Initialize RPC notifiers for agents.""" self.ovo_notifier = ovo_rpc.OVOServerRpcInterface() self.notifier = rpc.AgentNotifierApi(topics.AGENT) - self.agent_notifiers[const.AGENT_TYPE_DHCP] = ( - dhcp_rpc_agent_api.DhcpAgentNotifyAPI() - ) + if cfg.CONF.enable_traditional_dhcp: + self.agent_notifiers[const.AGENT_TYPE_DHCP] = ( + dhcp_rpc_agent_api.DhcpAgentNotifyAPI() + ) @log_helpers.log_method_call def start_rpc_listeners(self): @@ -1375,6 +1380,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, raise psec_exc.PortSecurityAndIPRequiredForSecurityGroups() def _setup_dhcp_agent_provisioning_component(self, context, port): + if not cfg.CONF.enable_traditional_dhcp: + 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, diff --git a/releasenotes/notes/config_disable_traditional_dhcp-e553e2bd327c37c5.yaml b/releasenotes/notes/config_disable_traditional_dhcp-e553e2bd327c37c5.yaml new file mode 100644 index 00000000000..271d564c902 --- /dev/null +++ b/releasenotes/notes/config_disable_traditional_dhcp-e553e2bd327c37c5.yaml @@ -0,0 +1,10 @@ +--- +other: + - | + Added a new config option ``enable_traditional_dhcp`` for neutron server, + if it is set to False, neutron server will disable DHCP provisioning + block, DHCP scheduler API extension, network scheduling mechanism and + DHCP RPC/notification. This option can be used with the + ``dhcp`` extension of the OVS agent to enable distributed DHCP, or + for a deployment which needs + to disable the DHCP agent related functions permanently.