Interface Attach and Detach API

https://bugs.launchpad.net/ironic/+bug/1582188

We are adding pluggable network interfaces to Ironic. These interfaces will be configurable per Ironic node, this means that different nodes might have different ways of handling their network interfaces. We need a way that different network interfaces can override the virtual network interface (VIF) to physical network interface (PIF) mapping logic currently contained in nova.

Problem description

Currently we use an Ironic port update to assign tenant neutron ports to Ironic ports using their extra field. Doing the mapping this way may not work for a third party network interface implementation. This also ties the ironic nova virt driver to a particular network VIF to PIF mapping implementation. If a third party network interface wants to do something different with network VIF to PIF mapping such as storing the port IDs for dynamic vNIC creation later in the provisioning process or we as the Ironic team want to change an implementation detail we have to submit changes into nova. Additionally if we want to support post-deployment attach and detach of a network VIF then we have to watch for any updates made to the port object and interpret certain changes as certain actions.

Proposed change

To solve this problem I propose to add a new API endpoint,

  • POST v1/nodes/<node_id>/vifs
  • GET v1/nodes/<node_id>/vifs
  • DELETE v1/nodes/<node_id>/vifs/<vif_id>

These API endpoints will take via a POST body, a JSON representation of a generic VIF object. Making it generic allows for non-neutron based implementations to use this API. This VIF object will be passed to new functions in the pluggable network interfaces:

def vif_attach(self, vif):
...
def vif_detach(self, vif_id):
...
def vif_list(self):
...

The network interface can use these functions to handle attaching the VIF to the Ironic node in whichever way it needs to for its implementation. This could be by adding a field to the Ironic port as with the existing implementation, or it might be different for example storing it in a list in the node’s driver_internal_info.

The ironic nova virt driver will be updated to use this new API in the plug_vifs and unplug_vifs functions, unbinding it from the underlying implementation details.

Alternatives

  • Continue to use a port update to allow nova to interact with ironic ports and soon portgroups, documenting the vif_port_id etc logic as a defined API for the network interfaces to use.

Data model impact

None

State Machine Impact

None

REST API impact

  • GET v1/nodes/<node_id>/vifs

    • Calls to vif_list on the node’s network interface

    • This is a synchronous API endpoint, and the normal ironic rules apply for avoiding implementing tasks that take a long time or are unstable under synchronous endpoints.

    • Method: GET

    • Successful http response: 200

    • Expected response body is a JSON

      • JSON Schema:

        {
            "title": "VIFS",
            "type": "object",
            "properties": {
                "vifs": {
                    "description": "List of VIFs currently attached"
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            }
                        },
                        "required": ["id"]
                    }
                }
            },
            "required": ["vifs"]
        }
      • Example:

        {
            "vifs": [
                        {
                            "id": "8e6ba175-1c16-4dfa-82b9-dfc12f129170",
                        }
            ]
        }
        
  • POST v1/nodes/<node_id>/vifs

    • Calls vif_attach on the network interface for the node, passing in the json provided

    • This is a synchronous API endpoint, and the normal ironic rules apply for avoiding implementing tasks that take a long time or are unstable under synchronous endpoints.

    • Method: POST

    • Successful http response: 204

    • Expected error response codes:

      • 404, Node not found
      • 400, Request was malformed
      • 409, Conflict between the requested VIF to attach and other VIFs already attached
      • 422, The request was good but unable to attach the VIF for a defined reason, for example: “No physical interfaces available to attach too”
    • Expected data is a JSON

      • JSON Schema:

        {
            "title": "Attachment",
            "type": "object",
            "properties": {
                "id": {
                    "description": "ID of VIF to attach"
                    "type": "string"
                },
            },
            "required": ["id"]
        }
      • Example:

        {
          "id": "8e6ba175-1c16-4dfa-82b9-dfc12f129170"
        }
        
    • Expected response body is empty

  • DELETE v1/nodes/<node_id>/vifs/<vif_id>

    • Calls vif_detach on the network interface for the node, passing in the json provided
    • This is a synchronous API endpoint, and the normal ironic rules apply for avoiding implementing tasks that take a long time or are unstable under synchronous endpoints.
    • Method: DELETE
    • Successful http response: 204
    • Expected error response codes:
      • 404, Node not found
      • 400, Request was malformed
      • 422, The request was good but unable to detach the VIF for a defined reason
    • Expected response body is empty.
  • Does the API microversion need to increment? Yes

  • Is a corresponding change in the client library and CLI necessary? Yes

  • As these are new API entry points they will not affect older clients.

