==============================
Port and Service Binding Model
==============================

This document describes a generic modeling paradigm for new service APIs
(Protons) for OpenStack Gluon.

One fundamental driving force behind Gluon is the need for flexibility in
defining new network service APIs. The modeling paradigm described in the
following provides **design guidelines** and describes **best practices** for
creating new network service APIs. It hence supports developers in making the
best use of the flexibility provided by Gluon.

This model is based on the "service binding pattern" described in the NetReady
requirements document [0]_ and was adapted for Gluon.

The modeling tools in Gluon provide building blocks to allow the creation of
arbitrarily complex networking APIs.  However, some constraints are needed to
enforce model consistency and to ensure interworking with the rest of the
Openstack system.  This document describes the base objects that provide the
building blocks for defining new API objects and the relationship constraints
enforced by the system.

Objects and Relationships
-------------------------

The fundamental goal of this design paradigm is to clearly separate VM ports
from services and define how services bind to particular VM ports.
Specifically, there are four basic entities:

 i)   ports,
 ii)  interfaces,
 iii) services, and
 iv)  service bindings.


* **Port**

  A Port object represents a vNIC which is bindable to an OpenStack instance by
  the compute service (Nova). It hence comprises all required information for
  defining the hand-off point between a network and a VM instance.  Other
  services may in the future bind to ports (today, this happens within Neutron
  to bind things like routers and DHCP services in the ML2 world).

* **Interface**

  An interface is a logical entity which specifies a traffic segmentation
  mechanism (i.e., VLAN, VxLAN, GRE). Interfaces sit on top of ports and
  services are bound to interfaces instead of ports. Hence, interfaces allow
  for binding multiple (incompatible) services to a single port.

  When a Port is created, a corresponding default Interface object is
  automatically created for un-segmented traffic.  The UUID of this default
  interface will be the same as the UUID of the parent Port.  Additional
  Interface objects created for the Port will have unique UUID identifiers.

* **Service**

  A Service object represents a specific networking service, for example a L2
  network, a L3VPN or a service chaining service.

* **Service Binding**

  A Service Binding object binds a networking service to an Interface object.
  It has at least two attributes: a reference to an Interface and a reference
  to a Service. In addition, it can comprise attributes which are specific to a
  Service **and** an Interface.

  A Service Binding is **not** an extension of an Interface (no inheritance).
  Instead, it is a separate entity. Modeling the binding as a separate entity
  instead of encoding it in the Interface object has the following advantages:

  i) It allows for dynamically binding and unbinding a Service while keeping
  the VM and its port untouched. This simplifies VM migration across hosts as
  well as the migration of VMs between different network services and backends.

  ii) This entity allows for encapsulating service specific attributes which
  are specific to an Interface but that are not part of the Interface. For
  example, in a L3 service, the IP address of the interface bound to the
  service can be specified here whereas this is not required for a pure L2
  service.

The following diagram shows the relationship between these objects:

::


                                         +-----------+
                                         |           |
                                         |   Port    |
                                         |           |
                                         +-----+-----+
                                               | 1
                                               |
                                               |
                                               |
                                               | *
                 +-----------+           +-----+-----+
                 |  Service  | *       1 |           |
                 |  Binding  +-----------+ Interface +
                 |           |           |           |
                 +-----+-----+           +-----------+
                       | 1
                       |
                       |
                       |
                       |
                       | 1
                 +-----+-----+
                 |           |
                 |  Service  |
                 |           |
                 +-----------+


Base Object Definitions
-----------------------

These are the base objects for defining APIs.  These objects cannot be used
directly in an API definition.  They must be used as the base object for
objects of similar type.  There is an **"extends"** keyword in the
YAML model to provide this capability.  To have a functional networking API,
one must extend the ``BasePort``, ``BaseInterface``, ``BaseService`` and
``BaseServiceBinding`` objects.  It is not required that additional attributes
are defined for the extended objects.  See the Interface definition in the
example_ at the end of this document.

In addition, you can also define objects that do not extend any of the base
objects.  The proton server will provide CRUD functions on these objects but it
will not ensure any model consistency.  However, objects that are extensions of
base objects will be examined to ensure model consistency.  For example, the
proton server will have logic to validate that a Service Binding object
references only valid Interface and Service objects.

**BasePort**

  The ``BasePort`` object must be extended in an API model.  This base object
  contains all of the attributes needed by Nova to bind the Port to a VM.  The
  extended object may contain additional attributes needed by the API model
  (but not Nova).  Note, the extended object does not have to define additional
  attributes.

::

  BasePort:
      attributes:
          id:
              type: uuid
              primary: true
              description: "UUID of Port instance"
          name:
              type: string
              length: 64
              description: "Descriptive name for Port"
          tenant_id:
              type: uuid
              required: true
              description: "UUID of Tenant owning this Port"
          mac_address:
              type: string
              length: 17
              required: true
              description: "MAC address for Port"
              validate: mac_address
          admin_state_up:
              type: boolean
              required: true
              description: "Admin state of Port"
          status:
              type: enum
              required: true
              description: "Operational status of Port"
              values:
                  - 'ACTIVE'
                  - 'DOWN'
          vnic_type:
              type: enum
              required: true
              description: "Port should be attache to this VNIC type"
              values:
                 - 'normal'
                 - 'virtual'
                 - 'direct'
                 - 'macvtap'
                 - 'sriov'
                 - 'whole-dev'
          zone:
              type: string
              length: 64
              description: "zone information"
          mtu:
              type: integer
              description: "MTU"
              required: true
          vlan_transparency:
              type: boolean
              description: "Allow VLAN tagged traffic on Port"
              required: true
          profile:
              type: string # JSON Format
              length: 128
              description: "JSON string for binding profile dictionary"
          device_id:
              type: uuid
              description: "UUID of bound VM"
          device_owner:
              type: string
              length: 128
              description: "Name of compute or network service (if bound)"
          host_id:
              type: string
              length: 32
              description: "binding:host_id: Name of bound host"
          vif_details:
              type: string # JSON Format
              length: 128
              description: "binding:vif_details: JSON string for VIF details"
          vif_type:
              type: string
              length: 32
              description: "binding:vif_type: Headline binding type for VIF"

