Jump to: navigation, search

Difference between revisions of "Neutron/ServiceTypeFramework"

 
(39 intermediate revisions by 4 users not shown)
Line 2: Line 2:
 
It describes entities and corresponding workflow.
 
It describes entities and corresponding workflow.
  
'''Service Type Framework serves two main purposes:'''<br />
+
'''Service Type Framework serves the main purpose:'''<br />
1. Allow tenant to specify vendor (or service provider) for the requested service<br />
+
Allow tenant to specify vendor (or service provider) for the requested service<br />
2. Allow admin to offer different kinds of service insertion models of the services<br />
+
Service Provider is main entity of Service Type Framework.<br/>
 +
As an addition, another benefits are possible to add on top of service providers like service offerings, insertion modes, etc.
  
 
<br />
 
<br />
Line 12: Line 13:
 
'''1. ServiceType'''  <br />
 
'''1. ServiceType'''  <br />
 
type of the service: loadbalancer, firewall, vpn, etc.<br />
 
type of the service: loadbalancer, firewall, vpn, etc.<br />
This is more or less static set of string values that are currently residing in quantum/plugins/common/constants.py<br />
+
This is more or less static set of string values that are currently residing in neutron/plugins/common/constants.py<br />
 
These strings are used as keys in plugins dictionary when dispatching REST API calls.<br />
 
These strings are used as keys in plugins dictionary when dispatching REST API calls.<br />
  
'''2. ServiceTypeProvider'''<br />
+
'''2. ServiceProvider'''<br />
 
This is a pointer to particular driver that implements some service.<br />
 
This is a pointer to particular driver that implements some service.<br />
Currently it has form ServiceType:PluginClass:DriverClass, where PluginClass and DriverClass are class paths that are loaded by quantum.<br />
+
Currently it has form ServiceType:Name:Driver[:default] where Driver is class identification that are loaded by neutron.<br />
A set of service type providers should be used by service plugin to load drivers.
+
Name is human-readable form which is used to represent provider for a user. <br />
TODO: if the model is single plugin per service type (like it is now), then it should be simplified to ServiceType:DriverClass<br />
+
Name should be unique for given ServiceType, but may be not unique across all providers. <br />
TODO: decide, if the set of ServiceTypeProviders needs to be dynamically configured. <br />
+
A set of service type providers should be used by service plugin to load plugin drivers.
Looks like there's no need for that, so it could be provided in configuration file in a form of string list.
+
ServiceProviders are specified in configuration file in a form of string list (multiline option).
  
'''3. ServiceGroup'''<br />
+
'''3. ProviderResourceAssociation'''<br />
Main intent of this entity is to express specific type of insertion for the group of ServiceTypeProviders.<br />
+
Entity that connects particular resource to a provider.<br />
In other word ServiceGroup is a list of ServicesTypeProviders that could be inserted in a certain way.<br />
+
Association consist of unique resource_id and provider_name.<br />
ServiceTypeProvider could be included in several ServiceGroups. In DB terms in means M:N relationship.<br />
+
It's assumed that resource_id (uuid type) is unique in the whole database, so additional service_type field is not needed. <br />
 +
<br />
  
'''4. Insertion model'''<br />
+
==== '''Integration with services''' ====
Just like ServiceType is should be a static set of string values: L2, L3, etc<br /><br />
+
In order to decouple service provider configuration from logical resource configuration the ProviderResourceAssociation is used.<br/>
  
 +
Special handling required for the case when admin is going to remove service provider from the configuration or a tenant decides to change provider for existing resource.
 +
In that cases lbaas should undeploy the resource using one provider and deploy it using the other,
 +
or just undeploy all resource in case provider is going to be removed. <br />
 +
Additional API call for each kind of service is required. This is subject for additional service-specific feature.
 +
<br /><br/>
 +
 +
==== '''Workflow for an admin''' ====
 +
Admin usually would add service providers to the quantum.conf file.<br/>
 +
That should make service plugins to load specified drivers and allow tenants to list service providers.<br/>
 +
Those provider options should be specified in multiline form, one per provider in format:<br/>
 +
<service_type>:<name>:<driver>[:default] <br/>
 +
Where:
 +
- service_type is a string identifying a service, one of allowed services. In Havana the next list of services will be allowed: LOADBALANCER, FIREWALL, VPN, ROUTER.<br/>
 +
