Hi all,

as promised here is status update of the OpenAPI work, and sorry in advance for another long message

Short version
==========
I have extended codegerator [1] to build OpenAPI specs from the sources of the services. All the exposed URLs with wherever possible query parameters/request/body are placed into the OpenAPI spec and whenever available generated information is extended with descriptions from rendered API-Ref html to keep life easier.
This helped me to spot a variety of issues: unknown/undesired routes exposed, undocumented routes, documentation for unexposed routes, etc
Sadly not all services are having all the required information to build the spec so the generator is created in the way that supports extension and overrides for every service.
- Nova has route versions, request_body and response codes, but no information about response json
- Glance is not bad, but not every request/response info is available directly on the controller.
- Cinder is not having query parameters information, no response body schema
- Keystone is not having much of useful information directly attached to the routes, but is having useful part schemas in the code
- Neutron is very special
- Octavia is having request and response info available (as wsme, but I have written wsme=>jsonschema convertor)

Current state of schemas can be found under [2]. Schemas are still with gaps, but general structure can be seen

[1] https://review.opendev.org/c/openstack/openstacksdk/+/882326
[2] https://github.com/gtema/openstack-openapi/tree/main/specs

Long version
=========
codegenerator is able to inspect source code of services in diverse ways (requires service to be "pip installed" into the env of codegenerator). Generally I am looking at the api router/mapper of the service and start traversing from there. This ensures we document all the routes and not what we think about. It helped me to figure out i.e. Cinder is exposing all routes with and without project_id (this was honestly new to me and would have helped to reduce insanity in project_id handling in the SDK code), Octavia exposes all routes with /v2, /v2/lbaas, /v2.0 and /v2.0/lbaas prefixes (altogether 4 times same operations). 
It is also possible to provide rendered html of the API-Ref and codegenerator will try to extract all methods descriptions and even try to get parameters description as long as it is possible (no magic, best effort approach).

Nova:
uses typical wsgi + routes. All exposed routes in all versions can be seen. There are validations attached to all routes what provides jsonschemas about query parameters and request body.
There is some non standard mess with flavors actions (flavor delete/create/update are exposed as wsgi actions what under the hood exposes /flavors/{flavor_id}/action with corresponding json bodies. Validation for those fails, but that results in a wrong errors being returned to the user. I assume this is rather a bug and not a feature.
Sadly there are no schemas describing api responses at all, so this needs to be provided separately/manually.

Cinder:
similar to Nova, except that also no query parameters information is available.

Glance:
Glance is sometimes having useful information attached to the routes by having serializer/deserializer classes available. This helped getting nearly all metadefs documented at no effort. Sadly there are also negative exceptions: image data operations are not having content-type information attached directly, so this requires a hack in the generator to build a correct spec for those operations. Still I was positively surprised with the amount of useful info I was able to get out of the source code without "hacks".

Keystone:
Flask is a tricky thing. Looking at all the routes exposed I got specs for all the resources in HEAD mode. Current API Ref mentions that, but they are not described at all. But that is not a big deal. A more severe problem is that the same controller is exposed for /<RESOURCE> and /<RESOURCE>/{resource_id} routes. This leads to the fact that user can send i.e. DELETE/PUT to /projects which will fail with 500 because project_id is a positional argument in the controller and not having default. But that heavily depends on the function signature and in my eyes this is a huge potential vulnerability and a quality gap (what would happen when somebody accidentally adds default value to that parameter?). This is the same for all routes exposed and not only relevant to projects.
Sadly no extractable information about query parameters is available, but jsonschemas of resources are there (even for the /auth/tokens ). This requires manual mapping in the generator to know where schemas can be obtained from.

Neutron:
This one caused me a 4 day long headache. I have solved most of the issues, but there is still work to be done
  - inspecting the app requires neutron to be running (with a db created, all the schemas populated, config with all the plugins/extensions enabled, ....) Here the problem is to have actually all the plugins configured (some of them appears just don't like to work together with others)
  - some routes are exposed as wsgi app (the extensions app), but basic resources (networks, subnets, ports) are exposed as not inspectable pecan stuff (using dynamic _lookup to find route controller is just too complex for inspection)
  - neutron is having api definition which can be treated as a schema, but requires sophisticated logic (describing bulk requests is actually a no-brainer this way either)
  - still current biggest item is to have a max configuration so that codegenerator can look at every possible plugin

Octavia:
It is also using the Pecan framework with dynamic lookups which is a huge problem for the inspection, but the amount of those is rather an exception that allows me to traverse through "static" paths and supplement them with "exceptions".
In contrast to all the other services Octavia is attaching full request and response definitions to the routes. Those are not jsonschema (wsme types), but jsonschema can be generated out of that with ~100 magic lines

Heat:
have not started, but the first look tells it is also using routes lib so it should be easy to get exposed routes. However it doesn't seem to have any usable api schemas in the code.

Swift:
I created the spec manually before I started working on generating specs from source. Luckily Swift is not having any/major api changes so it should not be a problem.

With API-Ref info flowing into the spec we can get very usable specs automatically. Ideally all this information should be in docstrings (this is where initial descriptions are coming from and stay if api-ref match is not found).

In the meanwhile I got requests about the topic from some other contributors which is why I feel myself confirmed I am not working on something nobody needs. As such we might need to restructure how and where the work is done and eventually get a few new projects to host codegenerator and openapi specs. Ideally I would like openapi specs to be belonging to services themselves, but I think getting them together separately is a better choice for the current phase until generation is finalized. Anyway, having a generator allows us to create jobs generating new specs for the services.
With the generated specs I am already able to generate cli code (and sdk and ansible modules and etc)

Next steps
========
- decide on where to host the generator (currently under the openstacksdk project) and where to store the specs
- continue adding missing information to the already generated specs
- decide on how to deal with sphinx-openapi. It is present and Stephen seems to be a maintainer of it, but even ignoring OpenStack API specialities it just produces not the output we used to have with current os-api-ref. So eventually a new project for rendering specs in the current style is necessary. Doesn't look like a complex task though
- continue looking at other services (heat, magnum, etc)

Feel free to ping me directly for collaboration and/or questions.

Regards,
Artem