diff options
-rw-r--r-- | oslo_middleware/healthcheck/__init__.py | 3 | ||||
-rw-r--r-- | oslo_middleware/healthcheck/disable_by_file.py | 53 | ||||
-rw-r--r-- | oslo_middleware/healthcheck/pluginbase.py | 2 | ||||
-rw-r--r-- | oslo_middleware/tests/test_healthcheck.py | 41 | ||||
-rw-r--r-- | setup.cfg | 1 |
5 files changed, 94 insertions, 6 deletions
diff --git a/oslo_middleware/healthcheck/__init__.py b/oslo_middleware/healthcheck/__init__.py index 9e46bd8..d3b6a35 100644 --- a/oslo_middleware/healthcheck/__init__.py +++ b/oslo_middleware/healthcheck/__init__.py @@ -343,7 +343,8 @@ class Healthcheck(base.ConfigurableMiddleware): def process_request(self, req): if req.path != self._path: return None - results = [ext.obj.healthcheck() for ext in self._backends] + results = [ext.obj.healthcheck(req.server_port) + for ext in self._backends] healthy = self._are_results_healthy(results) if req.method == "HEAD": functor = self._make_head_response diff --git a/oslo_middleware/healthcheck/disable_by_file.py b/oslo_middleware/healthcheck/disable_by_file.py index cd438cf..e422f91 100644 --- a/oslo_middleware/healthcheck/disable_by_file.py +++ b/oslo_middleware/healthcheck/disable_by_file.py @@ -22,6 +22,57 @@ from oslo_middleware.healthcheck import pluginbase LOG = logging.getLogger(__name__) +class DisableByFilesPortsHealthcheck(pluginbase.HealthcheckBaseExtension): + """DisableByFilesPorts healthcheck middleware plugin + + This plugin checks presence of a file that is provided for a application + running on a certain port to report if the service is unavailable + or not. + + Example of middleware configuration: + + .. code-block:: ini + + [filter:healthcheck] + paste.filter_factory = oslo_middleware:Healthcheck.factory + path = /healthcheck + backends = disable_by_files_ports + disable_by_file_paths = 5000:/var/run/keystone/healthcheck_disable, \ + 35357:/var/run/keystone/admin_healthcheck_disable + """ + def __init__(self, conf): + super(DisableByFilesPortsHealthcheck, self).__init__(conf) + self.status_files = {} + self.status_files.update( + self._iter_paths_ports(self.conf.get('disable_by_file_paths'))) + + @staticmethod + def _iter_paths_ports(paths): + if paths: + for port_path in paths.split(","): + port_path = port_path.strip() + if port_path: + port, path = port_path.split(":") + port = int(port) + yield (port, path) + + def healthcheck(self, server_port): + path = self.status_files.get(server_port) + if not path: + LOG.warning(_LW('DisableByFilesPorts healthcheck middleware' + ' enabled without disable_by_file_paths set' + ' for port %s') % server_port) + return pluginbase.HealthcheckResult(available=True, + reason="OK") + else: + if not os.path.exists(path): + return pluginbase.HealthcheckResult(available=True, + reason="OK") + else: + return pluginbase.HealthcheckResult(available=False, + reason="DISABLED BY FILE") + + class DisableByFileHealthcheck(pluginbase.HealthcheckBaseExtension): """DisableByFile healthcheck middleware plugin @@ -39,7 +90,7 @@ class DisableByFileHealthcheck(pluginbase.HealthcheckBaseExtension): disable_by_file_path = /var/run/nova/healthcheck_disable """ - def healthcheck(self): + def healthcheck(self, server_port): path = self.conf.get('disable_by_file_path') if path is None: LOG.warning(_LW('DisableByFile healthcheck middleware enabled ' diff --git a/oslo_middleware/healthcheck/pluginbase.py b/oslo_middleware/healthcheck/pluginbase.py index ffd3e08..e95749c 100644 --- a/oslo_middleware/healthcheck/pluginbase.py +++ b/oslo_middleware/healthcheck/pluginbase.py @@ -28,7 +28,7 @@ class HealthcheckBaseExtension(object): self.conf = conf @abc.abstractmethod - def healthcheck(): + def healthcheck(self, server_port): """method called by the healthcheck middleware return: HealthcheckResult object diff --git a/oslo_middleware/tests/test_healthcheck.py b/oslo_middleware/tests/test_healthcheck.py index 144d274..3ffb03f 100644 --- a/oslo_middleware/tests/test_healthcheck.py +++ b/oslo_middleware/tests/test_healthcheck.py @@ -29,18 +29,21 @@ class HealthcheckTests(test_base.BaseTestCase): return 'Hello, World!!!' def _do_test_request(self, conf={}, path='/healthcheck', - accept='text/plain', method='GET'): + accept='text/plain', method='GET', + server_port=80): self.app = healthcheck.Healthcheck(self.application, conf) req = webob.Request.blank(path, accept=accept, method=method) + req.server_port = server_port res = req.get_response(self.app) return res def _do_test(self, conf={}, path='/healthcheck', expected_code=webob.exc.HTTPOk.code, expected_body=b'', accept='text/plain', - method='GET'): + method='GET', server_port=80): res = self._do_test_request(conf=conf, path=path, - accept=accept, method=method) + accept=accept, method=method, + server_port=server_port) self.assertEqual(expected_code, res.status_int) self.assertEqual(expected_body, res.body) @@ -125,3 +128,35 @@ class HealthcheckTests(test_base.BaseTestCase): expected_code=webob.exc.HTTPServiceUnavailable.code, expected_body=b'DISABLED BY FILE\nDISABLED BY FILE') self.assertIn('disable_by_file', self.app._backends.names()) + + def test_disable_by_port_file(self): + filename = self.create_tempfiles([('test', 'foobar')])[0] + conf = {'backends': 'disable_by_files_ports', + 'disable_by_file_paths': "80:%s" % filename} + self._do_test(conf, + expected_code=webob.exc.HTTPServiceUnavailable.code, + expected_body=b'DISABLED BY FILE') + self.assertIn('disable_by_files_ports', self.app._backends.names()) + + def test_no_disable_by_port_file(self): + filename = self.create_tempfiles([('test', 'foobar')])[0] + conf = {'backends': 'disable_by_files_ports', + 'disable_by_file_paths': "8000:%s" % filename} + self._do_test(conf, + expected_code=webob.exc.HTTPOk.code, + expected_body=b'OK') + self.assertIn('disable_by_files_ports', self.app._backends.names()) + + def test_disable_by_port_many_files(self): + filename = self.create_tempfiles([('test', 'foobar')])[0] + filename2 = self.create_tempfiles([('test2', 'foobar2')])[0] + conf = {'backends': 'disable_by_files_ports', + 'disable_by_file_paths': "80:%s,81:%s" % (filename, filename2)} + self._do_test(conf, + expected_code=webob.exc.HTTPServiceUnavailable.code, + expected_body=b'DISABLED BY FILE') + self._do_test(conf, + expected_code=webob.exc.HTTPServiceUnavailable.code, + expected_body=b'DISABLED BY FILE', + server_port=81) + self.assertIn('disable_by_files_ports', self.app._backends.names()) @@ -36,6 +36,7 @@ oslo.config.opts = oslo.middleware.healthcheck = disable_by_file = oslo_middleware.healthcheck.disable_by_file:DisableByFileHealthcheck + disable_by_files_ports = oslo_middleware.healthcheck.disable_by_file:DisableByFilesPortsHealthcheck [build_sphinx] source-dir = doc/source |