ironic-specs/specs/kilo-implemented/api-microversions.rst

419 lines
18 KiB
ReStructuredText

..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
====================
Ironic Microversions
====================
https://blueprints.launchpad.net/ironic/+spec/api-microversions
The purpose of this spec is to call out the specific behaviour between
Ironic and python-ironicclient that is required now that we are using
microversions, and to provide guidance how other clients may wish to
interact with Ironic.
Problem description
===================
As a community we are really good at evolving interfaces and code over time
via incremental development. We've been less good at giant big bang drops of
code. The Ironic API is under heavy development, and we want to ensure that
consumers of Ironic's API are able to make use of new features as they become
available, while also ensuring they don't break due to incompatibilities.
Ironic isn't the only OpenStack project implementing microversions, ironically.
Nova[0] is also implementing microversions in parallel for the 'Kilo' release.
The implementation of microversions is currently underway in Ironic, based
around that Nova spec. The implementation in Ironic has already landed[1],
and is currently under implementation for Ironic's primary client,
python-ironicclient[2].
Microversions are implemented in the API through the addition of a new HTTP
header - specifically 'X-OpenStack-Ironic-API-Version'. This header is
accepted by Ironic so a client can indicate which version of the API it wants
to use for communication, and likewise for Ironic to indicate which version
it is using for communication.
For Ironic, if no HTTP header is supplied, v1.0 (stable/juno) of the API is
used. If an invalid version is specified in the HTTP header, an HTTP 406 Not
Acceptable is returned with an indication of the supported range of
versions[4]. If the special 'latest' version is specified, Ironic will use
its most recent version.
During changes being made to python-ironicclient[2] to support Ironic's
microversions it was discovered that there isn't a formal specification of how
Ironic and a client should interact for varying cases of microversion mismatch
or for an unknown/unspecified microversion.
The need for this spec was discussed in IRC[3], to specifically address the
interaction between Ironic and a client (whether that be python-ironicclient or
any other client).
Proposed change
===============
To address the specific behaviour between Ironic and python-ironicclient, the
following Use Cases are listed to specify the expected functionality. Please
see the IRC logs[3][5] and this code review[2] for further context for these
Use Cases.
For the purposes of definition, we will use the term "old Ironic" to refer to
a version of Ironic that predates microversions and has no knowledge of them.
Likewise, we will use the term "new Ironic" to refer to a version of Ironic
that includes support for microversions.
Similarly, we will apply such labelling to "old client" and "new client"
respectively.
New Client Default Microversion
-------------------------------
The python-ironicclient provides an option to specify which microversion to
attempt to use for communicating to Ironic. When this is specified, the
requested microversion should be used (unless of course the client cannot
support that version). This includes 'latest' which is an indication to
Ironic that the latest microversion that ironic knows about should be used.
However if no microversion is specified to the client, it should use the
latest microversion that the client supports.
As part of the initial communication with Ironic it may need to revert to a
lower microversion due to Ironic's support for only older microversions
(as per Use Case 7).
The goal of this requirement is for python-ironicclient / Ironic communication
to "just work" for the user, and if possible, to use the most recent version
of the REST API possible, so that the user is able to make use of the latest
functionality.
Use Case 1: Old Client communicating with an Old Ironic
-------------------------------------------------------
This is exactly the same behaviour that was seen prior to the introduction
of microversions - no change to either the client or server is required
for this case.
* The client makes a connection to Ironic, not specifying the HTTP header
X-OpenStack-Ironic-API-Version
* Ironic does not check for an X-OpenStackIronic-API-Version header, and
processes all communication simply as v1.0 (stable/juno)
Use Case 2: Old Client communicating with a New Ironic
------------------------------------------------------
This is where Ironic is updated to a new version that support microversions,
but an old client is used to communicate to it.
* The client makes a connection to Ironic, not specifying the HTTP header
X-OpenStack-Ironic-API-Version
* Ironic does not see the X-OpenStack-Ironic-API-Version HTTP header
* Ironic communicates using v1.0 (stable/juno) of the REST API, and
all communication with the client uses that version of the interface.
Use Case 3A: New Client communicating with a Old Ironic (not user-specified)
-----------------------------------------------------------------------------
This is the where the user does not request a particular microversion to a
new client that support microversions and tries to communicate with an old
Ironic. The version that the new client uses is the maximum microversion
it supports.
* The user does not specify the microversion to use in communication with
the client. Consequentally, the client attempts to use the latest
microversion that the client knows about.
* The client makes a connection to an old Ironic, supplying a
X-OpenStack-Ironic-API-Version HTTP header
* Ironic doesn't look for, or parse the HTTP header. It communicates using
the only API code path it knows about, that being v1.0
* The client does not receive a X-OpenStack-Ironic-API-Version header in
the response, and from that is able to assume that the version of Ironic
that it is talking to does not support microversions. That is, it is using
a version of the REST API that predates v1.0 (stable/juno).
* The client should transparently proceed now that it knows that it is
communicating to an Ironic that can only support v1.0 of the REST API.
Use Case 3B: New Client communicating with a Old Ironic (user-specified)
-------------------------------------------------------------------------
This is the where the user requests a particular microversion to a
new client that support microversions and tries to communicate with an old
Ironic.
* The user specifies a microversion that is valid for the client.
* The client makes a connection to an old Ironic, supplying a
X-OpenStack-Ironic-API-Version HTTP header
* Ironic doesn't look for, or parse the HTTP header. It communicates using
the only API code path it knows about, that being v1.0
* The client does not receive a X-OpenStack-Ironic-API-Version header in
the response, and from that is able to assume that the version of Ironic
that it is talking to does not support microversions. That is, it is using
a version of the REST API that predates v1.0.
* The client informs the user that it cannot communicate to Ironic using that
microversion and exits.
Use Case 4: New Client, user specifying an invalid version number
-----------------------------------------------------------------
This is the case where a user provides as input to a new client an invalid
microversion identifier, such as 'spam', 'l33t', or '1.2.3.4.5'.
* The user specifies a microversion to the client that is invalid. The client
should return an error to the user, i.e. the client should provide some
validation that a valid microversion identifier is provided.
Use Case 5: New Client/New Ironic: Unsupported Ironic version
-------------------------------------------------------------
This is the case where a new client requests a version that is older than
the new Ironic can handle. For example, the client supports microversions
1.1 to 1.6, and Ironic supports versions 1.8 to 1.15.
* The client makes a connection to Ironic, supplying 1.6 as the requested
microversion.
* Ironic responds with a 406 Not Acceptable, along with the -Min- and -Max-
headers that it can support (in this case 1.8 and 1.15)
* As the client does not support a version supported by Ironic, it cannot
continue and reports such to the user.
* (An alternative path would be for the client to try and proceed using a
version acceptable to Ironic. Note that in this case the client should be
able to proceed since any change that would break basic compatibility
would likely require a major version bump to v2)
Use Case 6: New Client/New Ironic: Unsupported Client version
-------------------------------------------------------------
This is the case where a new client requests a version that is newer than
the new Ironic can handle. For example, the client supports microversions
1.10 to 1.15, and Ironic supports versions 1.1 to 1.5.
* The client makes a connection to Ironic, supplying 1.10 as the requested
microversion.
* Ironic responds with a 406 Not Acceptable, along with the -Min- and -Max-
headers that it can support (in this case 1.1 and 1.5)
* The client reports this error to the user
* (An alternative path would be for the client to try and proceed using a
version acceptable to Ironic. Note that in this case the client should be
able to proceed since any change that would break basic compatibility
would likely require a major version bump to v2)
Note: This scenario should not occur in practice as the client should always
be able to talk to any version of Ironic.
Use Case 7A: New Client/New Ironic: Negotiated version (not user-specified)
---------------------------------------------------------------------------
This is the case where a new client requests a version that is newer than
the new Ironic can handle, but supports a version that Ironic supports. For
example, the client supports microversions 1.8 to 1.15, and Ironic supports
versions 1.1 to 1.10.
* The user has not specified a version to the client
* The client makes a connection to Ironic, supplying 1.15 as the
microversion since this is the latest microversion that the client
supports.
* Ironic responds with a 406 Not Acceptable, along with the -Min- and -Max-
headers that it can support (in this case 1.1 and 1.10)
* The client should transparently proceed, having negotiated that both
client and server will use v1.10. The client should also cache this
microversion, so that subsequent attempts do not need to renegotiate
microversions.
Use Case 7B: New Client/New Ironic: Negotiated version (user-specified)
-----------------------------------------------------------------------
This is a slight variation on Use Case 7A, where the user specifies a
specific version to use to communicate with Ironic.
* The user specifies a particular microversion (e.g. 1.15) that the client
should use
* The client makes a connection to Ironic, supplying 1.15 as the
microversion
* Ironic responds with a 406 Not Acceptable, along with the -Min- and -Max-
headers that it can support (in this case 1.1 and 1.10)
* The client reports this to the user and exits
Use Case 8: New Client/New Ironic: Compatible Version
-----------------------------------------------------
This is the case where a new client requests a version that is supported
by the new Ironic. For example, the client supports microversions 1.8 to
1.10, and Ironic supports versions 1.1 to 1.12.
* The client makes a connection to Ironic, supplying 1.10 as the requested
microversion.
* As Ironic can support this microversion, it responds by sending back a
response of 1.10 in the X-OpenStack-Ironic-API-Version HTTP header.
Use Case 9: New Client/New Ironic: Version request of 'latest'
--------------------------------------------------------------
This is the case where a new client requests a version of 'latest' from a
new Ironic.
* The client makes a connection to Ironic, supplying 'latest' as the version
in the X-OpenStack-Ironic-API-Version HTTP header
* Ironic responds by using the latest API version it supports, and includes
this in the X-OpenStack-Ironic-API-Version header, along with the -Min- and
-Max- headers.
Note: It's possible that Ironic provides a response that the client is not able
to correctly interpret. This is unavoidable, however it enables a client that
is older than the deployed version of Ironic to potentially access all of the
functionality available in that Ironic version. In this instance, the client
may choose to report to the user the version that Ironic included in the
response, along with the min and max microversions that the client is known to
be able to support. Any parts of the response from Ironic that the client is
not programmed to handle will simply be discarded.
Alternatives
------------
One alternative to microversions is to not have them at all. What this would
result in would be a group of large changes happening simultaneously, resulting
in unpaired server/client versions not being compatible at all. It would also
result in less frequent, but larger incompatible API changes. And nobody wants
that.
Data model impact
-----------------
None. This change is isolated to the API code.
REST API impact
---------------
As described above, a new HTTP header would be accepted, and returned by
Ironic.
If a client chose to use that header to request a specific version, Ironic
would respond, either accepting the requested version for future communication,
or rejecting that version request as not being supportable.
If a client chose not to use that header, Ironic would assume that the REST API
to be used would be v1.0 (that is, the same API that was present in the 'Juno'
release[6]). This is how the REST API works today.
RPC API impact
--------------
None
Driver API impact
-----------------
None
Nova driver impact
------------------
The current behaviour of python-ironicclient (pass no version header) results
in the Nova driver using v1.0 of our API. The proposed changes to
python-ironicclient will cause the Nova driver to use the latest microversion
that the client supports. This will make available to Nova any new
functionality we add to Ironic at the point in time when we tag a new client
release.
A future enhancement would be to modify the Nova Ironic driver to specify a
specified microversion to use when communicating to Ironic. This would provide
exact control over which REST API version to consume.
This behaviour should be documented in how Nova and Ironic are gate tested.
There is the potential here to break the nova driver if the incorrect version
is requested. Consequently, it is important to manage the Nova driver, Ironic
and python-ironicclient version changes.
Security impact
---------------
None
Other end user impact
---------------------
Clients that wish to use new features available over the REST API added since
the 'Juno' release will need to start using this HTTP header. The fact that
new features will only be added in new versions will encourage them to do so.
Scalability impact
------------------
None
Performance Impact
------------------
None
Other deployer impact
---------------------
None
Developer impact
----------------
Any future changes to Ironic's REST API (whether that be in the request or
any response) *must* result in a microversion update, and guarded in the code
appropriately.
Upgrades and Backwards Compatibility
====================================
As described above.
Implementation
==============
Assignee(s)
-----------
Primary assignees:
::
lintan - Tan Lin <tan.lin.good@gmail.com>
Secondary assignees:
::
devananda - Devananda van der Veen <devananda.vdv@gmail.com>
rloo - Ruby Loo <rloo@yahoo-inc.com>
mrda - Michael Davies <michael@the-davies.net>
plus many others
Work Items
----------
Complete the python-ironicclient microversion implementation by:
#. Add in the highest Ironic microversion that the python-ironicclient can
support.
#. If the User does not pass a version, the client should automatically
try the highest version it supports. That is, send the
X-OpenStack-Ironic-API-Version HTTP header with the highest Ironic
microversion that it supports.
#. The python-ironicclient should support X.Y and 'latest' as valid API
versions.
Dependencies
============
None
Testing
=======
It is not feasible for tempest to test all possible combinations of the API
supported by microversions. We will have to pick specific versions which are
representative of what is implemented. The existing tempest tests will be used
as the baseline for future API version testing.
The following combinations should be tested:
* Old client (eg, juno-era client release) against current master branch of
Ironic
* Latest client (eg, proposed changes to master) against current master branch
of Ironic
* Latest client (eg, proposed changes to master) against stable/juno Ironic
And we should continue such forwards-and-backwards testing for as long as we
claim to support a given release.
Documentation Impact
====================
No specific documentation impact is identified that is not covered by existing
API change processes.
References
==========
* [0] http://specs.openstack.org/openstack/nova-specs/specs/kilo/implemented/api-microversions.html for details on Nova's microversioning. Note that this document borrows heavily from that spec. (Thanks cyeoh!)
* [1] https://review.openstack.org/#/c/150821/ and https://review.openstack.org/#/c/158601/
* [2] https://review.openstack.org/#/c/155624/
* [3] http://eavesdrop.openstack.org/irclogs/%23openstack-ironic/%23openstack-ironic.2015-03-03.log#2015-03-03T22:17:26-2015-03-03T23:00:42
* [4] https://review.openstack.org/#/c/160758/
* [5] http://eavesdrop.openstack.org/meetings/ironic/2015/ironic.2015-03-09-17.00.log.txt#17:17:33-17:50:20
* [6] While this is broadly true, at least one change - the addition of the
'maintenance_reason' field - has been made since the 'Juno' release of
Ironic