Jump to: navigation, search

Difference between revisions of "Neutron/EmbraneNeutronPlugin"

m (Implementation)
Line 62: Line 62:
 
'''Plugin Inheritance'''<br />
 
'''Plugin Inheritance'''<br />
  
In 'neutron/plugins/embrane/plugin.py' (plugin main module) the main class 'EmbranePlugin' is created at runtime starting from class '__EmbranePlugin'. This is done looking at the configuration file, assuring that the specified L2 plugin is a valid one, and creating a new class which attribute and methods (in general, the full dict) coincides with '__EmbranePlugin', but also inherits from the configured L2 plugin, from which 'EmbranePlugin' will get all the implemented methods overriding everything related with L3 connectivity.
+
In 'neutron/plugins/embrane/plugins/*' (where the actual plugins resides) each plugin class (i.e. EmbraneOvsPlugin) is created using the base Embrane plugin (neutron/plugins/embrane/plugin.py.EmbranePlugin) and the specific L2 plugin as bases. This will ensure, provided that everything is done correctly, that the L2 networks will be provided by an existing L2 plugin, while L3 connectivity will be managed by Embrane's plugin. More details on how to create a specific Embrane plugin are provided below.
Also, all the necessary inheritances are set unless already present on the base L2 plugin.
 
  
 
'''Plugin-in-Plugin'''<br />
 
'''Plugin-in-Plugin'''<br />
  
