From 829f3e09623dc5f4a6f6ef9ebf3c332f9affafc7 Mon Sep 17 00:00:00 2001 From: Oleg Bondarev Date: Fri, 15 Nov 2013 16:21:42 +0400 Subject: [PATCH] Add state reporting to the metadata agent Need to add state reporting in order metadata agent to appear in Neutron's agent list output Closes-Bug: #1250369 Change-Id: I3a001e065004685d9702e817336e5d4923597791 --- neutron/agent/metadata/agent.py | 46 +++++++++++++++++++++++ neutron/common/constants.py | 1 + neutron/tests/unit/test_metadata_agent.py | 20 ++++++++++ 3 files changed, 67 insertions(+) diff --git a/neutron/agent/metadata/agent.py b/neutron/agent/metadata/agent.py index dcb0e00a53..60fcc4bc3a 100644 --- a/neutron/agent/metadata/agent.py +++ b/neutron/agent/metadata/agent.py @@ -28,9 +28,15 @@ from neutronclient.v2_0 import client from oslo.config import cfg import webob +from neutron.agent.common import config as agent_conf +from neutron.agent import rpc as agent_rpc from neutron.common import config +from neutron.common import constants as n_const +from neutron.common import topics from neutron.common import utils +from neutron import context from neutron.openstack.common import log as logging +from neutron.openstack.common import loopingcall from neutron import wsgi LOG = logging.getLogger(__name__) @@ -222,6 +228,45 @@ class UnixDomainMetadataProxy(object): else: os.makedirs(dirname, 0o755) + self._init_state_reporting() + + def _init_state_reporting(self): + self.context = context.get_admin_context_without_session() + self.state_rpc = agent_rpc.PluginReportStateAPI(topics.PLUGIN) + self.agent_state = { + 'binary': 'neutron-metadata-agent', + 'host': cfg.CONF.host, + 'topic': 'N/A', + 'configurations': { + 'metadata_proxy_socket': cfg.CONF.metadata_proxy_socket, + 'nova_metadata_ip': cfg.CONF.nova_metadata_ip, + 'nova_metadata_port': cfg.CONF.nova_metadata_port, + }, + 'start_flag': True, + 'agent_type': n_const.AGENT_TYPE_METADATA} + report_interval = cfg.CONF.AGENT.report_interval + if report_interval: + self.heartbeat = loopingcall.FixedIntervalLoopingCall( + self._report_state) + self.heartbeat.start(interval=report_interval) + + def _report_state(self): + try: + self.state_rpc.report_state( + self.context, + self.agent_state, + use_call=self.agent_state.get('start_flag')) + except AttributeError: + # This means the server does not support report_state + LOG.warn(_('Neutron server does not support state report.' + ' State report for this agent will be disabled.')) + self.heartbeat.stop() + return + except Exception: + LOG.exception(_("Failed reporting state!")) + return + self.agent_state.pop('start_flag', None) + def run(self): server = UnixDomainWSGIServer('neutron-metadata-agent') server.start(MetadataProxyHandler(self.conf), @@ -233,6 +278,7 @@ def main(): eventlet.monkey_patch() cfg.CONF.register_opts(UnixDomainMetadataProxy.OPTS) cfg.CONF.register_opts(MetadataProxyHandler.OPTS) + agent_conf.register_agent_state_opts_helper(cfg.CONF) cfg.CONF(project='neutron') config.setup_logging(cfg.CONF) utils.log_opt_values(LOG) diff --git a/neutron/common/constants.py b/neutron/common/constants.py index dfa8f1fd92..a55e1bfb79 100644 --- a/neutron/common/constants.py +++ b/neutron/common/constants.py @@ -71,6 +71,7 @@ AGENT_TYPE_L3 = 'L3 agent' AGENT_TYPE_LOADBALANCER = 'Loadbalancer agent' AGENT_TYPE_MLNX = 'Mellanox plugin agent' AGENT_TYPE_METERING = 'Metering agent' +AGENT_TYPE_METADATA = 'Metadata agent' L2_AGENT_TOPIC = 'N/A' PAGINATION_INFINITE = 'infinite' diff --git a/neutron/tests/unit/test_metadata_agent.py b/neutron/tests/unit/test_metadata_agent.py index 36b6f842f0..f944676dfc 100644 --- a/neutron/tests/unit/test_metadata_agent.py +++ b/neutron/tests/unit/test_metadata_agent.py @@ -381,3 +381,23 @@ class TestUnixDomainMetadataProxy(base.BaseTestCase): mock.call(cfg.CONF), mock.call().run()] ) + + def test_init_state_reporting(self): + with mock.patch('neutron.openstack.common.loopingcall.' + 'FixedIntervalLoopingCall') as loop_call: + with mock.patch('os.makedirs'): + proxy = agent.UnixDomainMetadataProxy(mock.Mock()) + loop_call.assert_called_once_with(proxy._report_state) + loop_call.return_value.start.assert_called_once_with( + interval=mock.ANY) + + def test_report_state(self): + with mock.patch('neutron.agent.rpc.PluginReportStateAPI') as state_api: + with mock.patch('os.makedirs'): + proxy = agent.UnixDomainMetadataProxy(mock.Mock()) + self.assertTrue(proxy.agent_state['start_flag']) + proxy._report_state() + self.assertNotIn('start_flag', proxy.agent_state) + state_api_inst = state_api.return_value + state_api_inst.report_state.assert_called_once_with( + proxy.context, proxy.agent_state, use_call=True)