diff --git a/kuryr_kubernetes/cmd/sanity/__init__.py b/kuryr_kubernetes/cmd/sanity/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/kuryr_kubernetes/cmd/sanity/checks.py b/kuryr_kubernetes/cmd/sanity/checks.py new file mode 100644 index 000000000..9c3c9b009 --- /dev/null +++ b/kuryr_kubernetes/cmd/sanity/checks.py @@ -0,0 +1,85 @@ +# Copyright (c) 2021 OpenStack Foundation. +# 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 oslo_config import cfg +from oslo_log import log as logging + +from kuryr_kubernetes import config + +CONF = config.CONF +LOG = logging.getLogger(__name__) + + +def _logger(): + if cfg.CONF.sanity_check_error: + return LOG.error + else: + return LOG.warning + + +def ports_pool_min_max(): + try: + if not cfg.CONF.vif_pool.ports_pool_max: + return True + pool_max = cfg.CONF.vif_pool.ports_pool_max + pool_min = cfg.CONF.vif_pool.ports_pool_min + if pool_max < pool_min: + _logger()(f'The current configuration of ports_pool_min ' + f'"{pool_min}" and ports_pool_max "{pool_max}" ' + f'may cause infinite loop of creating ' + f'and deleting ports.') + return False + except (OSError, RuntimeError, IndexError, ValueError) as e: + LOG.debug("Exception while checking ports_pool_max. " + "Exception: %s", e) + return False + return True + + +def ports_pool_min_batch(): + try: + pool_min = cfg.CONF.vif_pool.ports_pool_min + pool_batch = cfg.CONF.vif_pool.ports_pool_batch + if pool_min > pool_batch: + _logger()(f'The current configuration of ports_pool_min ' + f'"{pool_min}" and ports_pool_batch "{pool_batch}" ' + f'may cause kuryr to send multiple unnecessary ' + f'bulk ports creation requests. ') + return False + except (OSError, RuntimeError, IndexError, ValueError) as e: + LOG.debug("Exception while checking ports_pool_batch. " + "Exception: %s", e) + return False + return True + + +def ports_pool_max_batch(): + try: + if not cfg.CONF.vif_pool.ports_pool_max: + return True + pool_max = cfg.CONF.vif_pool.ports_pool_max + pool_batch = cfg.CONF.vif_pool.ports_pool_batch + if pool_max < pool_batch: + _logger()(f'The current configuration of ports_pool_max ' + f'"{pool_max}" and ports_pool_batch "{pool_batch}" ' + f'may cause kuryr to create the ' + f'ports and then delete them immediately.') + return False + except (OSError, RuntimeError, IndexError, ValueError) as e: + LOG.debug("Exception while checking ports_pool_batch. " + "Exception: %s", e) + return False + return True diff --git a/kuryr_kubernetes/cmd/sanity_checks.py b/kuryr_kubernetes/cmd/sanity_checks.py new file mode 100644 index 000000000..237b9b02d --- /dev/null +++ b/kuryr_kubernetes/cmd/sanity_checks.py @@ -0,0 +1,105 @@ +# Copyright (c) 2021 OpenStack Foundation. +# 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. + +""" +CLI interface for kuryr sanity commands. +""" + +import sys + +from oslo_config import cfg +from oslo_log import log as logging + +from kuryr_kubernetes.cmd.sanity import checks +from kuryr_kubernetes import config +from kuryr_kubernetes.controller.drivers import vif_pool # noqa + +LOG = logging.getLogger(__name__) + + +class BoolOptCallback(cfg.BoolOpt): + def __init__(self, name, callback, **kwargs): + if 'default' not in kwargs: + kwargs['default'] = False + self.callback = callback + super(BoolOptCallback, self).__init__(name, **kwargs) + + +def check_ports_pool_min_max(): + result = checks.ports_pool_min_max() + if not result: + LOG.warning("The ports_pool_max is enabled, " + "the ports_pool_min should be smaller than " + "ports_pool_max. Either disable ports_pool_max " + "setting it to 0 or increase it's value.") + return result + + +def check_ports_pool_min_batch(): + result = checks.ports_pool_min_batch() + if not result: + LOG.warning("The ports_pool_min should be lower than " + "ports_pool_batch. Please decrease it's value.") + return result + + +def check_ports_pool_max_batch(): + result = checks.ports_pool_max_batch() + if not result: + LOG.warning("The ports_pool_max is enabled, " + "the ports_pool_max should be higher than " + "ports_pool_batch. Either disable ports_pool_max " + "setting it to 0 or decrease it's value.") + return result + + +# Define CLI opts to test specific features, with a callback for the test +OPTS = [ + BoolOptCallback('vif_pool_min_max', check_ports_pool_min_max, + default=False, + help='Check configuration sanity of ports_pool_min and ' + 'ports_pool_max.'), + BoolOptCallback('vif_pool_min_batch', check_ports_pool_min_batch, + default=False, + help='Check configuration sanity of ports_pool_min and ' + 'ports_pool_batch.'), + BoolOptCallback('vif_pool_max_batch', check_ports_pool_max_batch, + default=False, + help='Check configuration sanity of ports_pool_max and ' + 'ports_pool_batch.'), +] + +CLI_OPTS = [ + cfg.BoolOpt('sanity_check_error', default=False, + help='If this flag is configured, the sanity command fails ' + 'if any of the sanity tests fails.'), +] + + +def all_tests_passed(): + results = [opt.callback() for opt in OPTS if cfg.CONF.get(opt.name)] + return all(results) + + +def main(): + cfg.CONF.register_cli_opts(OPTS) + cfg.CONF.register_cli_opts(CLI_OPTS) + config.init(sys.argv[1:], default_config_files=['/etc/kuryr/kuryr.conf']) + config.setup_logging() + return 0 if all_tests_passed() else 1 + + +if __name__ == '__main__': + main() diff --git a/setup.cfg b/setup.cfg index bdf42d01f..841608294 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,6 +31,7 @@ console_scripts = kuryr-k8s-controller = kuryr_kubernetes.cmd.eventlet.controller:start kuryr-daemon = kuryr_kubernetes.cmd.daemon:start kuryr-cni = kuryr_kubernetes.cmd.cni:run + kuryr-k8s-sanity = kuryr_kubernetes.cmd.sanity_checks:main kuryr-k8s-status = kuryr_kubernetes.cmd.status:main kuryr_kubernetes.vif_translators =