It is possible to create a node without specifying any driver_info properties in the initial POST -- this is reasonable and fine. However, the API does not expose what driver_info properties are required for the node's driver. The client cannot know what fields/properties to send in subsequent PATCH requests without reading Ironic's developer docs (or source code!). To address the above, an API is proposed, that returns the driver_info properties, along with a description for each property. The description will include whether the property is required or not. This is a specification for blueprint https://blueprints.launchpad.net/ironic/+spec/get-required-driver-info. Change-Id: I5e1dd5d0ee8c71bf2e81d4ce074296c6c4e15220
11 KiB
API to Get driver_info Properties
https://blueprints.launchpad.net/ironic/+spec/get-required-driver-info
This blueprint proposes an API that returns all the driver_info properties, along with a description for each property.
Problem description
It is possible to create a node without specifying any driver_info properties in the initial POST -- this is reasonable and fine. However, the API does not expose the list of driver_info properties, nor which are required for the node's driver. The client cannot know what fields/properties to send in subsequent PATCH requests without reading Ironic's developer docs (or source code!).
To address the above, an API is proposed, that returns the driver_info properties, along with a description for each property. The description will include whether the property is required or not.
Being an API, it may be consumed by humans and applications.
Proposed change
RESTful web API
The RESTful web API will be enhanced with:
GET /v1/drivers/<driver>/properties
where <driver> is the name of the driver.
If unsuccessful, eg an invalid driver name was specified, it returns HTTP status 404 and an error message.
If successful, it returns HTTP status 200 and the response (in Json format) is a list of :
<property name>: <property description>
where <property description> is a description of the property, including whether it is required or optional or any other special circumstances.
Eg: GET /v1/drivers/pxe_ssh/properties
might return:
{"pxe_deploy_ramdisk": "UUID... Required.",
"ssh_address": "IP address or hostname of the node to ssh into. Required.",
"ssh_virt_type": "virtualization software... Required.",
"ssh_user_name": "username to authenticate as. Required.",
"ssh_key_contents": "private key(s). One of this, ssh_key_filename,
or ssh_password must be specified."
"ssh_key_filename": "filename ... One of this, ssh_key_contents,
or ssh_password must be specified."
"ssh_password": "password... One of this, ssh_key_contents, or
ssh_key_filename must be specified."
"pxe_deploy_kernel": "UUID... Required."}
}
CLI subcommand
The driver-properties
subcommand will be added:
ironic driver-properties <driver_name>
It returns a table with the driver_info properties of the specified driver. For each property, this information is displayed:
- name of the driver_info property
- description
Eg:
$ ironic driver-properties fake_ipminative
+---------------+---------------------------------+
| Property | Description |
+---------------+----------+----------------------+
| ipmi_address | IP of the node's BMC. Required. |
| ipmi_password | IPMI password. Required. |
| ipmi_username | IPMI username. Required. |
+---------------+---------------------------------+
For invalid driver names, it returns:
The driver '<invalid-driver-name>' is unknown. (HTTP 404)
Required vs optional properties
The driver properties are specific to each driver, and depend on the
interfaces (power, deploy, console, rescue, management) of a driver. It
is at the interface implementation where we identify which properties
are required and which are optional. Having said that, it isn't all
black and white. For example, a driver with the
SHPower power
interface requires one of
ssh_key_contents
, ssh_key_filename
, or
ssh_password
properties to be specified. Handling this
"exactly one of these must be specified" case might be reasonable, but
what happens if there is a desire for "one or more of these must be
specified", "exactly X of these must be specified", "B must be specified
if A is specified", or "if A is specified, B or C must be
specified"?
After discussing this <irc_discussion>
, we decided to
take the approach of indicating, as part of the description, whether a
property is required or not along with any constraints on that. No
explicit 'required' field will be returned.
How the API service gets the information
A conductor service can handle one or more different drivers. There could be different versions of conductor services running, different versions of the API service running, and different versions of drivers available via the different conductor services. Ironic currently has a mechanism for versioning the conductor service and api service (via the RPC_API_VERSION). However, there is no mechanism yet for versioning of drivers.
When/if Ironic has a mechanism for versioning the drivers, the API (and code) can be updated to use the driver version to get the driver properties specific to that version.
Driver upgrades (resulting in one or more conductor services being restarted) need to be considered, since driver upgrades could include changes to their properties. There will be upgrade windows, during which different conductor services may be handling different drivers due to an upgrade. This specification assumes that the upgrade window is small, and that after an upgrade, all conductor services will be handling the same driver versions. (The right solution is to have explicit driver versioning; an intermediate solution might be to allow the user to explicitly specify a conductor service when querying for driver information, but that doesn't seem to be the right approach to take.)
After the conductor services are upgraded, all the API services should be restarted. So during the upgrade window, the API services may return incorrect/different driver property information, but after the upgrade is done, the information should be correct again.
Although an API service could access/instantiate the drivers directly, that would only give the service access to local drivers. These drivers may not be the actual drivers that the conductor services use. Furthermore, since the drivers talk to hardware, the API service shouldn't be allowed to access them directly.
The conductor service, then, is the gateway to getting driver properties. Two approaches were considered:
- the API service queries, via RPC, a conductor service, to get the driver properties. It picks the first conductor service (any one will do if we assume that all the conductors are handling the same version of the driver). This is the approach we will take.
- the API service queries the DB to get driver properties that the conductor services have placed there. When a conductor service starts, it adds the property information for each of the drivers it can handle, to a DB table. Since more than one conductor could be handling the same driver, the driver information would be added to a new DB table, different from the "conductor" table.
For both of these approaches, making an RPC or DB call for each user request may become a performance issue; especially if the user requests are generated by some automated system. Since the information is static for the lifetime of the conductor services (or longer), it makes sense for the API services to cache the information locally.
If an upgrade (where a conductor driver is updated) occurs, all the API services must be restarted after the conductor service upgrades are completed. This will clear out the caches, to make sure that the API services get the most recent drivers' information.
A cache-refresh mechanism could be added, but the information is relatively static and only changes when a driver changes. Driver changes should be infrequent enough that having the API services restarted after conductor services are upgraded should suffice.
Since there doesn't seem to be much gain with storing the driver information in the database since caching will be done, having the API service query a conductor service for the driver information (approach #1) will be implemented.
Alternatives
The driver_info information could be made available in a non-API fashion:
- document the information.
- pros: no code changes at all, no need to write this specification
- cons: user needs to know where to find the documentation; documentation needs to be kept up-to-date; more difficult to write automation tools to extract this information
- read the code.
- pros: no additional code changes required; no need to write this spec; will always be the source of truth
- cons: very user-unfriendly; user needs to know python and know where to find the appropriate code.
Given that we think having an API is a GOOD THING, these approaches were ruled out.
This doesn't describe alternative RESTful web API, CLI commands or response outputs, because the proposed API is consistent with the existing API, but clearly there are alternatives.
Data model impact
This will add an internal cache to each API service. The database is not affected.
REST API impact
See RESTful web API <rest_api>
section above for a
description of the new request.
Driver API impact
All the driver interfaces (DeployInterface, PowerInterface, ConsoleInterface, RescueInterface, VendorInterface, ManagementInterface) will/must have a new method:
@abc.abstractmethod
def get_properties(self):
"""Return the properties of the interface.
:returns: a dictionary with <property name>:<property description>
entries
"""
Nova driver impact
None
Security impact
None
Other end user impact
See CLI subcommand <cli_subcommand>
section above
for the CLI subcommand.
Scalability impact
None
Performance Impact
Negligible.
Other deployer impact
Requirement that all the API services must be restarted after an upgrade of the conductor services.
Developer impact
None except for doing reviews. Well, making sure the list of properties is updated in the code.
Implementation
Assignee(s)
- Primary assignee:
-
rloo
- Other contributors:
-
None
Work Items
Bug:
- API does not expose required driver_info (https://bugs.launchpad.net/ironic/+bug/1261915)
Patches:
- Implement API to get driver properties (https://review.openstack.org/#/c/73005/)
- Add driver-properties command (https://review.openstack.org/#/c/76338/)
Dependencies
None
Testing
Since the information is static, Ironic unit tests are sufficient.
Tempest testing should be added if the QA team feels it is in the best interest of Tempest to check the output of common drivers.
Documentation Impact
The CLI subcommand will need to be documented, but the docs team have a script that generates the documentation via issuing ironic commands.
One or more guides (operators and/or deployment) will need to mention that all the API services need to be restarted after an upgrade of all conductor services.
References
discussion about how to handle required vs optional properties. Starting from 2014-07-08T14:18:06: http://eavesdrop.openstack.org/irclogs/%23openstack-ironic/%23openstack-ironic.2014-07-08.log