Port and Service Binding Model for Gluon

This document describes the generic port and service-binding model
available in Gluon to define new networking service APIs.

Moreover, this document shall support developers of new APIs
by providing a guideline for new APIs.  In addition to the generic
model, a slightly adapted version of the L3VPN model is included as
an example.  This commit is a combination of:

https://review.openstack.org/392250 and
https://review.openstack.org/395738

Co-Authored-By: Georg.Kunz@ericsson.com
Co-Authored-By: Thomas.Hambleton@nokia.com

Change-Id: I69f2b530088d4dd7bc21be502210db1740f507d3
Implements: blueprint port-service-binding-model
This commit is contained in:
Thomas Hambleton 2016-11-17 14:25:23 -06:00 committed by Thomas Hambleton
parent 5e1f8b3ede
commit ff669cac79
1 changed files with 424 additions and 0 deletions

View File

@ -0,0 +1,424 @@
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 [1] 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.
* **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.
::
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
[1] NetReady - Service Binding model: http://artifacts.opnfv.org/netready/colorado/docs/requirements/index.html#service-binding-design-pattern