doc: Document for ryu.lib.ovs
Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
bd384997ac
commit
09d2811569
@ -15,3 +15,4 @@ Ryu provides some useful library for your network applications.
|
|||||||
library_bgp_speaker_ref.rst
|
library_bgp_speaker_ref.rst
|
||||||
library_mrt.rst
|
library_mrt.rst
|
||||||
library_ovsdb_manager.rst
|
library_ovsdb_manager.rst
|
||||||
|
library_ovsdb.rst
|
||||||
|
76
doc/source/library_ovsdb.rst
Normal file
76
doc/source/library_ovsdb.rst
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
*************
|
||||||
|
OVSDB library
|
||||||
|
*************
|
||||||
|
|
||||||
|
Path: ``ryu.lib.ovs``
|
||||||
|
|
||||||
|
Similar to the :doc:`library_ovsdb_manager`, this library enables your
|
||||||
|
application to speak the OVSDB protocol (RFC7047_), but differ from the
|
||||||
|
:doc:`library_ovsdb_manager`, this library will initiate connections from
|
||||||
|
controller side as ovs-vsctl_ command does.
|
||||||
|
Please make sure that your devices are listening on either the Unix domain
|
||||||
|
socket or TCP/SSL port before calling the APIs of this library.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Show current configuration
|
||||||
|
$ ovs-vsctl get-manager
|
||||||
|
|
||||||
|
# Set TCP listen address
|
||||||
|
$ ovs-vsctl set-manager "ptcp:6640"
|
||||||
|
|
||||||
|
See manpage of ovs-vsctl_ command for more details.
|
||||||
|
|
||||||
|
.. _RFC7047: https://tools.ietf.org/html/rfc7047
|
||||||
|
.. _ovs-vsctl: http://openvswitch.org/support/dist-docs/ovs-vsctl.8.txt
|
||||||
|
|
||||||
|
Basic Usage
|
||||||
|
===========
|
||||||
|
|
||||||
|
1. Instantiate :py:mod:`ryu.lib.ovs.vsctl.VSCtl`.
|
||||||
|
|
||||||
|
2. Construct commands with :py:mod:`ryu.lib.ovs.vsctl.VSCtlCommand`.
|
||||||
|
The syntax is almost the same as ovs-vsctl_ command.
|
||||||
|
|
||||||
|
3. Execute commands via :py:mod:`ryu.lib.ovs.vsctl.VSCtl.run_command`.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from ryu.lib.ovs import vsctl
|
||||||
|
|
||||||
|
OVSDB_ADDR = 'tcp:127.0.0.1:6640'
|
||||||
|
ovs_vsctl = vsctl.VSCtl(OVSDB_ADDR)
|
||||||
|
|
||||||
|
# Equivalent to
|
||||||
|
# $ ovs-vsctl show
|
||||||
|
command = vsctl.VSCtlCommand('show')
|
||||||
|
ovs_vsctl.run_command([command])
|
||||||
|
print(command)
|
||||||
|
# >>> VSCtlCommand(args=[],command='show',options=[],result='830d781f-c3c8-4b4f-837e-106e1b33d058\n ovs_version: "2.8.90"\n')
|
||||||
|
|
||||||
|
# Equivalent to
|
||||||
|
# $ ovs-vsctl list Port s1-eth1
|
||||||
|
command = vsctl.VSCtlCommand('list', ('Port', 's1-eth1'))
|
||||||
|
ovs_vsctl.run_command([command])
|
||||||
|
print(command)
|
||||||
|
# >>> VSCtlCommand(args=('Port', 's1-eth1'),command='list',options=[],result=[<ovs.db.idl.Row object at 0x7f525fb682e8>])
|
||||||
|
print(command.result[0].name)
|
||||||
|
# >>> s1-eth1
|
||||||
|
|
||||||
|
API Reference
|
||||||
|
=============
|
||||||
|
|
||||||
|
ryu.lib.ovs.vsctl
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. automodule:: ryu.lib.ovs.vsctl
|
||||||
|
:members:
|
||||||
|
|
||||||
|
ryu.lib.ovs.bridge
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. automodule:: ryu.lib.ovs.bridge
|
||||||
|
:members:
|
@ -15,7 +15,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
slimmed down version of OVSBridge in quantum agent
|
Wrapper utility library of :py:mod:`ryu.lib.ovs.vsctl`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
@ -92,6 +92,26 @@ class TunnelPort(object):
|
|||||||
|
|
||||||
|
|
||||||
class OVSBridge(object):
|
class OVSBridge(object):
|
||||||
|
"""
|
||||||
|
Class to provide wrapper utilities of :py:mod:`ryu.lib.ovs.vsctl.VSCtl`
|
||||||
|
|
||||||
|
``CONF`` is a instance of ``oslo_config.cfg.ConfigOpts``.
|
||||||
|
Mostly ``self.CONF`` is sufficient to instantiate this class from your Ryu
|
||||||
|
application.
|
||||||
|
|
||||||
|
``datapath_id`` specifies Datapath ID of the target OVS instance.
|
||||||
|
|
||||||
|
``ovsdb_addr`` specifies the address of the OVS instance.
|
||||||
|
Automatically validated when you call ``init()`` method.
|
||||||
|
Refer to :py:mod:`ryu.lib.ovs.vsctl.valid_ovsdb_addr` for the format of
|
||||||
|
this address.
|
||||||
|
|
||||||
|
if ``timeout`` is omitted, ``CONF.ovsdb_timeout`` will be used as the
|
||||||
|
default value.
|
||||||
|
|
||||||
|
Usage of ``timeout`` and ``exception`` is the same with ``timeout_sec``
|
||||||
|
and ``exception`` of :py:mod:`ryu.lib.ovs.vsctl.VSCtl.run_command`.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, CONF, datapath_id, ovsdb_addr, timeout=None,
|
def __init__(self, CONF, datapath_id, ovsdb_addr, timeout=None,
|
||||||
exception=None):
|
exception=None):
|
||||||
@ -105,9 +125,25 @@ class OVSBridge(object):
|
|||||||
self.br_name = None
|
self.br_name = None
|
||||||
|
|
||||||
def run_command(self, commands):
|
def run_command(self, commands):
|
||||||
|
"""
|
||||||
|
Executes the given commands and sends OVSDB messages.
|
||||||
|
|
||||||
|
``commands`` must be a list of
|
||||||
|
:py:mod:`ryu.lib.ovs.vsctl.VSCtlCommand`.
|
||||||
|
|
||||||
|
The given ``timeout`` and ``exception`` when instantiation will be used
|
||||||
|
to call :py:mod:`ryu.lib.ovs.vsctl.VSCtl.run_command`.
|
||||||
|
"""
|
||||||
self.vsctl.run_command(commands, self.timeout, self.exception)
|
self.vsctl.run_command(commands, self.timeout, self.exception)
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
|
"""
|
||||||
|
Validates the given ``ovsdb_addr`` and connects to OVS instance.
|
||||||
|
|
||||||
|
If failed to connect to OVS instance or the given ``datapath_id`` does
|
||||||
|
not match with the Datapath ID of the connected OVS instance, raises
|
||||||
|
:py:mod:`ryu.lib.ovs.bridge.OVSBridgeNotFound` exception.
|
||||||
|
"""
|
||||||
if not valid_ovsdb_addr(self.ovsdb_addr):
|
if not valid_ovsdb_addr(self.ovsdb_addr):
|
||||||
raise ValueError('Invalid OVSDB address: %s' % self.ovsdb_addr)
|
raise ValueError('Invalid OVSDB address: %s' % self.ovsdb_addr)
|
||||||
if self.br_name is None:
|
if self.br_name is None:
|
||||||
@ -126,16 +162,37 @@ class OVSBridge(object):
|
|||||||
return command.result[0].name
|
return command.result[0].name
|
||||||
|
|
||||||
def get_controller(self):
|
def get_controller(self):
|
||||||
|
"""
|
||||||
|
Gets the configured OpenFlow controller address.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl get-controller <bridge>
|
||||||
|
"""
|
||||||
command = ovs_vsctl.VSCtlCommand('get-controller', [self.br_name])
|
command = ovs_vsctl.VSCtlCommand('get-controller', [self.br_name])
|
||||||
self.run_command([command])
|
self.run_command([command])
|
||||||
return command.result[0]
|
return command.result[0]
|
||||||
|
|
||||||
def set_controller(self, controllers):
|
def set_controller(self, controllers):
|
||||||
|
"""
|
||||||
|
Sets the OpenFlow controller address.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl set-controller <bridge> <target>...
|
||||||
|
"""
|
||||||
command = ovs_vsctl.VSCtlCommand('set-controller', [self.br_name])
|
command = ovs_vsctl.VSCtlCommand('set-controller', [self.br_name])
|
||||||
command.args.extend(controllers)
|
command.args.extend(controllers)
|
||||||
self.run_command([command])
|
self.run_command([command])
|
||||||
|
|
||||||
def del_controller(self):
|
def del_controller(self):
|
||||||
|
"""
|
||||||
|
Deletes the configured OpenFlow controller address.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl del-controller <bridge>
|
||||||
|
"""
|
||||||
command = ovs_vsctl.VSCtlCommand('del-controller', [self.br_name])
|
command = ovs_vsctl.VSCtlCommand('del-controller', [self.br_name])
|
||||||
self.run_command([command])
|
self.run_command([command])
|
||||||
|
|
||||||
@ -245,30 +302,72 @@ class OVSBridge(object):
|
|||||||
self.run_command([command])
|
self.run_command([command])
|
||||||
|
|
||||||
def db_get_val(self, table, record, column):
|
def db_get_val(self, table, record, column):
|
||||||
|
"""
|
||||||
|
Gets values of 'column' in 'record' in 'table'.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl get TBL REC COL
|
||||||
|
"""
|
||||||
command = ovs_vsctl.VSCtlCommand('get', (table, record, column))
|
command = ovs_vsctl.VSCtlCommand('get', (table, record, column))
|
||||||
self.run_command([command])
|
self.run_command([command])
|
||||||
assert len(command.result) == 1
|
assert len(command.result) == 1
|
||||||
return command.result[0]
|
return command.result[0]
|
||||||
|
|
||||||
def db_get_map(self, table, record, column):
|
def db_get_map(self, table, record, column):
|
||||||
|
"""
|
||||||
|
Gets dict type value of 'column' in 'record' in 'table'.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl get TBL REC COL
|
||||||
|
"""
|
||||||
val = self.db_get_val(table, record, column)
|
val = self.db_get_val(table, record, column)
|
||||||
assert isinstance(val, dict)
|
assert isinstance(val, dict)
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def get_datapath_id(self):
|
def get_datapath_id(self):
|
||||||
|
"""
|
||||||
|
Gets Datapath ID of OVS instance.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl get Bridge <bridge> datapath_id
|
||||||
|
"""
|
||||||
return self.db_get_val('Bridge', self.br_name, 'datapath_id')
|
return self.db_get_val('Bridge', self.br_name, 'datapath_id')
|
||||||
|
|
||||||
def delete_port(self, port_name):
|
def delete_port(self, port_name):
|
||||||
|
"""
|
||||||
|
Deletes a port on the OVS instance.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl --if-exists del-port <bridge> <port>
|
||||||
|
"""
|
||||||
command = ovs_vsctl.VSCtlCommand(
|
command = ovs_vsctl.VSCtlCommand(
|
||||||
'del-port', (self.br_name, port_name), '--if-exists')
|
'del-port', (self.br_name, port_name), '--if-exists')
|
||||||
self.run_command([command])
|
self.run_command([command])
|
||||||
|
|
||||||
def get_ofport(self, port_name):
|
def get_ofport(self, port_name):
|
||||||
|
"""
|
||||||
|
Gets the OpenFlow port number.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl get Interface <port> ofport
|
||||||
|
"""
|
||||||
ofport_list = self.db_get_val('Interface', port_name, 'ofport')
|
ofport_list = self.db_get_val('Interface', port_name, 'ofport')
|
||||||
assert len(ofport_list) == 1
|
assert len(ofport_list) == 1
|
||||||
return int(ofport_list[0])
|
return int(ofport_list[0])
|
||||||
|
|
||||||
def get_port_name_list(self):
|
def get_port_name_list(self):
|
||||||
|
"""
|
||||||
|
Gets a list of all ports on OVS instance.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl list-ports <bridge>
|
||||||
|
"""
|
||||||
command = ovs_vsctl.VSCtlCommand('list-ports', (self.br_name, ))
|
command = ovs_vsctl.VSCtlCommand('list-ports', (self.br_name, ))
|
||||||
self.run_command([command])
|
self.run_command([command])
|
||||||
return command.result
|
return command.result
|
||||||
@ -297,6 +396,16 @@ class OVSBridge(object):
|
|||||||
|
|
||||||
def add_tunnel_port(self, name, tunnel_type, remote_ip,
|
def add_tunnel_port(self, name, tunnel_type, remote_ip,
|
||||||
local_ip=None, key=None, ofport=None):
|
local_ip=None, key=None, ofport=None):
|
||||||
|
"""
|
||||||
|
Creates a tunnel port.
|
||||||
|
|
||||||
|
:param name: Port name to be created
|
||||||
|
:param tunnel_type: Type of tunnel (gre or vxlan)
|
||||||
|
:param remote_ip: Remote IP address of tunnel
|
||||||
|
:param local_ip: Local IP address of tunnel
|
||||||
|
:param key: Key of GRE or VNI of VxLAN
|
||||||
|
:param ofport: Requested OpenFlow port number
|
||||||
|
"""
|
||||||
options = 'remote_ip=%(remote_ip)s' % locals()
|
options = 'remote_ip=%(remote_ip)s' % locals()
|
||||||
if key:
|
if key:
|
||||||
options += ',key=%(key)s' % locals()
|
options += ',key=%(key)s' % locals()
|
||||||
@ -314,15 +423,32 @@ class OVSBridge(object):
|
|||||||
|
|
||||||
def add_gre_port(self, name, remote_ip,
|
def add_gre_port(self, name, remote_ip,
|
||||||
local_ip=None, key=None, ofport=None):
|
local_ip=None, key=None, ofport=None):
|
||||||
|
"""
|
||||||
|
Creates a GRE tunnel port.
|
||||||
|
|
||||||
|
See the description of ``add_tunnel_port()``.
|
||||||
|
"""
|
||||||
self.add_tunnel_port(name, 'gre', remote_ip,
|
self.add_tunnel_port(name, 'gre', remote_ip,
|
||||||
local_ip=local_ip, key=key, ofport=ofport)
|
local_ip=local_ip, key=key, ofport=ofport)
|
||||||
|
|
||||||
def add_vxlan_port(self, name, remote_ip,
|
def add_vxlan_port(self, name, remote_ip,
|
||||||
local_ip=None, key=None, ofport=None):
|
local_ip=None, key=None, ofport=None):
|
||||||
|
"""
|
||||||
|
Creates a VxLAN tunnel port.
|
||||||
|
|
||||||
|
See the description of ``add_tunnel_port()``.
|
||||||
|
"""
|
||||||
self.add_tunnel_port(name, 'vxlan', remote_ip,
|
self.add_tunnel_port(name, 'vxlan', remote_ip,
|
||||||
local_ip=local_ip, key=key, ofport=ofport)
|
local_ip=local_ip, key=key, ofport=ofport)
|
||||||
|
|
||||||
def del_port(self, port_name):
|
def del_port(self, port_name):
|
||||||
|
"""
|
||||||
|
Deletes a port on OVS instance.
|
||||||
|
|
||||||
|
This method is corresponding to the following ovs-vsctl command::
|
||||||
|
|
||||||
|
$ ovs-vsctl del-port <bridge> <port>
|
||||||
|
"""
|
||||||
command = ovs_vsctl.VSCtlCommand('del-port', (self.br_name, port_name))
|
command = ovs_vsctl.VSCtlCommand('del-port', (self.br_name, port_name))
|
||||||
self.run_command([command])
|
self.run_command([command])
|
||||||
|
|
||||||
@ -396,6 +522,9 @@ class OVSBridge(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def set_qos(self, port_name, type='linux-htb', max_rate=None, queues=None):
|
def set_qos(self, port_name, type='linux-htb', max_rate=None, queues=None):
|
||||||
|
"""
|
||||||
|
Sets a Qos rule and creates Queues on the given port.
|
||||||
|
"""
|
||||||
queues = queues if queues else []
|
queues = queues if queues else []
|
||||||
command_qos = ovs_vsctl.VSCtlCommand(
|
command_qos = ovs_vsctl.VSCtlCommand(
|
||||||
'set-qos',
|
'set-qos',
|
||||||
@ -409,6 +538,9 @@ class OVSBridge(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def del_qos(self, port_name):
|
def del_qos(self, port_name):
|
||||||
|
"""
|
||||||
|
Deletes the Qos rule on the given port.
|
||||||
|
"""
|
||||||
command = ovs_vsctl.VSCtlCommand(
|
command = ovs_vsctl.VSCtlCommand(
|
||||||
'del-qos',
|
'del-qos',
|
||||||
[port_name])
|
[port_name])
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""
|
||||||
|
``ovs-vsctl`` command like library to speak OVSDB protocol
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
@ -53,9 +56,9 @@ def valid_ovsdb_addr(addr):
|
|||||||
|
|
||||||
The valid formats are:
|
The valid formats are:
|
||||||
|
|
||||||
- unix:file
|
- ``unix:file``
|
||||||
- tcp:ip:port
|
- ``tcp:ip:port``
|
||||||
- ssl:ip:port
|
- ``ssl:ip:port``
|
||||||
|
|
||||||
If ip is IPv6 address, wrap ip with brackets (e.g., ssl:[::1]:6640).
|
If ip is IPv6 address, wrap ip with brackets (e.g., ssl:[::1]:6640).
|
||||||
|
|
||||||
@ -959,6 +962,34 @@ class _VSCtlTable(object):
|
|||||||
|
|
||||||
|
|
||||||
class VSCtlCommand(StringifyMixin):
|
class VSCtlCommand(StringifyMixin):
|
||||||
|
"""
|
||||||
|
Class to describe artgumens similar to those of ``ovs-vsctl`` command.
|
||||||
|
|
||||||
|
``command`` specifies the command of ``ovs-vsctl``.
|
||||||
|
|
||||||
|
``args`` specifies a list or tuple of arguments for the given command.
|
||||||
|
|
||||||
|
``options`` specifies a list or tuple of options for the given command.
|
||||||
|
Please note that NOT all options of ``ovs-vsctl`` are supported.
|
||||||
|
For example, ``--id`` option is not yet supported.
|
||||||
|
This class supports the followings.
|
||||||
|
|
||||||
|
================= =========================================================
|
||||||
|
Option Description
|
||||||
|
================= =========================================================
|
||||||
|
``--may-exist`` Does nothing when the given port already exists.
|
||||||
|
The supported commands are ``add-port`` and
|
||||||
|
``add-bond``.
|
||||||
|
``--fake-iface`` Creates a port as a fake interface.
|
||||||
|
The supported command is ``add-bond``.
|
||||||
|
``--must-exist`` Raises exception if the given port does not exist.
|
||||||
|
The supported command is ``del-port``.
|
||||||
|
``--with-iface`` Takes effect to the interface which has the same name.
|
||||||
|
The supported command is ``del-port``.
|
||||||
|
``--if-exists`` Ignores exception when not found.
|
||||||
|
The supported command is ``get``.
|
||||||
|
================= =========================================================
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, command, args=None, options=None):
|
def __init__(self, command, args=None, options=None):
|
||||||
super(VSCtlCommand, self).__init__()
|
super(VSCtlCommand, self).__init__()
|
||||||
@ -978,6 +1009,13 @@ class VSCtlCommand(StringifyMixin):
|
|||||||
|
|
||||||
|
|
||||||
class VSCtl(object):
|
class VSCtl(object):
|
||||||
|
"""
|
||||||
|
A class to describe an Open vSwitch instance.
|
||||||
|
|
||||||
|
``remote`` specifies the address of the OVS instance.
|
||||||
|
:py:mod:`ryu.lib.ovs.vsctl.valid_ovsdb_addr` is a convenient function to
|
||||||
|
validate this address.
|
||||||
|
"""
|
||||||
|
|
||||||
def _reset(self):
|
def _reset(self):
|
||||||
self.schema_helper = None
|
self.schema_helper = None
|
||||||
@ -1237,6 +1275,19 @@ class VSCtl(object):
|
|||||||
self._do_main(commands)
|
self._do_main(commands)
|
||||||
|
|
||||||
def run_command(self, commands, timeout_sec=None, exception=None):
|
def run_command(self, commands, timeout_sec=None, exception=None):
|
||||||
|
"""
|
||||||
|
Executes the given commands and sends OVSDB messages.
|
||||||
|
|
||||||
|
``commands`` must be a list of
|
||||||
|
:py:mod:`ryu.lib.ovs.vsctl.VSCtlCommand`.
|
||||||
|
|
||||||
|
If ``timeout_sec`` is specified, raises exception after the given
|
||||||
|
timeout [sec]. Additionally, if ``exception`` is specified, this
|
||||||
|
function will wraps exception using the given exception class.
|
||||||
|
|
||||||
|
Retruns ``None`` but fills ``result`` attribute for each command
|
||||||
|
instance.
|
||||||
|
"""
|
||||||
if timeout_sec is None:
|
if timeout_sec is None:
|
||||||
self._run_command(commands)
|
self._run_command(commands)
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user