In order to get all this to work, the 2 plugins (Embrane's and L2) need to share some information about the actual network implementation. At the present state, only plugins which implements network isolation through VLANs can be used together with Embrane's plugin. Support for different L2 isolation will be added in the future.
+
In order to get all this to work, the 2 plugins (Embrane's and L2) need to share some information about the actual network implementation. At the present state, only plugins which implement network isolation through VLANs can be used together with Embrane's plugin. Support for different L2 isolation will be added in the future.
This "information sharing" is implemented through a "Plugin inside the Plugin", which means that for each L2 plugin that is to be supported, it's mandatory to create a new package inside 'neutron/plugins/embrane/l2base/' and a class that inherits from 'neutron/plugins/embrane/l2base/support_base.py'.
+
This "information sharing" is implemented through a plugin "inside the plugin", which means that for each L2 plugin that is to be supported, it's mandatory to create a new package inside 'neutron/plugins/embrane/l2base/' and a class that inherits from 'neutron/plugins/embrane/l2base/support_base.py'.
 
This abstract class only defines one simple method, which shall be implemented by the support class in order to fulfill the contract.
 
This abstract class only defines one simple method, which shall be implemented by the support class in order to fulfill the contract.
 +
 +
'''-Instructions to build a new Embrane plugin from a different base-'''
 +
 +
see examples from:
 +
 +
<pre><nowiki>
 +
neutron.plugins.embrane.plugins.embrane_fake_plugin.EmbraneFakePlugin
 +
neutron.plugins.embrane.plugins.embrane_ovs_plugin.EmbraneOvsPlugin
 +
</nowiki></pre>
 +
 +
To build a new L2 support for the Embrane's Neutron plugin, you must first implement the specific l2base.<br />
 +
 +
Create a new package under:
 +
 +
<pre><nowiki>
 +
neutron.plugins.embrane.l2base
 +
</nowiki></pre>
 +
 +
And name it with the specific plugin technology. Create a python module, and a class which extends support_base.SupportBase, implementing all its abstract methods.
  
 
<pre><nowiki>
 
<pre><nowiki>
Line 76: Line 94:
 
</nowiki></pre>
 
</nowiki></pre>
  
An example of support class can be found in 'neutron/plugins/embrane/l2base/openvswitch/openvswitch_support.py'.
+
An example of support class can be found in 'neutron/plugins/embrane/l2base/openvswitch/openvswitch_support.py'.<br />
 +
 
 +
Once the contract is fulfilled (see examples and comments in the code for more info) create a new module under:
 +
 
 +
<pre><nowiki>
 +
neutron.plugins.embrane.plugins
 +
</nowiki></pre>
 +
 
 +
Named referencing the specific plugin technology (see existing examples). Inside the module define a class built as follows:
 +
of the plugin following the example below:
 +
 
 +
<pre><nowiki>
 +
class EmbraneNewPlugin(base.EmbranePlugin, l2.NewL2Plugin):
 +
    _plugin_support = support.NewPluginSupport
 +
    def __init__(self):
 +
        '''First run plugin specific initialization, then Embrane's.'''
 +
        self.supported_extension_aliases += ["extraroute", "router"] #IF NEEDED
 +
        l2.NewL2Plugin.__init__(self)
 +
        self._run_embrane_config()
 +
</nowiki></pre>
 +
 
 +
NOTE: The base order is very important!!! EmbranePlugin shall always be the first base of the built plugin, so the L3 requests can be correctly resolved (MRO)<br />
 +
NOTE2: The plugin needs certain bases and extensions:<br />
 +
*REQUIRED_EXTENSIONS = ["extraroute", "router"]
 +
*REQUIRED_BASES = (ExtraRoute_db_mixin,)
 +
Add them if needed (i.e. the L2 plugin doesn't natively support them).
  
 
=== Asynchronous Calls===
 
=== Asynchronous Calls===
Line 106: Line 149:
  
 
The configuration file is stored in 'etc/neutron/plugins/embrane/heleos_conf.ini', this section explains the meaning of each field (example are provided in the configuration class itself).
 
The configuration file is stored in 'etc/neutron/plugins/embrane/heleos_conf.ini', this section explains the meaning of each field (example are provided in the configuration class itself).
*'''l2_plugin''': path to one of the existing L2 plugins which will work together with the Embrane's plugin;
 
*'''l2_support''': path to one of the existing L2 support class (see the section above);
 
 
*'''esm_mgmt''': management address of the ESM, the Embrane module that is installed separately and which will actually provision the routers inside the cloud environent;
 
*'''esm_mgmt''': management address of the ESM, the Embrane module that is installed separately and which will actually provision the routers inside the cloud environent;
 
*'''admin_username''': admin username for authenticating against the ESM;
 
*'''admin_username''': admin username for authenticating against the ESM;
Line 113: Line 154:
 
*'''router_image''': ID to the router image stored inside the ESM, which will be used to create the routers;
 
*'''router_image''': ID to the router image stored inside the ESM, which will be used to create the routers;
 
*'''*_id''': a series of resources product specific that can be specified inside the plugin, or alternatively, from the product itself.
 
*'''*_id''': a series of resources product specific that can be specified inside the plugin, or alternatively, from the product itself.
 +
 +
 +
etc/neutron/neutron.conf example:<br />
 +
*'''core_plugin =''' neutron.plugins.embrane.plugins.embrane_ovs_plugin.EmbraneOvsPlugin

Revision as of 20:32, 30 August 2013

Embrane Neutron Plugin

Scope

The present blueprint aims at the implementation of a Neutron plugins which allows users to interface Neutron with Embrane's heleos platform.

Use Cases

Cloud service providers who choose to adopt OpenStack and Neutron for their cloud orchestration, will also be able to use Embrane's heleos platform with the API and workflows set they are comfortable with.

Using the Embrane's plugin, the users can achieve any level of L2 isolation using the existing plugins (when supported), while leveraging L3 connectivity through Embrane's provisioning system, which can rapidly provide per tenant "core routers" in a pool of dedicated/shared physical hosts. These routers are configurable through both Neutron itself or their own REST APIs.

Network Overview

[TBD]

Implementation

This session discusses the plugin implementation, with special focus to the plugin specific features and configurations.

The plugin file list is the following:

neutron/plugins/embrane/EmbraneInit.py
neutron/plugins/embrane/__init__.py
neutron/plugins/embrane/agent/__init__.py	
neutron/plugins/embrane/agent/dispatcher.py	
neutron/plugins/embrane/agent/operations/__init__.py	
neutron/plugins/embrane/agent/operations/routerOperations.py	
neutron/plugins/embrane/l2base/__init__.py		
neutron/plugins/embrane/l2base/openvswitch/__init__.py
neutron/plugins/embrane/l2base/openvswitch/openvswitch_support.py
neutron/plugins/embrane/l2base/support_base.py
neutron/plugins/embrane/l2base/support_exceptions.py		
neutron/plugins/embrane/plugin.py

Additionally, more packages are defined:

neutron/plugins/embrane/api/*	
neutron/plugins/embrane/embranerest/*	

The files inside these packages are backend-specific, and represent the set of tools used to interact with the Embrane's platform. They are a dependency for the plugin and may be distributed separately at first.

Supported feature

The plugin supports the following features:


Using existing plugins for L2 connectivity

The Embrane Neutron Plugin main goal is of course to interface OpenStack (specifically Neutron) with heleos, which provides L3-7 network services for cloud environments. For this reason, the Embrane Plugin lends the leveraging of L2 connectivity to an existing Plugin chosen at configuration time. The Embrane Plugin and the L2 plugin share information about the network implementation, which will be used to implement L3. So any time a request is sent to Neutron, it will be directed to the Embrane Plugin if is part of the API set showed in the previous section, to the L2 plugin otherwise.

To achieve this, there are 2 main techniques that have been used:

Plugin Inheritance

In 'neutron/plugins/embrane/plugins/*' (where the actual plugins resides) each plugin class (i.e. EmbraneOvsPlugin) is created using the base Embrane plugin (neutron/plugins/embrane/plugin.py.EmbranePlugin) and the specific L2 plugin as bases. This will ensure, provided that everything is done correctly, that the L2 networks will be provided by an existing L2 plugin, while L3 connectivity will be managed by Embrane's plugin. More details on how to create a specific Embrane plugin are provided below.

Plugin-in-Plugin

In order to get all this to work, the 2 plugins (Embrane's and L2) need to share some information about the actual network implementation. At the present state, only plugins which implement network isolation through VLANs can be used together with Embrane's plugin. Support for different L2 isolation will be added in the future. This "information sharing" is implemented through a plugin "inside the plugin", which means that for each L2 plugin that is to be supported, it's mandatory to create a new package inside 'neutron/plugins/embrane/l2base/' and a class that inherits from 'neutron/plugins/embrane/l2base/support_base.py'. This abstract class only defines one simple method, which shall be implemented by the support class in order to fulfill the contract.

-Instructions to build a new Embrane plugin from a different base-

see examples from:

neutron.plugins.embrane.plugins.embrane_fake_plugin.EmbraneFakePlugin
neutron.plugins.embrane.plugins.embrane_ovs_plugin.EmbraneOvsPlugin

To build a new L2 support for the Embrane's Neutron plugin, you must first implement the specific l2base.

Create a new package under:

neutron.plugins.embrane.l2base

And name it with the specific plugin technology. Create a python module, and a class which extends support_base.SupportBase, implementing all its abstract methods.

@abstractmethod
def retrieve_utif_info(self, context, neutron_port=None, network=None):

An example of support class can be found in 'neutron/plugins/embrane/l2base/openvswitch/openvswitch_support.py'.

Once the contract is fulfilled (see examples and comments in the code for more info) create a new module under:

neutron.plugins.embrane.plugins

Named referencing the specific plugin technology (see existing examples). Inside the module define a class built as follows: of the plugin following the example below:

class EmbraneNewPlugin(base.EmbranePlugin, l2.NewL2Plugin):
    _plugin_support = support.NewPluginSupport
    def __init__(self):
        '''First run plugin specific initialization, then Embrane's.'''
        self.supported_extension_aliases += ["extraroute", "router"] #IF NEEDED
        l2.NewL2Plugin.__init__(self)
        self._run_embrane_config()

NOTE: The base order is very important!!! EmbranePlugin shall always be the first base of the built plugin, so the L3 requests can be correctly resolved (MRO)
NOTE2: The plugin needs certain bases and extensions:

  • REQUIRED_EXTENSIONS = ["extraroute", "router"]
  • REQUIRED_BASES = (ExtraRoute_db_mixin,)

Add them if needed (i.e. the L2 plugin doesn't natively support them).

Asynchronous Calls

To avoid too much wait time on long operations, the calls to the Embrane Plugin will be executed asynchronously and by a different thread "per Router". This means that each request will be sent to the dispatcher ('neutron/plugins/embrane/agent/dispatcher.py') which will serve each Router using a different thread, in which all the operations will be queued and executed sequentially, while the available database information on the specific resource will be returned to the user (Nova style). Moreover, Router state attribute is used to tell the user when a Router is busy with an operation:

Table 1. Status Values

Name
ACTIVE
PENDING_CREATE
PENDING_UPDATE
PENDING_DELETE
INACTIVE
ERROR


So when the model is changed (via POST, PUT or DELETE for example) the call may return before the actual operation is executed on the virtual system, putting the router in a 'PENDING_*' state. Subsequent GETs shall always reflect the current status of the virtual appliance itself. When a Router is in a given state, only a subset of operations can be executed on it.

Configuration

The configuration file is stored in 'etc/neutron/plugins/embrane/heleos_conf.ini', this section explains the meaning of each field (example are provided in the configuration class itself).

  • esm_mgmt: management address of the ESM, the Embrane module that is installed separately and which will actually provision the routers inside the cloud environent;
  • admin_username: admin username for authenticating against the ESM;
  • admin_password: admin password for authenticating against the ESM;
  • router_image: ID to the router image stored inside the ESM, which will be used to create the routers;
  • *_id: a series of resources product specific that can be specified inside the plugin, or alternatively, from the product itself.


etc/neutron/neutron.conf example:

  • core_plugin = neutron.plugins.embrane.plugins.embrane_ovs_plugin.EmbraneOvsPlugin