Volume connection information for Ironic nodes
This spec defines data model and REST APIs for boot from volume support in Ironic. Co-Authored-By: Ramakrishnan G <rameshg87@gmail.com> Change-Id: Ibf50be735905f868e0d523ab16353a6b5cc300af Partial-Bug: 1526231
This commit is contained in:
parent
d63a80f1d9
commit
b5b3a42b26
|
@ -0,0 +1,872 @@
|
||||||
|
..
|
||||||
|
This work is licensed under a Creative Commons Attribution 3.0 Unported
|
||||||
|
License.
|
||||||
|
|
||||||
|
http://creativecommons.org/licenses/by/3.0/legalcode
|
||||||
|
|
||||||
|
==================================================
|
||||||
|
Add volume connection information for Ironic nodes
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
https://bugs.launchpad.net/ironic/+bug/1526231
|
||||||
|
|
||||||
|
This RFE introduces the changes in Ironic to support connecting
|
||||||
|
and booting instances from remote volumes.
|
||||||
|
|
||||||
|
Problem description
|
||||||
|
===================
|
||||||
|
|
||||||
|
When user starts bare metal instance with Cinder volume, Nova orchestrates
|
||||||
|
the communication with Cinder and Ironic. The work flow of the boot process is
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
#. (Preparation) Administrator registers a node with initiator information.
|
||||||
|
|
||||||
|
#. User asks Cinder to create a boot volume.
|
||||||
|
|
||||||
|
#. User asks Nova to boot a node from the Cinder volume.
|
||||||
|
|
||||||
|
#. Nova calls Ironic to collect iSCSI/FC initiator information. Ironic
|
||||||
|
collects initiator information and returns it to Nova.
|
||||||
|
|
||||||
|
#. Nova calls Cinder to attach the volume to the node. Cinder attaches the
|
||||||
|
volume to the node and returns connection information which includes
|
||||||
|
target information.
|
||||||
|
|
||||||
|
#. Nova passes the target information for the node to Ironic
|
||||||
|
|
||||||
|
#. Nova calls Ironic to spawn the instance. Ironic prepares the bare metal
|
||||||
|
node to boot from the remote volume which is identified by target
|
||||||
|
information and powers on the bare metal node.
|
||||||
|
|
||||||
|
In the work flow above, Nova calls Ironic to get/set initiator/target
|
||||||
|
information (4 and 6) and also administrator calls Ironic to set initiator
|
||||||
|
information (1) but currently Ironic has neither those information
|
||||||
|
nor APIs for them.
|
||||||
|
|
||||||
|
Proposed change
|
||||||
|
===============
|
||||||
|
|
||||||
|
* Add a new table named ``volume_connectors`` with the below fields:
|
||||||
|
|
||||||
|
+ id
|
||||||
|
|
||||||
|
- Integer
|
||||||
|
- PrimaryKeyConstraint
|
||||||
|
|
||||||
|
+ uuid
|
||||||
|
|
||||||
|
- String(length=36)
|
||||||
|
- UniqueConstraint
|
||||||
|
|
||||||
|
+ node_id
|
||||||
|
|
||||||
|
- Integer
|
||||||
|
- ForeignKeyConstraint('nodes.id')
|
||||||
|
|
||||||
|
+ created_at
|
||||||
|
|
||||||
|
- DateTime
|
||||||
|
|
||||||
|
+ updated_at
|
||||||
|
|
||||||
|
- DateTime
|
||||||
|
|
||||||
|
+ type (can have values "iqn", "ip", "mac", "wwnn", "wwpn", "net-id")
|
||||||
|
|
||||||
|
- String(Length=32)
|
||||||
|
- UniqueConstraint(type, connector_id)
|
||||||
|
|
||||||
|
+ connector_id
|
||||||
|
|
||||||
|
- String(length=255)
|
||||||
|
- UniqueConstraint(type, connector_id)
|
||||||
|
|
||||||
|
+ extra
|
||||||
|
|
||||||
|
- Text
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Ironic should allow users to set IP and/or MAC address hardcorded into
|
||||||
|
`connector_id` field because we can't put any assumptions on the storage
|
||||||
|
network. It might be a Neutron network, or it might be a network that the
|
||||||
|
OpenStack part of the deployment doesn't know about at all. It depends on
|
||||||
|
deployment.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
`extra` field is text in the database but a dictionary (JSON-encoded
|
||||||
|
dict) in the object
|
||||||
|
|
||||||
|
* Add a new table named ``volume_targets`` with the below fields:
|
||||||
|
|
||||||
|
+ id
|
||||||
|
|
||||||
|
- Integer
|
||||||
|
- PrimaryKeyConstraint
|
||||||
|
|
||||||
|
+ uuid
|
||||||
|
|
||||||
|
- String(length=36)
|
||||||
|
- UniqueConstraint
|
||||||
|
|
||||||
|
+ node_id
|
||||||
|
|
||||||
|
- Integer
|
||||||
|
- ForeignKeyConstraint('nodes.id')
|
||||||
|
|
||||||
|
+ created_at
|
||||||
|
|
||||||
|
- DateTime
|
||||||
|
|
||||||
|
+ updated_at
|
||||||
|
|
||||||
|
- DateTime
|
||||||
|
|
||||||
|
+ volume_type
|
||||||
|
|
||||||
|
- String(length=64)
|
||||||
|
|
||||||
|
+ properties
|
||||||
|
|
||||||
|
- Text
|
||||||
|
|
||||||
|
+ boot_index
|
||||||
|
|
||||||
|
- Integer
|
||||||
|
- UniqueConstraint(node_id, boot_index)
|
||||||
|
- This is used for Ironic to distinguish the root volume. Similar to Nova,
|
||||||
|
Ironic assumes volumes with boot index 0 are root device.
|
||||||
|
(Nova associates a boot index with each block device and assumes volumes
|
||||||
|
with boot index 0 are root volumes.)
|
||||||
|
|
||||||
|
+ volume_id
|
||||||
|
|
||||||
|
- String(length=36)
|
||||||
|
|
||||||
|
+ extra
|
||||||
|
|
||||||
|
- Text
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Ironic should clear the connected target information on node tear_down,
|
||||||
|
just like it does for instance_info.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
`properties` and `extra` are text in the database but a dictionary
|
||||||
|
(JSON-encoded dict) in the object
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The contents of the `properties` field depend on volume type. Reference
|
||||||
|
information should be added in Bare Metal API document[1]:
|
||||||
|
|
||||||
|
For iSCSI example::
|
||||||
|
|
||||||
|
{"auth_method": "CHAP",
|
||||||
|
"auth_username": "XXX",
|
||||||
|
"auth_password": "XXX",
|
||||||
|
"target_iqn": "iqn.2010-10.com.example:vol-X",
|
||||||
|
"target_portal": "192.168.0.123:3260",
|
||||||
|
"volume_id": "12345678-...",
|
||||||
|
"target_lun": 0,
|
||||||
|
"access_mode": "rw",
|
||||||
|
"target_discovered": false,
|
||||||
|
"encrypted": false,
|
||||||
|
"qos_specs": null}
|
||||||
|
|
||||||
|
For iSCSI multipath example::
|
||||||
|
|
||||||
|
{"auth_method": "CHAP",
|
||||||
|
"auth_username": "XXX",
|
||||||
|
"auth_password": "XXX",
|
||||||
|
"target_iqns": ["iqn.2010-10.com.example:vol-X",
|
||||||
|
"iqn.2010-10.com.example:vol-Y"],
|
||||||
|
"target_portals": ["192.168.0.123:3260",
|
||||||
|
"192.168.0.124:3260"],
|
||||||
|
"volume_id": "12345678-...",
|
||||||
|
"target_luns": [0, 1],
|
||||||
|
"access_mode": "rw",
|
||||||
|
"target_discovered": false,
|
||||||
|
"encrypted": false,
|
||||||
|
"qos_specs": null}
|
||||||
|
|
||||||
|
For fibre channel example::
|
||||||
|
|
||||||
|
{"device_path": "/dev/disk/by-path/pci-XXXX",
|
||||||
|
"encrypted": false,
|
||||||
|
"qos_specs": null,
|
||||||
|
"target_lun": 1,
|
||||||
|
"access_mode": "rw",
|
||||||
|
"target_wwn": ["XXXX"]}
|
||||||
|
|
||||||
|
REST API masks credential information such as `auth_username` and
|
||||||
|
`auth_password` in iSCSI and iSCSI multipath examples in order to avoid
|
||||||
|
security risk.
|
||||||
|
|
||||||
|
* Add REST APIs end points to get/set values on them. For details see REST API
|
||||||
|
Impact section.
|
||||||
|
|
||||||
|
+ /v1/volume/connectors
|
||||||
|
+ /v1/volume/targets
|
||||||
|
+ /v1/nodes/<node_uuid or name>/volume/connectors
|
||||||
|
+ /v1/nodes/<node_uuid or name>/volume/targets
|
||||||
|
|
||||||
|
* Add new capability flags in ``node.properties['capabilities']``. These flags
|
||||||
|
show whether or not the node can boot from volume with each backend. If it
|
||||||
|
can boot from volume, we should set the flag to true.
|
||||||
|
|
||||||
|
+ iscsi_boot
|
||||||
|
+ fibre_channel_boot
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This should be set to true if the bare metal node supports booting from
|
||||||
|
that specific volume. It might be populated manually by operator or by
|
||||||
|
inspection, but that is not in the scope of this spec.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
In the future, Ironic will provide driver capabilities information[3].
|
||||||
|
Nova can use that information to choose appropriate node.
|
||||||
|
|
||||||
|
* If a list of targets are specified, it's up to the driver handling the deploy
|
||||||
|
to take care of this. For multi-pathing, Ironic driver, bare metal hardware
|
||||||
|
and the operating system should support it. If Ironic driver and bare metal
|
||||||
|
hardware supports it, but instance operating system doesn't understand it,
|
||||||
|
then it might lead to failure in booting the instance or corrupting the
|
||||||
|
information in the Cinder volume.
|
||||||
|
|
||||||
|
* Information which is stored in volume_connector and volume_target tables
|
||||||
|
are used in drivers in order to boot the node from volume. Changes for
|
||||||
|
reference driver, driver interfaces are described in the spec[4].
|
||||||
|
|
||||||
|
|
||||||
|
Alternatives
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Saving connector information in a new node attribute like
|
||||||
|
volume_initiator_info. This change has less impact on current code and API
|
||||||
|
but proposed one has more benefits such as better integrity check, faster
|
||||||
|
query from db and easier to store information related to a particular
|
||||||
|
connector.
|
||||||
|
|
||||||
|
* Saving target information in a new node attribute like volume_target_info.
|
||||||
|
This change has less impact on current code and API but proposed one has
|
||||||
|
more benefits such as better integrity check, faster query from db and
|
||||||
|
easier to store information related to a particular target.
|
||||||
|
|
||||||
|
* Saving target information in instance_info along with other instance related
|
||||||
|
information. This seems to be straightforward because basically target
|
||||||
|
volume information is related to the instance. In this case,
|
||||||
|
``node.instance_info`` is nested to store target information. This makes it
|
||||||
|
difficult for users to manipulate target information, and for a driver to
|
||||||
|
validate it. On the other hand, current approach can avoid nesting
|
||||||
|
instance_info and so it's easier to use those information. Note, ironic
|
||||||
|
clears the target connection information on the node tear_down.
|
||||||
|
|
||||||
|
* Not implement storage of target and initiator information, which ultimately
|
||||||
|
would not improve user experience and require manual post-deployment
|
||||||
|
configuration for out-of-band control. For in-band use, Nova ironic driver
|
||||||
|
can manage initiator information and it is proposed by jroll[2].
|
||||||
|
|
||||||
|
Data model impact
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
* Add new type of object ``VolumeConnector`` in objects/volume_connector.py. It
|
||||||
|
inherits IronicObject class. The new object will have the following fields:
|
||||||
|
|
||||||
|
+ ``id``
|
||||||
|
+ ``uuid``
|
||||||
|
+ ``node_id``
|
||||||
|
+ ``type``
|
||||||
|
+ ``connector_id``
|
||||||
|
+ ``extra``
|
||||||
|
+ ``created_at`` (defined in IronicObject class)
|
||||||
|
+ ``updated_at`` (defined in IronicObject class)
|
||||||
|
|
||||||
|
* Add new type of object ``VolumeTarget`` in objects/volume_target.py. It
|
||||||
|
inherits IronicObject class. The new object will have the following fields:
|
||||||
|
|
||||||
|
+ ``id``
|
||||||
|
+ ``uuid``
|
||||||
|
+ ``node_id``
|
||||||
|
+ ``volume_type``
|
||||||
|
+ ``properties``
|
||||||
|
+ ``boot_index``
|
||||||
|
+ ``volume_id``
|
||||||
|
+ ``extra``
|
||||||
|
+ ``created_at`` (defined in IronicObject class)
|
||||||
|
+ ``updated_at`` (defined in IronicObject class)
|
||||||
|
|
||||||
|
|
||||||
|
State Machine Impact
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
REST API impact
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Six new REST API endpoints will be introduced with this change.
|
||||||
|
|
||||||
|
- ``/v1/volume/connectors``
|
||||||
|
|
||||||
|
+ To set the volume connector (initiator) information::
|
||||||
|
|
||||||
|
POST /v1/volume/connectors
|
||||||
|
|
||||||
|
with the body containing the JSON description of the volume connector.
|
||||||
|
It will return 201 on success, 400 if some required attributes are missing
|
||||||
|
or having invalid value OR 409 if an entry already exists for the same
|
||||||
|
volume connector.
|
||||||
|
|
||||||
|
+ To get information about all volume connectors::
|
||||||
|
|
||||||
|
GET /v1/volume/connectors
|
||||||
|
|
||||||
|
This operation will return a list of dictionaries. It contains information
|
||||||
|
about all volume connectors::
|
||||||
|
|
||||||
|
{
|
||||||
|
"volume_connectors":[
|
||||||
|
{
|
||||||
|
"connector_id": "<wwpn>",
|
||||||
|
"links": [ ... ],
|
||||||
|
"type": "wwpn",
|
||||||
|
"uuid": "<uuid>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"connector_id": "<wwpn>",
|
||||||
|
"links": [ ... ],
|
||||||
|
...
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
This will return 200 on success
|
||||||
|
|
||||||
|
This operation can take parameters like ``type``, ``container_id``,
|
||||||
|
``limit``, ``marker``, ``sort_dir``, and ``fields``.
|
||||||
|
|
||||||
|
+ To get detail information about all volume connectors::
|
||||||
|
|
||||||
|
GET /v1/volume/connectors/detail
|
||||||
|
|
||||||
|
The operation will return a list of dictionaries. It contains detailed
|
||||||
|
information about all volume connectors::
|
||||||
|
|
||||||
|
{
|
||||||
|
"volume_connectors":[
|
||||||
|
{
|
||||||
|
"connector_id": "<wwpn>",
|
||||||
|
"created_at": "<created_date>",
|
||||||
|
"extra": {},
|
||||||
|
"links": [ ... ],
|
||||||
|
"node_uuid": "<node_uuid>",
|
||||||
|
"type": "wwpn",
|
||||||
|
"updated_at": "<updated_date>",
|
||||||
|
"uuid": "<uuid>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"connector_id": "<wwpn>",
|
||||||
|
"created_at": "<created_date>",
|
||||||
|
...
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
It will return 200 on success.
|
||||||
|
|
||||||
|
This operation can take parameters like ``type``, ``container_id``,
|
||||||
|
``limit``, ``marker``, and ``sort_dir``.
|
||||||
|
|
||||||
|
+ It should be possible to pass ``node`` as a parameter which can be a node
|
||||||
|
name or a node UUID to get all volume connectors for that particular node::
|
||||||
|
|
||||||
|
GET /v1/volume/connectors?node=<node_uuid or name>
|
||||||
|
GET /v1/volume/connectors/detail?node=<node_uuid or name>
|
||||||
|
|
||||||
|
It will return 200 on success or 404 if the node is not found.
|
||||||
|
|
||||||
|
- ``/v1/volume/connectors/<volume_connector_uuid>``
|
||||||
|
|
||||||
|
+ To get detail information about a particular volume connector::
|
||||||
|
|
||||||
|
GET /v1/volume/connectors/<volume_connector_uuid>
|
||||||
|
|
||||||
|
This will return 200 on success or 404 if volume connector is not found.
|
||||||
|
|
||||||
|
+ To update a particular volume connector::
|
||||||
|
|
||||||
|
PATCH /v1/volume/connectors/<volume_connector_uuid>
|
||||||
|
|
||||||
|
This will return 200 and the representation of the updated resource on
|
||||||
|
success and 404 if volume connector is not found.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Updating connector information when the node is in POWER_ON or REBOOT
|
||||||
|
state is blocked. It means that users need to make sure the node is in
|
||||||
|
POWER_OFF state before updating connector information. When connector
|
||||||
|
information is updated, driver should update node configuration.
|
||||||
|
|
||||||
|
+ To delete volume connector::
|
||||||
|
|
||||||
|
DELETE /v1/volume/connectors/<volume_connector_uuid>
|
||||||
|
|
||||||
|
It will return 204 on success or 404 if volume connector is not found or
|
||||||
|
405 if the node is not in POWER_OFF state.
|
||||||
|
|
||||||
|
- ``/v1/nodes/<node_uuid or name>/volume/connectors``
|
||||||
|
|
||||||
|
+ To get all the volume connectors information for a node::
|
||||||
|
|
||||||
|
GET ``/v1/nodes/<node_uuid or name>/volume/connectors``
|
||||||
|
|
||||||
|
- ``/v1/volume/targets``
|
||||||
|
|
||||||
|
+ To set the volume target information::
|
||||||
|
|
||||||
|
POST /v1/volume/targets
|
||||||
|
|
||||||
|
with the body containing the JSON description of the volume target.
|
||||||
|
It will return 201 on success, 400 if some required attributes are missing
|
||||||
|
or having invalid value OR 409 if an entry already exists for the same
|
||||||
|
volume target.
|
||||||
|
|
||||||
|
+ To get information about all volume targets::
|
||||||
|
|
||||||
|
GET /v1/volume/targets
|
||||||
|
|
||||||
|
This operation will return a list of dictionaries. It contains information
|
||||||
|
about all volume targets::
|
||||||
|
|
||||||
|
{
|
||||||
|
"volume_targets":[
|
||||||
|
{
|
||||||
|
"boot_index", "<boot_index>",
|
||||||
|
"links": [ ... ],
|
||||||
|
"uuid": "<uuid>",
|
||||||
|
"volume_id": "<volume_id>"
|
||||||
|
"volume_type": "<volume_target_type>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"boot_index", "<boot_index>",
|
||||||
|
"links": [ ... ],
|
||||||
|
...
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
This will return 200 on success.
|
||||||
|
|
||||||
|
This operation can take parameters like ``boot_index``, ``volume_id``,
|
||||||
|
``volume_type``, ``limit``, ``marker``, ``sort_dir``, and ``fields``.
|
||||||
|
|
||||||
|
+ To get details information about all volume targets::
|
||||||
|
|
||||||
|
GET /v1/volume/targets/detail
|
||||||
|
|
||||||
|
The operation will return a list of dictionaries. It contains detailed
|
||||||
|
information about all volume targets::
|
||||||
|
|
||||||
|
{
|
||||||
|
"volume_targets":[
|
||||||
|
{
|
||||||
|
"boot_index": "<boot_index>",
|
||||||
|
"created_at": "<created_date>",
|
||||||
|
"extra": {},
|
||||||
|
"links": [ ... ],
|
||||||
|
"node_uuid": "<node_uuid>",
|
||||||
|
"properties" : { "<target_information>" },
|
||||||
|
"updated_at": "<updated_date>",
|
||||||
|
"uuid": "<uuid>",
|
||||||
|
"volume_id": "<volume_id>",
|
||||||
|
"volume_type": "<volume_target_type>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"boot_index": "<boot_index>",
|
||||||
|
"created_at": "<created_date>",
|
||||||
|
...
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
It will return 200 on success.
|
||||||
|
|
||||||
|
This operation can take parameters like ``boot_index``, ``volume_id``,
|
||||||
|
``volume_type``, ``limit``, ``marker``, and ``sort_dir``.
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
`properties` may include credential information. This API will
|
||||||
|
mask it to avoid security risk.
|
||||||
|
|
||||||
|
+ It should be possible to pass ``node`` as a parameter which can be a node
|
||||||
|
name or a node UUID to get all volume targets for that particular node::
|
||||||
|
|
||||||
|
GET /v1/volume/targets?node=<node_uuid or name>
|
||||||
|
GET /v1/volume/targets/detail?node=<node_uuid or name>
|
||||||
|
|
||||||
|
It will return 200 on success or 404 if the node is not found.
|
||||||
|
|
||||||
|
- ``/v1/volume/targets/<volume_target_uuid>``
|
||||||
|
|
||||||
|
+ To get detailed information about a particular volume target::
|
||||||
|
|
||||||
|
GET /v1/volume/targets/<volume_target_uuid>
|
||||||
|
|
||||||
|
This will return 200 on success or 404 if volume target is not found.
|
||||||
|
|
||||||
|
+ To update a particular volume target::
|
||||||
|
|
||||||
|
PATCH /v1/volume/targets/<volume_target_uuid>
|
||||||
|
|
||||||
|
This will return 200 and the representation of the updated resource on
|
||||||
|
success, 404 if volume target is not found or 405 if the node is not
|
||||||
|
POWER_OFF state.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Updating target information when the node is in POWER_ON or REBOOT state
|
||||||
|
is blocked. It means that users need to make sure the node is in
|
||||||
|
POWER_OFF state before updating target information. When target
|
||||||
|
information is updated, driver should update node configuration.
|
||||||
|
|
||||||
|
+ To delete volume target::
|
||||||
|
|
||||||
|
DELETE /v1/volume/targets/<volume_target_uuid>
|
||||||
|
|
||||||
|
It will return 204 on success, 404 if volume target is not found or
|
||||||
|
405 if the node is not in POWER_OFF state.
|
||||||
|
|
||||||
|
- ``/v1/nodes/<node_uuid or name>/volume/targets``
|
||||||
|
|
||||||
|
+ To get all the volume targets information for a node::
|
||||||
|
|
||||||
|
GET ``/v1/nodes/<node_uuid or name>/volume/targets``
|
||||||
|
|
||||||
|
- ``/v1/nodes/<node_uuid or name>/volume/targets``
|
||||||
|
|
||||||
|
+ To get all the volume targets information for a node::
|
||||||
|
|
||||||
|
GET ``/v1/nodes/<node_uuid or name>/volume/targets``
|
||||||
|
|
||||||
|
The endpoint ``GET /v1/nodes/detail`` will provide the volume connectors and
|
||||||
|
targets information for the node with links to them. Also, the endpoint
|
||||||
|
``GET /v1/nodes/<node_uuid or name>`` will provide the volume connectors and
|
||||||
|
targets information for the specified node.
|
||||||
|
|
||||||
|
For the above REST API changes, micro version will be bumped and 406 will be
|
||||||
|
raised if newer endpoints are accessed with a lesser micro version.
|
||||||
|
|
||||||
|
Client (CLI) impact
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* A new ``VolumeConnectorManager`` will be added to ``ironicclient`` to get/set
|
||||||
|
connector information for the node. Also the CLI will be modified as
|
||||||
|
follows::
|
||||||
|
|
||||||
|
ironic volume-connector-create --node <node> --type <type>
|
||||||
|
--connector_id <connector_id>
|
||||||
|
[-e <key=value>] [-u <uuid>]
|
||||||
|
ironic volume-connector-delete <uuid> [<uuid>]
|
||||||
|
ironic volume-connector-list [--detail] [--type <type>]
|
||||||
|
[--connector_id <connector_id>]
|
||||||
|
[--limit <limit>] [--marker <uuid>]
|
||||||
|
[--sort-key <field>] [--sort-dir <direction>]
|
||||||
|
[--fields <field> [<field> ...]]
|
||||||
|
ironic volume-connector-show [--fields <field> [<field> ...]] <uuid>
|
||||||
|
ironic volume-connector-update <uuid> <op> <path=value> [<path=value> ...]
|
||||||
|
|
||||||
|
ironic node-volume-connector-list [--detail] [--limit <limit>]
|
||||||
|
[--marker <uuid>] [--sort-key <field>]
|
||||||
|
[--sort-dir <direction>]
|
||||||
|
[--fields <field> [<field> ...]]
|
||||||
|
<node>
|
||||||
|
|
||||||
|
* A new ``VolumeTargetManager`` will be added to ``ironicclient`` to get/set
|
||||||
|
target information for the node. Also the CLI will be modified as
|
||||||
|
follows::
|
||||||
|
|
||||||
|
ironic volume-target-create --node <node> --volume_type <volume_type>
|
||||||
|
--volume_id <volume_id>
|
||||||
|
[--properties <key=value>]
|
||||||
|
[--boot_index <boot_index>]
|
||||||
|
[-e <key=value>] [-u <uuid>]
|
||||||
|
ironic volume-target-delete <uuid> [<uuid>]
|
||||||
|
ironic volume-target-list [--detail] [--volume_type <volume_type>]
|
||||||
|
[--volume_id <volume_id>]
|
||||||
|
[--boot_index <boot_index>] [--limit <limit>]
|
||||||
|
[--marker <uuid>] [--sort-key <field>]
|
||||||
|
[--sort-dir <direction>]
|
||||||
|
[--fields <field> [<field> ...]]
|
||||||
|
ironic volume-target-show [--fields <field> [<field> ...]] <uuid>
|
||||||
|
ironic volume-target-update <uuid> <op> <path=value> [<path=value> ...]
|
||||||
|
|
||||||
|
ironic node-volume-target-list [--detail] [--limit <limit>]
|
||||||
|
[--marker <uuid>] [--sort-key <field>]
|
||||||
|
[--sort-dir <direction>]
|
||||||
|
<node>
|
||||||
|
|
||||||
|
* New objects, ``CreateBaremetalVolumeConnector``,
|
||||||
|
``DeleteBaremetalVolumeConnector``, ``ListBaremetalVolumeConnector``,
|
||||||
|
``SetBaremetalVolumeConnector``, ``ShowBaremetalVolumeConnector``,
|
||||||
|
and ``UnsetBaremetalVolumeConnector`` will be added to ``openstackclient``
|
||||||
|
plugin to get/set connector information for the node. Also the CLI will be
|
||||||
|
modified as follows::
|
||||||
|
|
||||||
|
openstack baremetal volume connector create [-h]
|
||||||
|
[-f {json,shell,table,value,yaml}]
|
||||||
|
[-c COLUMN]
|
||||||
|
[--max-width <integer>]
|
||||||
|
[--noindent] [--prefix PREFIX]
|
||||||
|
--node <node_uuid> --type <type>
|
||||||
|
--connector_id <connector_id>
|
||||||
|
[--extra <key=value>]
|
||||||
|
[--uuid <uuid>]
|
||||||
|
openstack baremetal volume connector delete [-h] <connector> [<connector>]
|
||||||
|
openstack baremetal volume connector list [-h]
|
||||||
|
[-f {json,shell,table,value,yaml}]
|
||||||
|
[-c COLUMN]
|
||||||
|
[--max-width <integer>]
|
||||||
|
[--noindent]
|
||||||
|
[--quote {all,minimal,none,nonnumeric}]
|
||||||
|
[--limit <limit>]
|
||||||
|
[--marker <uuid>]
|
||||||
|
[--sort <key>[:<direction>]]
|
||||||
|
[--long | fields <field [field] ...>]
|
||||||
|
openstack baremetal volume connector set [-h] [--node <node>]
|
||||||
|
[--type <type>]
|
||||||
|
[--connector_id <connector_id>]
|
||||||
|
[--extra <key=value>] <connector>
|
||||||
|
openstack baremetal volume connector show [-h]
|
||||||
|
[-f {json,shell,table,value,yaml}]
|
||||||
|
[-c COLUMN]
|
||||||
|
[--max-width <integer>]
|
||||||
|
[--noindent] [--prefix PREFIX]
|
||||||
|
[--fields <field> [<field> ...]]
|
||||||
|
<connector>
|
||||||
|
openstack baremetal volume connector unset [-h] [--extra <key>] <connector>
|
||||||
|
|
||||||
|
* New objects, ``CreateBaremetalVolumeTarget``,
|
||||||
|
``DeleteBaremetalVolumeTarget``, ``ListBaremetalVolumeTarget``,
|
||||||
|
``SetBaremetalVolumeTarget``, ``ShowBaremetalVolumeTarget``, and
|
||||||
|
``UnsetBaremetalVolumeTarget`` will be added to ``openstackclient`` plugin
|
||||||
|
to get/set target information for the node. Also the CLI will be modified
|
||||||
|
as follows::
|
||||||
|
|
||||||
|
|
||||||
|
openstack baremetal volume target create [-h]
|
||||||
|
[-f {json,shell,table,value,yaml}]
|
||||||
|
[-c COLUMN] [--max-width <integer>]
|
||||||
|
[--noindent] [--prefix PREFIX]
|
||||||
|
--node <node_uuid> --type <type>
|
||||||
|
--volume_id <volume_id>
|
||||||
|
[--properties <key=value>]
|
||||||
|
[--boot_index <boot_index>]
|
||||||
|
[--extra <key=value>]
|
||||||
|
[--uuid <uuid>]
|
||||||
|
openstack baremetal volume target delete [-h] <target> [<target>]
|
||||||
|
openstack baremetal volume target list [-h]
|
||||||
|
[-f {json,shell,table,value,yaml}]
|
||||||
|
[-c COLUMN] [--max-width <integer>]
|
||||||
|
[--noindent]
|
||||||
|
[--quote {all,minimal,none,nonnumeric}]
|
||||||
|
[--limit <limit>] [--marker <uuid>]
|
||||||
|
[--sort <key>[:<direction>]]
|
||||||
|
[--long | fields <field [field] ...>]
|
||||||
|
openstack baremetal volume target set [-h] [--node <node>] [--type <type>]
|
||||||
|
[--volume_id <volume_id>]
|
||||||
|
[--properties <key=value>]
|
||||||
|
[--boot_index <boot_index>]
|
||||||
|
[--extra <key=value>] <target>
|
||||||
|
openstack baremetal volume target show [-h]
|
||||||
|
[-f {json,shell,table,value,yaml}]
|
||||||
|
[-c COLUMN] [--max-width <integer>]
|
||||||
|
[--noindent] [--prefix PREFIX]
|
||||||
|
[--fields <field> [<field> ...]]
|
||||||
|
<target>
|
||||||
|
openstack baremetal volume target unset [-h]
|
||||||
|
[--properties <key>]
|
||||||
|
[--boot_index] [--extra <key>]
|
||||||
|
<target>
|
||||||
|
|
||||||
|
RPC API impact
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Four new rpcapi method ``update_volume_connector``,
|
||||||
|
``destroy_volume_connector``, ``update_volume_target``, and
|
||||||
|
``destroy_volume_target`` will be added.
|
||||||
|
|
||||||
|
* ``update_volume_connector``
|
||||||
|
|
||||||
|
This method takes context and volume connector object as input and returns
|
||||||
|
updated volume connector object.
|
||||||
|
|
||||||
|
* ``destroy_volume_connector``
|
||||||
|
|
||||||
|
This method takes context and volume connector object as input.
|
||||||
|
|
||||||
|
* ``update_volume_target``
|
||||||
|
|
||||||
|
This method takes context and volume target object as input and returns
|
||||||
|
updated volume target object.
|
||||||
|
|
||||||
|
* ``destroy_volume_target``
|
||||||
|
|
||||||
|
This method takes context and volume target object as input.
|
||||||
|
|
||||||
|
Driver API impact
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Nova driver impact
|
||||||
|
------------------
|
||||||
|
|
||||||
|
When spawning a new instance, Nova Ironic virt driver queries Ironic
|
||||||
|
(through API) to find out the volume connector information. It passes the
|
||||||
|
volume connector information to Cinder which returns the target information.
|
||||||
|
This is then passed down to Ironic. Detailed information about Nova Ironic
|
||||||
|
driver can be found in the spec [5].
|
||||||
|
|
||||||
|
Security impact
|
||||||
|
---------------
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
As for FC zoning, Cinder takes care of it[6].
|
||||||
|
|
||||||
|
|
||||||
|
Other end user impact
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Scalability impact
|
||||||
|
------------------
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Performance Impact
|
||||||
|
------------------
|
||||||
|
|
||||||
|
This may extend the time required for nova boot/delete, but it's not a big
|
||||||
|
impact and it's important for enterprise users.
|
||||||
|
|
||||||
|
Other deployer impact
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
* If administrators want to provide boot from volume feature, they need to
|
||||||
|
fill out following initiator information before activating the node.
|
||||||
|
|
||||||
|
+ iSCSI:
|
||||||
|
|
||||||
|
- ip
|
||||||
|
- iqn
|
||||||
|
- mac
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
ip may be omitted when Neutron is used to manage the storage network.
|
||||||
|
|
||||||
|
|
||||||
|
+ FC:
|
||||||
|
|
||||||
|
- wwnn
|
||||||
|
- wwpn
|
||||||
|
|
||||||
|
Administrators need to set the node.properties['capabilities']
|
||||||
|
(iscsi_boot and/or fibre_channel_boot) true.
|
||||||
|
|
||||||
|
It's better if inspection automatically collects and registers them.
|
||||||
|
For example, in the case of a node with FC-HBA, inspection(in-band) can
|
||||||
|
get wwnn and wwpn from sysfs like following::
|
||||||
|
|
||||||
|
# cat /sys/class/scsi_host/host*/device/fc_host/host*/node_name
|
||||||
|
# cat /sys/class/scsi_host/host*/device/fc_host/host*/port_name
|
||||||
|
|
||||||
|
* If users want to boot a node from volume in Ironic standalone mode, they
|
||||||
|
need additional tooling to leverage this functionality. For example, that
|
||||||
|
tool needs to do something like:
|
||||||
|
|
||||||
|
- Get initiator information from Ironic
|
||||||
|
- Call the storage management tool with initiator information to create a
|
||||||
|
new volume (maybe from template) and attach it to the initiator
|
||||||
|
- Get target information from storage management tool
|
||||||
|
- Put target information into Ironic
|
||||||
|
|
||||||
|
Developer impact
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Driver developers can consume the information mentioned above to write
|
||||||
|
boot from volume support in their driver. The details about reference driver
|
||||||
|
and driver interface specs are described in [4].
|
||||||
|
|
||||||
|
Implementation
|
||||||
|
==============
|
||||||
|
|
||||||
|
Assignee(s)
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Primary assignee:
|
||||||
|
satoru-moriya-br
|
||||||
|
|
||||||
|
Other contributors:
|
||||||
|
rameshg87
|
||||||
|
|
||||||
|
Work Items
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Create new table named volume_connectors and volume_targets
|
||||||
|
* Create new DB API methods
|
||||||
|
* Create new Object named VolumeConnector and VolumeTarget
|
||||||
|
* Create new RPC API methods
|
||||||
|
* Create new REST API endpoints
|
||||||
|
* Document the changes
|
||||||
|
* Enhance inspector to register connector information if available
|
||||||
|
* Enhance Client(CLI) to get/set connector and target information
|
||||||
|
* Enhance Nova-Ironic driver to support boot from volume with these APIs
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
============
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Testing
|
||||||
|
=======
|
||||||
|
|
||||||
|
* Unit tests will be added/updated to cover the changes.
|
||||||
|
|
||||||
|
* Tempest tests will be added to Ironic to ensure that the following newly
|
||||||
|
added API endpoints work correctly.
|
||||||
|
|
||||||
|
Upgrades and Backwards Compatibility
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Add a migration script for database.
|
||||||
|
|
||||||
|
Documentation Impact
|
||||||
|
====================
|
||||||
|
|
||||||
|
Documentations such as Installation guide and api-ref will be updated to
|
||||||
|
explain the newly added fields and end points.
|
||||||
|
|
||||||
|
* Installation guide:
|
||||||
|
|
||||||
|
http://docs.openstack.org/developer/ironic/deploy/install-guide.html
|
||||||
|
|
||||||
|
* api-ref documentation:
|
||||||
|
|
||||||
|
http://developer.openstack.org/api-ref/baremetal/index.html
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [1] http://developer.openstack.org/api-ref/baremetal/index.html
|
||||||
|
.. [2] https://review.openstack.org/#/c/184652/
|
||||||
|
.. [3] http://specs.openstack.org/openstack/ironic-specs/specs/backlog/driver-capabilities.html
|
||||||
|
.. [4] https://review.openstack.org/#/c/294995
|
||||||
|
.. [5] https://review.openstack.org/#/c/211101/
|
||||||
|
.. [6] http://docs.openstack.org/mitaka/config-reference/block-storage/fc-zoning.html
|
||||||
|
.. [7] https://blueprints.launchpad.net/ironic/+spec/cinder-integration
|
||||||
|
.. [8] https://wiki.openstack.org/wiki/Ironic/blueprints/cinder-integration
|
|
@ -0,0 +1 @@
|
||||||
|
../approved/volume-connection-information.rst
|
Loading…
Reference in New Issue