- name - user-facing representation of the provider<br/>
 +
- driver - driver identification. That could be a classpath, or some other identification (stevedore usage is considered)<br/>
 +
- default option. If specified, the provider becomes default for given service type.<br/>
 +
<br>
 +
There could be only one default provider for a given service type, driver identification should be unique across all providers.<br/>
 +
Name and service type must also be unique.
 +
<br/><br/>
 +
Example of quantum.conf section:
 +
[service_providers]
 +
service_provider=LOADBALANCER:reference:quantum.services.loadbalancer.plugin_drivers.haproxy.HaproxyOnHost:default
 +
service_provider=LOADBALANCER:net_scaler:quantum.services.loadbalancer.plugin_drivers.netscaler.NetScDriver
 +
service_provider=VPN:strong_swan:quantum.services.vpn.drivers.StrongSwan
 +
<br/>
 +
In order to remove provider from configuration, admin should either delete all resources created with that provider, or perform a special step to undeploy all resources associated with a provider being removed. That needs to be done before neutron server is restarted.
  
 
==== '''Workflow for a user''' ====
 
==== '''Workflow for a user''' ====
In order to request specific vendor and insertion model, user does the following steps:<br />
+
In order to request specific vendor (provider), user does the following steps:<br />
1. Chooses ServiceGroup from list of available groups.<br />
+
1. Chooses Service Provider Name from list of available service providers.<br />
2. Chooses ServiceTypeProvider from the list of chosen ServiceGroup.<br />
+
neutron service-provider-list<br/>
3. Creates resource with that TypeProvider (effectively, the driver)<br />
+
| Service Type      |        Name      | Default  |
 
+
-----------------------------------------------------
In other words, user chooses how service will be inserted and then chooses vendor that supports such insertion model.
+
| LOADBALANCER      |    Haproxy      |  True    |
 +
| LOADBALANCER      |    Netscaler    |  False  |
 +
<br/>
 +
2. Creates resource with that Provider Name (effectively, the driver). LBaaS example:<br />
 +
lb-pool-create '''--provider Netscaler''' --lb-method ROUND_ROBIN ... ...<br />
 +
After the pool has been created with Netscaler provider, all subsequent commands associating other objects to this pool will go through Netscaler plugin driver.<br />
 +
In case provider is not specified, the default one is used for that service type, in given example - Haproxy plugin driver. (only single default could be specified for given service type). <br />
 +
There could be no default provider for certain service type. In that case exception will be raised.
 +
Please note that this amendment to lbaas CLI/REST API is out of scope of service type framework patch.
 
<br /><br />
 
<br /><br />
 
==== '''REST API / DB changes''' ====
 
In order to accommodate changes in the workflow the following changes must be done to REST API and DB:<br />
 
ServiceTypeProvider field should be added to the root object of corresponding resource model.<br />
 
Example: in LBaaS the root object is a pool, so its model gets ServiceTypeProvider field.<br />
 
REST API call that creates a pool thus gets additional parameter ServiceTypeProvider.<br />
 
<br />
 
  
 
==== '''REST call dispatching''' ====
 
==== '''REST call dispatching''' ====
Currently I'm considering the model "one service plugin - multiple drivers".<br />
+
Currently considering model is "one service plugin - multiple drivers".<br />
There are two major options of how requests could be dispatched to corresponding driver:<br />
 
1) Specify ServiceTypeProvider in each request.
 
Cons: unnecessary parameter for the most of the calls, requires additional validation via existing DB objects <br />
 
(you can't link objects with one ServiceTypeProvider with objects of another ServiceTypeProvider)
 
Pros: ?
 
 
 
2) Specify ServiceTypeProvider only for "create root object" (create_pool for LBaaS),<br />
 
Any CRUD call for object related to the existing root object will be dispatched to the same driver as a root object.
 
Therefore dispatching involves fetching root object from the DB.
 
  
Pros: logical consistency, clear REST calls<br />
+
For REST call dispatching the following approach will be used:<br />
Cons: db query done just for dispatching. (I doubt we can do better)
+
Specify ServiceProvider name only for "create root object" (create_pool for LBaaS), that will add provider resource association.<br />
 +
Any CRUD call for object related to the existing root object (pool) will be dispatched to the same driver as a root object.
 +
Therefore dispatching involves fetching root object from the DB on each operation.
  
 
Example (LBaaS):<br />
 
Example (LBaaS):<br />
 
