oslomiddleware(1)
| OSLOMIDDLEWARE(1) | oslo.middleware | OSLOMIDDLEWARE(1) |
NAME
oslomiddleware - oslo.middleware 6.6.0 Latest VersionDownloads
Oslo middleware library includes components that can be injected into wsgi pipelines to intercept request/response flows. The base class can be enhanced with functionality like add/delete/modification of http headers and support for limiting size/connection etc.
- Free software: Apache license
- Documentation: https://docs.openstack.org/oslo.middleware/latest/
- Source: https://opendev.org/openstack/oslo.middleware
- Bugs: https://bugs.launchpad.net/oslo.middleware
- Release notes: https://docs.openstack.org/releasenotes/oslo.middleware/
CONTENTS
Installation
At the command line:
$ pip install oslo.middleware
Or, if you have virtualenvwrapper installed:
$ mkvirtualenv oslo.middleware $ pip install oslo.middleware
Contributing
If you would like to contribute to the development of oslo's libraries, first you must take a look to this page:
If you would like to contribute to the development of OpenStack, you must follow the steps in this page:
Once those steps have been completed, changes to OpenStack should be submitted for review via the Gerrit tool, following the workflow documented at:
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
Middlewares and configuration
Middlewares can be configured in multiple fashion depending of the application needs. Here is some use-cases:
Configuration from the application
The application code will looks like:
from oslo_middleware import sizelimit from oslo_config import cfg conf = cfg.ConfigOpts() app = sizelimit.RequestBodySizeLimiter(your_wsgi_application, conf)
Configuration with paste-deploy and the oslo.config
The paste filter (in /etc/my_app/api-paste.ini) will looks like:
[filter:sizelimit] use = egg:oslo.middleware#sizelimit # In case of the application doesn't use the global oslo.config # object. The middleware must known the app name to load # the application configuration, by setting this: # oslo_config_project = my_app # In some cases, you may need to specify the program name for the project # as well. # oslo_config_program = my_app-api
The oslo.config file of the application (eg: /etc/my_app/my_app.conf) will looks like:
[oslo_middleware] max_request_body_size=1000
Configuration with pastedeploy only
The paste filter (in /etc/my_app/api-paste.ini) will looks like:
[filter:sizelimit] use = egg:oslo.middleware#sizelimit max_request_body_size=1000
This will override any configuration done via oslo.config
NOTE:
Cross-project features
Many features are common to all the OpenStack services and are consistent in their configuration and deployment patterns. Unless explicitly noted, you can safely assume that the features in this chapter are supported and configured in a consistent manner.
Cross-origin resource sharing
NOTE:
OpenStack supports Cross-Origin Resource Sharing (CORS), a W3C specification defining a contract by which the single-origin policy of a user agent (usually a browser) may be relaxed. It permits the javascript engine to access an API that does not reside on the same domain, protocol, or port.
This feature is most useful to organizations which maintain one or more custom user interfaces for OpenStack, as it permits those interfaces to access the services directly, rather than requiring an intermediate proxy server. It can, however, also be misused by malicious actors; please review the security advisory below for more information.
Enabling CORS with configuration
In most cases, CORS support is built directly into the service itself. To enable it, simply follow the configuration options exposed in the default configuration file, or add it yourself according to the pattern below.
[cors] allowed_origin = https://first_ui.example.com max_age = 3600 allow_methods = GET,POST,PUT,DELETE allow_headers = Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Custom-Header expose_headers = Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Custom-Header
Additional origins can be explicitly added. To express this in your configuration file, first begin with a [cors] group as above, into which you place your default configuration values. Then, add as many additional configuration groups as necessary, naming them [cors.{something}] (each name must be unique). The purpose of the suffix to cors. is legibility, we recommend using a reasonable human-readable string:
[cors.ironic_webclient] # CORS Configuration for a hypothetical ironic webclient, which overrides # authentication allowed_origin = https://ironic.example.com:443 allow_credentials = True [cors.horizon] # CORS Configuration for horizon, which uses global options. allowed_origin = https://horizon.example.com:443 [cors.wildcard] # CORS Configuration for the CORS specified domain wildcard, which only # permits HTTP GET requests. allowed_origin = * allow_methods = GET
For more information about CORS configuration, see cross-origin resource sharing in OpenStack Configuration Reference.
Enabling CORS with PasteDeploy
CORS can also be configured using PasteDeploy. First of all, ensure that OpenStack's oslo_middleware package (version 2.4.0 or later) is available in the Python environment that is running the service. Then, add the following configuration block to your paste.ini file.
[filter:cors] paste.filter_factory = oslo_middleware.cors:filter_factory allowed_origin = https://website.example.com:443 max_age = 3600 allow_methods = GET,POST,PUT,DELETE allow_headers = Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Custom-Header expose_headers = Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Custom-Header
NOTE:
Security concerns
CORS specifies a wildcard character *, which permits access to all user agents, regardless of domain, protocol, or host. While there are valid use cases for this approach, it also permits a malicious actor to create a convincing facsimile of a user interface, and trick users into revealing authentication credentials. Please carefully evaluate your use case and the relevant documentation for any risk to your organization.
NOTE:
Troubleshooting
CORS is very easy to get wrong, as even one incorrect property will violate the prescribed contract. Here are some steps you can take to troubleshoot your configuration.
Check the service log
The CORS middleware used by OpenStack provides verbose debug logging that should reveal most configuration problems. Here are some example log messages, and how to resolve them.
Problem
CORS request from origin 'http://example.com' not permitted.
Solution
A request was received from the origin http://example.com, however this origin was not found in the permitted list. The cause may be a superfluous port notation (ports 80 and 443 do not need to be specified). To correct, ensure that the configuration property for this host is identical to the host indicated in the log message.
Problem
Request method 'DELETE' not in permitted list: GET,PUT,POST
Solution
A user agent has requested permission to perform a DELETE request, however the CORS configuration for the domain does not permit this. To correct, add this method to the allow_methods configuration property.
Problem
Request header 'X-Custom-Header' not in permitted list: X-Other-Header
Solution
A request was received with the header X-Custom-Header, which is not permitted. Add this header to the allow_headers configuration property.
Open your browser's console log
Most browsers provide helpful debug output when a CORS request is rejected. Usually this happens when a request was successful, but the return headers on the response do not permit access to a property which the browser is trying to access.
Manually construct a CORS request
By using curl or a similar tool, you can trigger a CORS response with a properly constructed HTTP request. An example request and response might look like this.
Request example:
$ curl -I -X OPTIONS https://api.example.com/api -H "Origin: https://ui.example.com"
Response example:
HTTP/1.1 204 No Content Content-Length: 0 Access-Control-Allow-Origin: https://ui.example.com Access-Control-Allow-Methods: GET,POST,PUT,DELETE Access-Control-Expose-Headers: origin,authorization,accept,x-total,x-limit,x-marker,x-client,content-type Access-Control-Allow-Headers: origin,authorization,accept,x-total,x-limit,x-marker,x-client,content-type Access-Control-Max-Age: 3600
If the service does not return any access control headers, check the service log, such as /var/log/upstart/ironic-api.log for an indication on what went wrong.
oslo.middleware Reference
API
- class oslo_middleware.BasicAuthMiddleware(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- Middleware which performs HTTP basic authentication on requests
- class oslo_middleware.CORS(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- CORS Middleware.
This middleware allows a WSGI app to serve CORS headers for multiple configured domains.
For more information, see http://www.w3.org/TR/cors/
- add_origin(allowed_origin: str | list[str], allow_credentials: bool = True, expose_headers: list[str] | None = None, max_age: int | None = None, allow_methods: list[str] | None = None, allow_headers: list[str] | None = None) -> None
- Add another origin to this filter.
- Parameters
- allowed_origin -- Protocol, host, and port for the allowed origin.
- allow_credentials -- Whether to permit credentials.
- expose_headers -- A list of headers to expose.
- max_age -- Maximum cache duration.
- allow_methods -- List of HTTP methods to permit.
- allow_headers -- List of HTTP headers to permit from the client.
- Returns
- classmethod factory(global_conf: dict[str, ty.Any] | None, **local_conf: ty.Any) -> ty.Callable[[WSGIApplication], base.MiddlewareType]
- factory method for paste.deploy
allowed_origin: Protocol, host, and port for the allowed origin. allow_credentials: Whether to permit credentials. expose_headers: A list of headers to expose. max_age: Maximum cache duration. allow_methods: List of HTTP methods to permit. allow_headers: List of HTTP headers to permit from the client.
- process_response(response: Response, request: Request | None = None) -> Response
- Check for CORS headers, and decorate if necessary.
Perform two checks. First, if an OPTIONS request was issued, let the application handle it, and (if necessary) decorate the response with preflight headers. In this case, if a 404 is thrown by the underlying application (i.e. if the underlying application does not handle OPTIONS requests, the response code is overridden.
In the case of all other requests, regular request headers are applied.
- class oslo_middleware.CatchErrors(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- Middleware that provides high-level error handling.
It catches all exceptions from subsequent applications in WSGI pipeline to hide internal errors from API response.
- class oslo_middleware.CorrelationId(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- Middleware that attaches a correlation id to WSGI request
- static process_request(req: webob.request.Request) -> webob.response.Response | None
- Called on each request.
If this returns None, the next application down the stack will be executed. If it returns a response then that response will be returned and execution will stop here.
- class oslo_middleware.Debug(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- Helper class that returns debug information.
Can be inserted into any WSGI application chain to get information about the request and response.
- static print_generator(app_iter: Iterable[bytes]) -> Iterator[bytes]
- Prints the contents of a wrapper string iterator when iterated.
- class oslo_middleware.HTTPProxyToWSGI(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- HTTP proxy to WSGI termination middleware.
This middleware overloads WSGI environment variables with the one provided by the remote HTTP reverse proxy.
- process_request(req: webob.request.Request) -> webob.response.Response | None
- Called on each request.
If this returns None, the next application down the stack will be executed. If it returns a response then that response will be returned and execution will stop here.
- class oslo_middleware.Healthcheck(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- Healthcheck application used for monitoring.
It will respond 200 with "OK" as the body. Or a 503 with the reason as the body if one of the backends reports an application issue.
This is useful for the following reasons:
- Load balancers can 'ping' this url to determine service availability.
- Provides an endpoint that is similar to 'mod_status' in apache which can provide details (or no details, depending on if configured) about the activity of the server.
- (and more)
NOTE:
Example requests/responses (not detailed mode):
$ curl -i -X HEAD "http://0.0.0.0:8775/healthcheck"
HTTP/1.1 204 No Content
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
Date: Fri, 11 Sep 2015 18:55:08 GMT
$ curl -i -X GET "http://0.0.0.0:8775/healthcheck"
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 2
Date: Fri, 11 Sep 2015 18:55:43 GMT
OK
$ curl -X GET -i -H "Accept: application/json" "http://0.0.0.0:8775/healthcheck"
HTTP/1.0 200 OK
Date: Wed, 24 Aug 2016 06:09:58 GMT
Content-Type: application/json
Content-Length: 63
{
"detailed": false,
"reasons": [
"OK"
]
}
$ curl -X GET -i -H "Accept: text/html" "http://0.0.0.0:8775/healthcheck"
HTTP/1.0 200 OK
Date: Wed, 24 Aug 2016 06:10:42 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 239
<HTML>
<HEAD><TITLE>Healthcheck Status</TITLE></HEAD>
<BODY>
<H2>Result of 1 checks:</H2>
<TABLE bgcolor="#ffffff" border="1">
<TBODY>
<TR>
<TH>
Reason
</TH>
</TR>
<TR>
<TD>OK</TD>
</TR>
</TBODY>
</TABLE>
<HR></HR>
</BODY>
Example requests/responses (detailed mode):
$ curl -X GET -i -H "Accept: application/json" "http://0.0.0.0:8775/healthcheck"
HTTP/1.0 200 OK
Date: Wed, 24 Aug 2016 06:11:59 GMT
Content-Type: application/json
Content-Length: 3480
{
"detailed": true,
"gc": {
"counts": [
293,
10,
5
],
"threshold": [
700,
10,
10
]
},
"greenthreads": [
...
],
"now": "2016-08-24 06:11:59.419267",
"platform": "Linux-4.2.0-27-generic-x86_64-with-Ubuntu-14.04-trusty",
"python_version": "2.7.6 (default, Jun 22 2015, 17:58:13) \n[GCC 4.8.2]",
"reasons": [
{
"class": "HealthcheckResult",
"details": "Path '/tmp/dead' was not found",
"reason": "OK"
}
],
"threads": [
...
]
}
$ curl -X GET -i -H "Accept: text/html" "http://0.0.0.0:8775/healthcheck"
HTTP/1.0 200 OK
Date: Wed, 24 Aug 2016 06:36:07 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 6838
<HTML>
<HEAD><TITLE>Healthcheck Status</TITLE></HEAD>
<BODY>
<H1>Server status</H1>
<B>Server hostname:</B><PRE>...</PRE>
<B>Current time:</B><PRE>2016-08-24 06:36:07.302559</PRE>
<B>Python version:</B><PRE>2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2]</PRE>
<B>Platform:</B><PRE>Linux-4.2.0-27-generic-x86_64-with-Ubuntu-14.04-trusty</PRE>
<HR></HR>
<H2>Garbage collector:</H2>
<B>Counts:</B><PRE>(77, 1, 6)</PRE>
<B>Thresholds:</B><PRE>(700, 10, 10)</PRE>
<HR></HR>
<H2>Result of 1 checks:</H2>
<TABLE bgcolor="#ffffff" border="1">
<TBODY>
<TR>
<TH>
Kind
</TH>
<TH>
Reason
</TH>
<TH>
Details
</TH>
</TR>
<TR>
<TD>HealthcheckResult</TD>
<TD>OK</TD>
<TD>Path '/tmp/dead' was not found</TD>
</TR>
</TBODY>
</TABLE>
<HR></HR>
<H2>1 greenthread(s) active:</H2>
<TABLE bgcolor="#ffffff" border="1">
<TBODY>
<TR>
<TD><PRE> File "oslo_middleware/healthcheck/__main__.py", line 94, in <module>
main()
File "oslo_middleware/healthcheck/__main__.py", line 90, in main
server.serve_forever()
...
</PRE></TD>
</TR>
</TBODY>
</TABLE>
<HR></HR>
<H2>1 thread(s) active:</H2>
<TABLE bgcolor="#ffffff" border="1">
<TBODY>
<TR>
<TD><PRE> File "oslo_middleware/healthcheck/__main__.py", line 94, in <module>
main()
File "oslo_middleware/healthcheck/__main__.py", line 90, in main
server.serve_forever()
....
</TR>
</TBODY>
</TABLE>
</BODY>
</HTML>
Example of paste configuration:
[app:healthcheck] use = egg:oslo.middleware:healthcheck backends = disable_by_file disable_by_file_path = /var/run/nova/healthcheck_disable [pipeline:public_api] pipeline = healthcheck sizelimit [...] public_service
Multiple filter sections can be defined if it desired to have pipelines with different healthcheck configuration, example:
[composite:public_api] use = egg:Paste#urlmap / = public_api_pipeline /healthcheck = healthcheck_public [composite:admin_api] use = egg:Paste#urlmap / = admin_api_pipeline /healthcheck = healthcheck_admin [pipeline:public_api_pipeline] pipeline = sizelimit [...] public_service [pipeline:admin_api_pipeline] pipeline = sizelimit [...] admin_service [app:healthcheck_public] use = egg:oslo.middleware:healthcheck backends = disable_by_file disable_by_file_path = /var/run/nova/healthcheck_public_disable [filter:healthcheck_admin] use = egg:oslo.middleware:healthcheck backends = disable_by_file disable_by_file_path = /var/run/nova/healthcheck_admin_disable
- classmethod app_factory(global_conf: dict[str, Any] | None, **local_conf: Any) -> Self
- Factory method for paste.deploy.
- Parameters
- global_conf -- dict of options for all middlewares (usually the [DEFAULT] section of the paste deploy configuration file)
- local_conf -- options dedicated to this middleware (usually the option defined in the middleware section of the paste deploy configuration file)
- classmethod factory(global_conf: dict[str, ty.Any] | None, **local_conf: ty.Any) -> ty.Callable[[WSGIApplication], base.ConfigurableMiddleware]
- Factory method for paste.deploy.
- Parameters
- global_conf -- dict of options for all middlewares (usually the [DEFAULT] section of the paste deploy configuration file)
- local_conf -- options dedicated to this middleware (usually the option defined in the middleware's section of the paste deploy configuration file)
- class oslo_middleware.RequestBodySizeLimiter(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- Limit the size of incoming requests.
- class oslo_middleware.RequestId(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- Middleware that ensures request ID.
It ensures to assign request ID for each API request and set it to request environment. The request ID is also added to API response.
Configuration Options
RequestBodySizeLimiter
oslo_middleware
- max_request_body_size
- Type
- integer
- Default
- 114688
The maximum body size for each request, in bytes.
SSLMiddleware
CORS Middleware
This middleware provides a comprehensive, configurable implementation of the CORS (Cross Origin Resource Sharing) specification as oslo-supported python wsgi middleware.
NOTE:
Quickstart
First, include the middleware in your application:
from oslo_middleware import cors app = cors.CORS(your_wsgi_application)
Secondly, add as many allowed origins as you would like:
app.add_origin(allowed_origin='https://website.example.com:443',
allow_credentials=True,
max_age=3600,
allow_methods=['GET','PUT','POST','DELETE'],
allow_headers=['X-Custom-Header'],
expose_headers=['X-Custom-Header']) # ... add more origins here.
Configuration for oslo_config
A factory method has been provided to simplify configuration of your CORS domain, using oslo_config:
from oslo_middleware import cors from oslo_config import cfg app = cors.CORS(your_wsgi_application, cfg.CONF)
In your application's config file, then include a configuration block something like this:
[cors] allowed_origin=https://website.example.com:443,https://website2.example.com:443 max_age=3600 allow_methods=GET,POST,PUT,DELETE allow_headers=X-Custom-Header expose_headers=X-Custom-Header
Configuration for pastedeploy
If your application is using pastedeploy, the following configuration block will add CORS support.:
[filter:cors] use = egg:oslo.middleware#cors allowed_origin=https://website.example.com:443,https://website2.example.com:443 max_age=3600 allow_methods=GET,POST,PUT,DELETE allow_headers=X-Custom-Header expose_headers=X-Custom-Header
If your application is using pastedeploy, but would also like to use the existing configuration from oslo_config in order to simplify the points of configuration, this may be done as follows.:
[filter:cors] use = egg:oslo.middleware#cors oslo_config_project = oslo_project_name # Optional field, in case the program name is different from the project: oslo_config_program = oslo_project_name-api
Configuration Options
cors
- allowed_origin
- Type
- list
- Default
- <None>
Indicate whether this resource may be shared with the domain received in the requests "origin" header. Format: "<protocol>://<host>[:<port>]", no trailing slash. Example: https://horizon.example.com
- allow_credentials
- Type
- boolean
- Default
- True
Indicate that the actual request can include user credentials
- expose_headers
- Type
- list
- Default
- []
Indicate which headers are safe to expose to the API. Defaults to HTTP Simple Headers.
- max_age
- Type
- integer
- Default
- 3600
Maximum cache age of CORS preflight requests.
- allow_methods
- Type
- list
- Default
- ['OPTIONS', 'GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'PATCH']
Indicate which methods can be used during the actual request.
- allow_headers
- Type
- list
- Default
- []
Indicate which header field names may be used during the actual request.
Module Documentation
- class oslo_middleware.cors.AllowedOrigin
- class oslo_middleware.cors.CORS(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- CORS Middleware.
This middleware allows a WSGI app to serve CORS headers for multiple configured domains.
For more information, see http://www.w3.org/TR/cors/
- add_origin(allowed_origin: str | list[str], allow_credentials: bool = True, expose_headers: list[str] | None = None, max_age: int | None = None, allow_methods: list[str] | None = None, allow_headers: list[str] | None = None) -> None
- Add another origin to this filter.
- Parameters
- allowed_origin -- Protocol, host, and port for the allowed origin.
- allow_credentials -- Whether to permit credentials.
- expose_headers -- A list of headers to expose.
- max_age -- Maximum cache duration.
- allow_methods -- List of HTTP methods to permit.
- allow_headers -- List of HTTP headers to permit from the client.
- Returns
- classmethod factory(global_conf: dict[str, ty.Any] | None, **local_conf: ty.Any) -> ty.Callable[[WSGIApplication], base.MiddlewareType]
- factory method for paste.deploy
allowed_origin: Protocol, host, and port for the allowed origin. allow_credentials: Whether to permit credentials. expose_headers: A list of headers to expose. max_age: Maximum cache duration. allow_methods: List of HTTP methods to permit. allow_headers: List of HTTP headers to permit from the client.
- process_response(response: Response, request: Request | None = None) -> Response
- Check for CORS headers, and decorate if necessary.
Perform two checks. First, if an OPTIONS request was issued, let the application handle it, and (if necessary) decorate the response with preflight headers. In this case, if a 404 is thrown by the underlying application (i.e. if the underlying application does not handle OPTIONS requests, the response code is overridden.
In the case of all other requests, regular request headers are applied.
- exception oslo_middleware.cors.InvalidOriginError(origin: str)
- Exception raised when Origin is invalid.
- oslo_middleware.cors.filter_factory(global_conf: dict[str, ty.Any] | None, **local_conf: ty.Any) -> ty.Callable[[WSGIApplication], base.MiddlewareType]
- factory method for paste.deploy
allowed_origin: Protocol, host, and port for the allowed origin. allow_credentials: Whether to permit credentials. expose_headers: A list of headers to expose. max_age: Maximum cache duration. allow_methods: List of HTTP methods to permit. allow_headers: List of HTTP headers to permit from the client.
- oslo_middleware.cors.set_defaults(**kwargs: Opt) -> None
- Override the default values for configuration options.
This method permits a project to override the default CORS option values. For example, it may wish to offer a set of sane default headers which allow it to function with only minimal additional configuration.
- Parameters
- allow_credentials (bool) -- Whether to permit credentials.
- expose_headers (List of Strings) -- A list of headers to expose.
- max_age (Int) -- Maximum cache duration in seconds.
- allow_methods (List of Strings) -- List of HTTP methods to permit.
- allow_headers (List of Strings) -- List of HTTP headers to permit from the client.
Healthcheck middleware plugins
- class oslo_middleware.healthcheck.Healthcheck(application: WSGIApplication | None, conf: dict[str, ty.Any] | cfg.ConfigOpts | None = None)
- Healthcheck application used for monitoring.
It will respond 200 with "OK" as the body. Or a 503 with the reason as the body if one of the backends reports an application issue.
This is useful for the following reasons:
- Load balancers can 'ping' this url to determine service availability.
- Provides an endpoint that is similar to 'mod_status' in apache which can provide details (or no details, depending on if configured) about the activity of the server.
- (and more)
NOTE:
Example requests/responses (not detailed mode):
$ curl -i -X HEAD "http://0.0.0.0:8775/healthcheck"
HTTP/1.1 204 No Content
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
Date: Fri, 11 Sep 2015 18:55:08 GMT
$ curl -i -X GET "http://0.0.0.0:8775/healthcheck"
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 2
Date: Fri, 11 Sep 2015 18:55:43 GMT
OK
$ curl -X GET -i -H "Accept: application/json" "http://0.0.0.0:8775/healthcheck"
HTTP/1.0 200 OK
Date: Wed, 24 Aug 2016 06:09:58 GMT
Content-Type: application/json
Content-Length: 63
{
"detailed": false,
"reasons": [
"OK"
]
}
$ curl -X GET -i -H "Accept: text/html" "http://0.0.0.0:8775/healthcheck"
HTTP/1.0 200 OK
Date: Wed, 24 Aug 2016 06:10:42 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 239
<HTML>
<HEAD><TITLE>Healthcheck Status</TITLE></HEAD>
<BODY>
<H2>Result of 1 checks:</H2>
<TABLE bgcolor="#ffffff" border="1">
<TBODY>
<TR>
<TH>
Reason
</TH>
</TR>
<TR>
<TD>OK</TD>
</TR>
</TBODY>
</TABLE>
<HR></HR>
</BODY>
Example requests/responses (detailed mode):
$ curl -X GET -i -H "Accept: application/json" "http://0.0.0.0:8775/healthcheck"
HTTP/1.0 200 OK
Date: Wed, 24 Aug 2016 06:11:59 GMT
Content-Type: application/json
Content-Length: 3480
{
"detailed": true,
"gc": {
"counts": [
293,
10,
5
],
"threshold": [
700,
10,
10
]
},
"greenthreads": [
...
],
"now": "2016-08-24 06:11:59.419267",
"platform": "Linux-4.2.0-27-generic-x86_64-with-Ubuntu-14.04-trusty",
"python_version": "2.7.6 (default, Jun 22 2015, 17:58:13) \n[GCC 4.8.2]",
"reasons": [
{
"class": "HealthcheckResult",
"details": "Path '/tmp/dead' was not found",
"reason": "OK"
}
],
"threads": [
...
]
}
$ curl -X GET -i -H "Accept: text/html" "http://0.0.0.0:8775/healthcheck"
HTTP/1.0 200 OK
Date: Wed, 24 Aug 2016 06:36:07 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 6838
<HTML>
<HEAD><TITLE>Healthcheck Status</TITLE></HEAD>
<BODY>
<H1>Server status</H1>
<B>Server hostname:</B><PRE>...</PRE>
<B>Current time:</B><PRE>2016-08-24 06:36:07.302559</PRE>
<B>Python version:</B><PRE>2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2]</PRE>
<B>Platform:</B><PRE>Linux-4.2.0-27-generic-x86_64-with-Ubuntu-14.04-trusty</PRE>
<HR></HR>
<H2>Garbage collector:</H2>
<B>Counts:</B><PRE>(77, 1, 6)</PRE>
<B>Thresholds:</B><PRE>(700, 10, 10)</PRE>
<HR></HR>
<H2>Result of 1 checks:</H2>
<TABLE bgcolor="#ffffff" border="1">
<TBODY>
<TR>
<TH>
Kind
</TH>
<TH>
Reason
</TH>
<TH>
Details
</TH>
</TR>
<TR>
<TD>HealthcheckResult</TD>
<TD>OK</TD>
<TD>Path '/tmp/dead' was not found</TD>
</TR>
</TBODY>
</TABLE>
<HR></HR>
<H2>1 greenthread(s) active:</H2>
<TABLE bgcolor="#ffffff" border="1">
<TBODY>
<TR>
<TD><PRE> File "oslo_middleware/healthcheck/__main__.py", line 94, in <module>
main()
File "oslo_middleware/healthcheck/__main__.py", line 90, in main
server.serve_forever()
...
</PRE></TD>
</TR>
</TBODY>
</TABLE>
<HR></HR>
<H2>1 thread(s) active:</H2>
<TABLE bgcolor="#ffffff" border="1">
<TBODY>
<TR>
<TD><PRE> File "oslo_middleware/healthcheck/__main__.py", line 94, in <module>
main()
File "oslo_middleware/healthcheck/__main__.py", line 90, in main
server.serve_forever()
....
</TR>
</TBODY>
</TABLE>
</BODY>
</HTML>
Example of paste configuration:
[app:healthcheck] use = egg:oslo.middleware:healthcheck backends = disable_by_file disable_by_file_path = /var/run/nova/healthcheck_disable [pipeline:public_api] pipeline = healthcheck sizelimit [...] public_service
Multiple filter sections can be defined if it desired to have pipelines with different healthcheck configuration, example:
[composite:public_api] use = egg:Paste#urlmap / = public_api_pipeline /healthcheck = healthcheck_public [composite:admin_api] use = egg:Paste#urlmap / = admin_api_pipeline /healthcheck = healthcheck_admin [pipeline:public_api_pipeline] pipeline = sizelimit [...] public_service [pipeline:admin_api_pipeline] pipeline = sizelimit [...] admin_service [app:healthcheck_public] use = egg:oslo.middleware:healthcheck backends = disable_by_file disable_by_file_path = /var/run/nova/healthcheck_public_disable [filter:healthcheck_admin] use = egg:oslo.middleware:healthcheck backends = disable_by_file disable_by_file_path = /var/run/nova/healthcheck_admin_disable
- classmethod app_factory(global_conf: dict[str, Any] | None, **local_conf: Any) -> Self
- Factory method for paste.deploy.
- Parameters
- global_conf -- dict of options for all middlewares (usually the [DEFAULT] section of the paste deploy configuration file)
- local_conf -- options dedicated to this middleware (usually the option defined in the middleware section of the paste deploy configuration file)
- classmethod factory(global_conf: dict[str, ty.Any] | None, **local_conf: ty.Any) -> ty.Callable[[WSGIApplication], base.ConfigurableMiddleware]
- Factory method for paste.deploy.
- Parameters
- global_conf -- dict of options for all middlewares (usually the [DEFAULT] section of the paste deploy configuration file)
- local_conf -- options dedicated to this middleware (usually the option defined in the middleware's section of the paste deploy configuration file)
- class oslo_middleware.healthcheck.Reason
- class oslo_middleware.healthcheck.disable_by_file.DisableByFileHealthcheck(oslo_conf: cfg.ConfigOpts, conf: dict[str, ty.Any])
- DisableByFile healthcheck middleware plugin
This plugin checks presence of a file to report if the service is unavailable or not.
Example of middleware configuration:
[filter:healthcheck] paste.filter_factory = oslo_middleware:Healthcheck.factory path = /healthcheck backends = disable_by_file disable_by_file_path = /var/run/nova/healthcheck_disable # set to True to enable detailed output, False is the default detailed = False
- healthcheck(server_port: int) -> HealthcheckResult
- method called by the healthcheck middleware
return: HealthcheckResult object
- class oslo_middleware.healthcheck.disable_by_file.DisableByFilesPortsHealthcheck(oslo_conf: cfg.ConfigOpts, conf: dict[str, ty.Any])
- 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:
[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 # set to True to enable detailed output, False is the default detailed = False
- healthcheck(server_port: int) -> HealthcheckResult
- method called by the healthcheck middleware
return: HealthcheckResult object
- class oslo_middleware.healthcheck.enable_by_files.EnableByFilesHealthcheck(oslo_conf: cfg.ConfigOpts, conf: dict[str, Any])
- EnableByFilesHealthcheck healthcheck middleware plugin
This plugin checks presence of a file at a specified location.
Example of middleware configuration:
[app:healthcheck] paste.app_factory = oslo_middleware:Healthcheck.app_factory path = /healthcheck backends = enable_by_files enable_by_file_paths = /var/lib/glance/images/.marker,
/var/lib/glance/os_glance_staging_store/.marker # set to True to enable detailed output, False is the default detailed = False
- healthcheck(server_port: int) -> HealthcheckResult
- method called by the healthcheck middleware
return: HealthcheckResult object
Available Plugins
disable_by_file
DisableByFile healthcheck middleware plugin
This plugin checks presence of a file to report if the service is unavailable or not.
Example of middleware configuration:
[filter:healthcheck] paste.filter_factory = oslo_middleware:Healthcheck.factory path = /healthcheck backends = disable_by_file disable_by_file_path = /var/run/nova/healthcheck_disable # set to True to enable detailed output, False is the default detailed = False
disable_by_files_ports
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:
[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 # set to True to enable detailed output, False is the default detailed = False
enable_by_files
EnableByFilesHealthcheck healthcheck middleware plugin
This plugin checks presence of a file at a specified location.
Example of middleware configuration:
[app:healthcheck] paste.app_factory = oslo_middleware:Healthcheck.app_factory path = /healthcheck backends = enable_by_files enable_by_file_paths = /var/lib/glance/images/.marker,
/var/lib/glance/os_glance_staging_store/.marker # set to True to enable detailed output, False is the default detailed = False
Glossary
This glossary offers a list of terms and definitions to define a vocabulary for OpenStack-related concepts.
C
- Cross-Origin Resource Sharing (CORS)
- A mechanism that allows many resources (for example, fonts, JavaScript) on a web page to be requested from another domain outside the domain from which the resource originated. In particular, JavaScript's AJAX calls can use the XMLHttpRequest mechanism.
RELEASE NOTES
Read also the oslo.middleware Release Notes.
AUTHOR
Author name not set
COPYRIGHT
2014, OpenStack Foundation
| August 21, 2025 | 6.6.0 |