Client (CLI) impact

“ironic” CLI

  • ironic node-vif-list <node_id>
  • ironic node-vif-attach <node_id> <vif_id>
  • ironic node-vif-detach <node_id> <vif_id>

“openstack baremetal” CLI

  • openstack baremetal node vif list <node_id>
  • openstack baremetal node vif attach <node_id> <vif_id>
  • openstack baremetal node vif detach <node_id> <vif_id>

RPC API impact

The RPC API will implement:

  • vif_attach(self, context, node_id, vif)
  • vif_detach(self, context, node_id, vif_id)
  • vif_list(self, context, node_id)

Driver API impact

Base network interface will need to be extended with:

def vif_list(self, task):
    # TODO(sambetts): Uncomment when vif_port_id in port.extra is removed.
    # raise NotImplemented
    default_vif_list()

def vif_attach(self, task, vif):
    # TODO(sambetts): Uncomment when vif_port_id in port.extra is removed.
    # raise NotImplemented
    default_vif_attach(vif)

def vif_detach(self, task, vif_id):
    # TODO(sambetts): Uncomment when vif_port_id in port.extra is removed.
    # raise NotImplemented
    default_vif_detach(vif_id)

Existing flat, neutron and noop network interfaces will need extending to include implementations for these functions.

Flat network driver will need to implement add_provisioning_network to bind the ports that used to be bound by nova.

Nova driver impact

plug/unplug_vifs logic will be replaced by calling attach/detach for every VIF passed into those functions.

nova.virt.driver.IronicDriver.macs_for_instance will be removed because mapping is handled inside Ironic so mac_address assignment must happen at binding later in the process.

nova.virt.driver.IronicDriver.network_binding_host_id will be changed to return None in all cases, so that neutron ports remain unbound until Ironic binds them during deployment.

nova driver will need to include the nova compute host ID in the instance_info so that the ironic flat network interface can use it to update the neutron ports mimicking the existing nova behavior.

The nova driver ironic API version requirement will need to be increased to the version that implements the attach and detach APIs. Operators will need to ensure the version of python-ironicclient they have installed on the nova compute service supports the new APIs.

Ramdisk impact

None

Security impact

None

Other end user impact

None

Scalability impact

None

Performance Impact

None

Other deployer impact

None

Developer impact

Developers of network interfaces will need to consider how their network interface wants to handle ports.

Implementation

Assignee(s)

Primary assignee:
sambetts

Work Items

  • Add new APIs to Ironic
  • Update existing ironic network interfaces to support the new APIs
  • Add new APIs to ironic client
  • Update nova virt driver to use new APIs via client

Testing

These changes will be tested as part of the normal gate process, as they will be part of the normal ironic deployment workflow.

Upgrades and Backwards Compatibility

Setting vif_port_id via a port/portgroup update will be deprecated in favor of the new APIs. A deprecation message should be issued on a port update if a user is directly setting vif_port_id on a port or portgroup. Code will need to be added to ensure that the network interfaces will still process a vif_port_id set via that method.

As the old vif_port_id field is still supported although deprecated, old nova virt drivers will continue to work using that method.

Ironic must be upgraded before Nova is as newer nova virt drivers won’t work with older versions of Ironic which are missing the new APIs.

Out-of-tree network interfaces may not immediately implement the interface_attach and interface_detach methods, so during the period that vif_port_id is a deprecated method, we should also ensure we provide a default implementation of attach and detach, this default implementation should match the behaviour of ironic nova virt driver implementation setting the vif_port_id in port.extra and will be removed when support for vif_port_id in port.extra is removed.

Documentation Impact

New API and its usage needs to be documented.

References

None