[[File:Call dispatching workflow.png]]
 
[[File:Call dispatching workflow.png]]

Latest revision as of 14:01, 14 July 2013

The intent of this document is to clarify and organize notions around so-called "Service Types". It describes entities and corresponding workflow.

Service Type Framework serves the main purpose:
Allow tenant to specify vendor (or service provider) for the requested service
Service Provider is main entity of Service Type Framework.
As an addition, another benefits are possible to add on top of service providers like service offerings, insertion modes, etc.


Notions of Service Type Framework


1. ServiceType
type of the service: loadbalancer, firewall, vpn, etc.
This is more or less static set of string values that are currently residing in neutron/plugins/common/constants.py
These strings are used as keys in plugins dictionary when dispatching REST API calls.

2. ServiceProvider
This is a pointer to particular driver that implements some service.
Currently it has form ServiceType:Name:Driver[:default] where Driver is class identification that are loaded by neutron.
Name is human-readable form which is used to represent provider for a user.
Name should be unique for given ServiceType, but may be not unique across all providers.
A set of service type providers should be used by service plugin to load plugin drivers. ServiceProviders are specified in configuration file in a form of string list (multiline option).

3. ProviderResourceAssociation
Entity that connects particular resource to a provider.
Association consist of unique resource_id and provider_name.
It's assumed that resource_id (uuid type) is unique in the whole database, so additional service_type field is not needed.

Integration with services

In order to decouple service provider configuration from logical resource configuration the ProviderResourceAssociation is used.

Special handling required for the case when admin is going to remove service provider from the configuration or a tenant decides to change provider for existing resource. In that cases lbaas should undeploy the resource using one provider and deploy it using the other, or just undeploy all resource in case provider is going to be removed.
Additional API call for each kind of service is required. This is subject for additional service-specific feature.

Workflow for an admin

Admin usually would add service providers to the quantum.conf file.
That should make service plugins to load specified drivers and allow tenants to list service providers.
Those provider options should be specified in multiline form, one per provider in format:

<service_type>:<name>:<driver>[:default] 

Where: - service_type is a string identifying a service, one of allowed services. In Havana the next list of services will be allowed: LOADBALANCER, FIREWALL, VPN, ROUTER.
- name - user-facing representation of the provider
- driver - driver identification. That could be a classpath, or some other identification (stevedore usage is considered)
- default option. If specified, the provider becomes default for given service type.

There could be only one default provider for a given service type, driver identification should be unique across all providers.
Name and service type must also be unique.

Example of quantum.conf section:

[service_providers] 
service_provider=LOADBALANCER:reference:quantum.services.loadbalancer.plugin_drivers.haproxy.HaproxyOnHost:default
service_provider=LOADBALANCER:net_scaler:quantum.services.loadbalancer.plugin_drivers.netscaler.NetScDriver
service_provider=VPN:strong_swan:quantum.services.vpn.drivers.StrongSwan


In order to remove provider from configuration, admin should either delete all resources created with that provider, or perform a special step to undeploy all resources associated with a provider being removed. That needs to be done before neutron server is restarted.

Workflow for a user

In order to request specific vendor (provider), user does the following steps:
1. Chooses Service Provider Name from list of available service providers.

neutron service-provider-list
| Service Type | Name | Default | ----------------------------------------------------- | LOADBALANCER | Haproxy | True | | LOADBALANCER | Netscaler | False |


2. Creates resource with that Provider Name (effectively, the driver). LBaaS example:

lb-pool-create --provider Netscaler --lb-method ROUND_ROBIN ... ...

After the pool has been created with Netscaler provider, all subsequent commands associating other objects to this pool will go through Netscaler plugin driver.
In case provider is not specified, the default one is used for that service type, in given example - Haproxy plugin driver. (only single default could be specified for given service type).
There could be no default provider for certain service type. In that case exception will be raised. Please note that this amendment to lbaas CLI/REST API is out of scope of service type framework patch.

REST call dispatching

Currently considering model is "one service plugin - multiple drivers".

For REST call dispatching the following approach will be used:
Specify ServiceProvider name only for "create root object" (create_pool for LBaaS), that will add provider resource association.
Any CRUD call for object related to the existing root object (pool) will be dispatched to the same driver as a root object. Therefore dispatching involves fetching root object from the DB on each operation.

Example (LBaaS):
Call dispatching workflow.png