**BaseInterface**

  The ``BaseInterface`` object must be extended in an API model.  A default
  Interface object will automatically be created for each Port object.  Note,
  the extended object does not have to define additional attributes.

::

  BaseInterface:
      attributes:
          id:
              type: uuid
              required: true
              primary: true
              description: "UUID of Interface instance"
          port_id:
              type: uuid
              required: true
              description: "Pointer to Port instance"
          segmentation_type:
              type: enum
              required: true
              description: "Type of segmention for this interface"
              values:
                 - 'none'
                 - 'vlan'
                 - 'tunnel_vxlan'
                 - 'tunnel_gre'
                 - 'mpls'
                 - 'other'
          segmentation_id:
              type: integer
              required: true
              description: "Segmentation identifier"

**BaseService**

  The ``BaseService`` object must be extended in an API model. There can be
  multiple Services defined of a given model.  However, an Interface can only
  be bound to one Service.  Note, the extended object does not have to define
  additional attributes.

::

  BaseService:
      attributes:
          id:
              type: uuid
              required: true
              primary: true
              description: "UUID of Service instance"
          name:
              type: string
              length: 64
              description: "Descriptive name of Service"
          description:
              type: string
              length: 256
              description: "Description of Service"

**BaseServiceBinding**

  The ``BaseServiceBinding`` object must be extended in an API model.  Additional
  attributes can be added to the extended object that are specific for a Port
  bound to the Service. Note, the extended object does not have to define
  additional attributes.

  The ``service_id`` attribute can be re-defined in the extended object to specify
  the specific type of Service that can be bound.  The system will validate
  that the UUID specified for the ``interface_id`` is a known Interface object.  A
  null value is also accepted to effectively "unbind" the interface from the
  service.  The system will also validate that the UUID specified for the
  ``service_id`` is a known Service object.

::

  BaseServcieBinding:
      attributes:
          interface_id:
              type: uuid
              required: true
              primary: true
              description: "Pointer to Interface instance"
          service_id:
              type: uuid
              required: true
              description: "Pointer to Service instance"


Example L3VPN API using proposed model:
---------------------------------------

The following model defines an L3VPN service.  The Port and Interface objects
extend the ``BasePort`` and ``BaseInterface``, respectively.  You can extend an object
without adding attributes.  That is done with the Interface object.  Even if no
attributes are added, you are still required to extend these objects for a
functional API.  You must also extend the ``BaseService`` and ``BaseServiceBinding``
base objects in a similar manner.

Note, the VpnAfConfig object does not extend a base class.  The
modeling tools allow for the creation of arbitrary objects as needed by an API
model.  The proton server will not enforce any constraints on the relationships
between these objects and objects extended from base objects.

.. _example:

::

  Port:
      extends: BasePort
      api:
        name: ports
        parent:
          type: root
      attributes:
          alarms:
              type: string
              length: 256
              description: "Alarm summary for port"

  Interface:
      extends: BaseInterface
      api:
        name: interfaces
        parent:
          type: root

  VpnService:
    extends: BaseService
    api:
      name: vpns
      parent:
        type: root
    attributes:
        ipv4_family:
            type: string
            length: 255
            description: "Comma separated list of route target strings"
        ipv6_family:
            type: string
            length: 255
            description: "Comma separated list of route target strings"
        route_distinguishers:
            type: string
            length: 32
            description: "Route distinguisher for this VPN"

  VpnBinding:
      extends: BaseServiceBinding
      api:
        name: vpnbindings
        parent:
          type: root
      attributes:
          service_id:    # Override from base object for specific Service type
              type: VpnService
              required: true
              description: "Pointer to VpnService instance"
          ipaddress:
              type: 'string'
              length: 64
              description: "IP Address of port"
              validate: 'ipv4address'
          subnet_prefix:
              type: 'integer'
              description: "Subnet mask"
              values:
                  - '1-31'
          gateway:
              type: 'string'
              length: 64
              description: "Default gateway"
              validate: 'ipv4address'

  VpnAfConfig:
      api:
        name: vpnafconfigs
        parent:
          type: root
      attributes:
          vrf_rt_value:
              required: True
              type: string
              length: 32
              primary: 'True'
              description: "Route target string"
          vrf_rt_type:
              type: enum
              required: True
              description: "Route target type"
              values:
                  - export_extcommunity
                  - import_extcommunity
                  - both
          import_route_policy:
              type: string
              length: 32
              description: "Route target import policy"
          export_route_policy:
              type: string
              length: 32
              description: "Route target export policy"



References

.. [0] NetReady - Service Binding model: http://artifacts.opnfv.org/netready/colorado/docs/requirements/index.html#service-binding-design-pattern

