diff --git a/neutron/agent/common/base_agent_rpc.py b/neutron/agent/common/base_agent_rpc.py new file mode 100644 index 00000000000..95b336ed683 --- /dev/null +++ b/neutron/agent/common/base_agent_rpc.py @@ -0,0 +1,33 @@ +# Copyright 2024 Red Hat, Inc. +# All Rights Reserved. +# +# 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 rpc as n_rpc +from oslo_messaging import Target + + +class BasePluginApi(object): + """Base agent side of the rpc API""" + def __init__(self, topic, namespace, version): + target = Target( + topic=topic, + namespace=namespace, + version=version) + self.client = n_rpc.get_client(target) + + def get_ports(self, context, port_filters): + # NOTE(mtomaska): The MetadataRpcCallback (server side) API version 1.0 + # exposes get_ports, under the PLUGIN topic and None namespace. + cctxt = self.client.prepare(version='1.0') + return cctxt.call(context, 'get_ports', filters=port_filters) diff --git a/neutron/agent/dhcp/agent.py b/neutron/agent/dhcp/agent.py index f07d9d83d24..d298d4f36f1 100644 --- a/neutron/agent/dhcp/agent.py +++ b/neutron/agent/dhcp/agent.py @@ -25,7 +25,6 @@ from neutron_lib.agent import topics from neutron_lib import constants from neutron_lib import context from neutron_lib import exceptions -from neutron_lib import rpc as n_rpc from oslo_concurrency import lockutils from oslo_config import cfg from oslo_log import helpers as log_helpers @@ -38,6 +37,7 @@ from oslo_utils import netutils from oslo_utils import timeutils from neutron._i18n import _ +from neutron.agent.common import base_agent_rpc from neutron.agent.common import resource_processing_queue as queue from neutron.agent.linux import dhcp from neutron.agent.linux import external_process @@ -844,7 +844,7 @@ class DhcpAgent(manager.Manager): del self._metadata_routers[network.id] -class DhcpPluginApi(object): +class DhcpPluginApi(base_agent_rpc.BasePluginApi): """Agent side of the dhcp rpc API. This class implements the client side of an rpc interface. The server side @@ -864,11 +864,10 @@ class DhcpPluginApi(object): def __init__(self, topic, host): self.host = host - target = oslo_messaging.Target( + super().__init__( topic=topic, namespace=constants.RPC_NAMESPACE_DHCP_PLUGIN, version='1.0') - self.client = n_rpc.get_client(target) @property def context(self): @@ -924,6 +923,11 @@ class DhcpPluginApi(object): if port: return dhcp.DictModel(port) + def get_ports(self, port_filters): + ports = super().get_ports(self.context, port_filters) + if ports: + return [dhcp.DictModel(port) for port in ports] + def dhcp_ready_on_ports(self, port_ids): """Notify the server that DHCP is configured for the port.""" cctxt = self.client.prepare(version='1.5') diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index 66dfebaef3a..9db30410426 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -42,6 +42,7 @@ from neutron.agent.linux import ip_lib from neutron.agent.linux import iptables_manager from neutron.cmd import runtime_checks as checks from neutron.common import _constants as common_constants +from neutron.common.ovn import constants as ovn_constants from neutron.common.ovn import utils as ovn_utils from neutron.common import utils as common_utils from neutron.ipam import utils as ipam_utils @@ -1210,11 +1211,16 @@ class Dnsmasq(DhcpLocalProcess): return name def _get_ovn_metadata_port_ip(self, subnet): - m_ports = [port for port in self.network.ports if - ovn_utils.is_ovn_metadata_port(port)] - if m_ports: - port = self.device_manager.plugin.get_dhcp_port(m_ports[0].id) - for fixed_ip in port.fixed_ips: + """Check if provided subnet contains OVN metadata port""" + ports_result = self.device_manager.plugin.get_ports( + port_filters={ + 'device_owner': [constants.DEVICE_OWNER_DISTRIBUTED], + 'device_id': + [ovn_constants.OVN_METADATA_PREFIX + self.network.id] + }, + ) + if ports_result: + for fixed_ip in ports_result[0].get('fixed_ips', []): if fixed_ip.subnet_id == subnet.id: return fixed_ip.ip_address diff --git a/neutron/agent/metadata/agent.py b/neutron/agent/metadata/agent.py index f0c030f76db..c3d94979ed9 100644 --- a/neutron/agent/metadata/agent.py +++ b/neutron/agent/metadata/agent.py @@ -19,17 +19,16 @@ import netaddr from neutron_lib.agent import topics from neutron_lib import constants from neutron_lib import context -from neutron_lib import rpc as n_rpc from neutron_lib.utils import host from oslo_config import cfg from oslo_log import log as logging -import oslo_messaging from oslo_service import loopingcall from oslo_utils import netutils import requests import webob from neutron._i18n import _ +from neutron.agent.common import base_agent_rpc from neutron.agent.linux import utils as agent_utils from neutron.agent import rpc as agent_rpc from neutron.common import cache_utils as cache @@ -46,7 +45,7 @@ MODE_MAP = { } -class MetadataPluginAPI(object): +class MetadataPluginAPI(base_agent_rpc.BasePluginApi): """Agent-side RPC for metadata agent-to-plugin interaction. This class implements the client side of an rpc interface used by the @@ -61,15 +60,10 @@ class MetadataPluginAPI(object): """ def __init__(self, topic): - target = oslo_messaging.Target( + super().__init__( topic=topic, namespace=constants.RPC_NAMESPACE_METADATA, version='1.0') - self.client = n_rpc.get_client(target) - - def get_ports(self, context, filters): - cctxt = self.client.prepare() - return cctxt.call(context, 'get_ports', filters=filters) class MetadataProxyHandler(object): diff --git a/neutron/tests/unit/agent/linux/test_dhcp.py b/neutron/tests/unit/agent/linux/test_dhcp.py index c3474180790..b7852f9dd3f 100644 --- a/neutron/tests/unit/agent/linux/test_dhcp.py +++ b/neutron/tests/unit/agent/linux/test_dhcp.py @@ -74,8 +74,11 @@ class DhcpOpt(object): # A base class where class attributes can also be accessed by treating # an instance as a dict. class Dictable(object): - def __getitem__(self, k): - return self.__dict__.get(k) + def __getitem__(self, k, default_value=None): + return self.__dict__.get(k, default_value) + + def get(self, k, default_value=None): + return self.__getitem__(k, default_value) class FakeDhcpPort(Dictable): @@ -3207,8 +3210,8 @@ class TestDnsmasq(TestBase): def test__generate_opts_per_subnet_with_metadata_port(self): config = {'enable_isolated_metadata': False, 'force_metadata': False} - self.mock_mgr.return_value.plugin.get_dhcp_port.return_value = \ - FakeOvnMetadataPort() + self.mock_mgr.return_value.plugin.get_ports.return_value = \ + [FakeOvnMetadataPort()] self._test__generate_opts_per_subnet_helper(config, True, network_class=FakeNetworkDhcpandOvnMetadataPort)