diff --git a/neutron/cmd/status.py b/neutron/cmd/status.py index 639001f836e..b25435a2d18 100644 --- a/neutron/cmd/status.py +++ b/neutron/cmd/status.py @@ -14,6 +14,7 @@ from neutron_lib.utils import runtime from oslo_config import cfg +from oslo_db import options as db_options from oslo_log import log as logging from oslo_upgradecheck import upgradecheck @@ -53,6 +54,7 @@ def setup_conf(conf=cfg.CONF): neutron_conf_base.register_core_common_config_opts(conf) neutron_conf_service.register_service_opts( neutron_conf_service.SERVICE_OPTS, cfg.CONF) + db_options.set_defaults(conf) return conf diff --git a/neutron/cmd/upgrade_checks/checks.py b/neutron/cmd/upgrade_checks/checks.py index d48092a6009..3267b863635 100644 --- a/neutron/cmd/upgrade_checks/checks.py +++ b/neutron/cmd/upgrade_checks/checks.py @@ -12,17 +12,33 @@ # License for the specific language governing permissions and limitations # under the License. +from neutron_lib import constants +from neutron_lib import context +from neutron_lib.db import model_query from oslo_config import cfg +from oslo_serialization import jsonutils from oslo_upgradecheck import upgradecheck from neutron._i18n import _ from neutron.cmd.upgrade_checks import base +from neutron.db.models import agent as agent_model + + +def get_l3_agents(): + filters = {'agent_type': [constants.AGENT_TYPE_L3]} + ctx = context.get_admin_context() + query = model_query.get_collection_query(ctx, + agent_model.Agent, + filters=filters) + return query.all() class CoreChecks(base.BaseChecks): def get_checks(self): return [ + (_("External network bridge"), + self.external_network_bridge_check), (_("Worker counts configured"), self.worker_count_check) ] @@ -40,3 +56,36 @@ class CoreChecks(base.BaseChecks): "has changed. Please see release notes for the new values, " "but it is strongly encouraged for deployers to manually " "set the values for api_workers and rpc_workers.")) + + @staticmethod + def external_network_bridge_check(checker): + if not cfg.CONF.database.connection: + return upgradecheck.Result( + upgradecheck.Code.WARNING, + _("Database connection string is not set. Check of usage of " + "'external_network_bridge' config option in L3 agents " + "can't be done")) + + agents_with_external_bridge = [] + for agent in get_l3_agents(): + config_string = agent.get('configurations') + if not config_string: + continue + config = jsonutils.loads(config_string) + if config.get("external_network_bridge"): + agents_with_external_bridge.append(agent.get("host")) + + if agents_with_external_bridge: + return upgradecheck.Result( + upgradecheck.Code.WARNING, + _("L3 agents on hosts %s are still using " + "'external_network_bridge' config option to provide " + "gateway connectivity. This option is now removed. " + "Migration of routers from those L3 agents will be " + "required to connect them to external network through " + "integration bridge.") % agents_with_external_bridge) + else: + return upgradecheck.Result( + upgradecheck.Code.SUCCESS, + _("L3 agents are using integration bridge to connect external " + "gateways")) diff --git a/neutron/tests/unit/cmd/upgrade_checks/test_checks.py b/neutron/tests/unit/cmd/upgrade_checks/test_checks.py index 8d2e2617188..9d7f17562bd 100644 --- a/neutron/tests/unit/cmd/upgrade_checks/test_checks.py +++ b/neutron/tests/unit/cmd/upgrade_checks/test_checks.py @@ -52,3 +52,30 @@ class TestChecks(base.BaseTestCase): cfg.CONF.set_override("rpc_workers", None) result = checks.CoreChecks.worker_count_check(mock.Mock()) self.assertEqual(Code.WARNING, result.code) + + def test_external_network_bridge_check_good(self): + agents = [ + {'host': 'Host A', 'configurations': '{}'}, + {'host': 'Host B', + 'configurations': '{"external_network_bridge": ""}'} + ] + with mock.patch.object(checks, "get_l3_agents", return_value=agents): + result = checks.CoreChecks.external_network_bridge_check( + mock.Mock()) + self.assertEqual(Code.SUCCESS, result.code) + + def test_external_network_bridge_check_bad(self): + agents = [ + {'host': 'Host A', 'configurations': '{}'}, + {'host': 'Host B', + 'configurations': '{"external_network_bridge": "br-ex"}'}, + {'host': 'Host C', + 'configurations': '{"external_network_bridge": ""}'} + ] + with mock.patch.object(checks, "get_l3_agents", return_value=agents): + result = checks.CoreChecks.external_network_bridge_check( + mock.Mock()) + self.assertEqual(Code.WARNING, result.code) + self.assertIn('Host B', result.details) + self.assertNotIn('Host A', result.details) + self.assertNotIn('Host C', result.details)