Signed-off-by: IWASE Yusuke <iwase.yusu...@gmail.com>
---
 doc/source/library.rst       |   1 +
 doc/source/library_ovsdb.rst |  76 ++++++++++++++++++++++++
 ryu/lib/ovs/bridge.py        | 134 ++++++++++++++++++++++++++++++++++++++++++-
 ryu/lib/ovs/vsctl.py         |  57 +++++++++++++++++-
 4 files changed, 264 insertions(+), 4 deletions(-)
 create mode 100644 doc/source/library_ovsdb.rst

diff --git a/doc/source/library.rst b/doc/source/library.rst
index ff28041..cdaed76 100644
--- a/doc/source/library.rst
+++ b/doc/source/library.rst
@@ -15,3 +15,4 @@ Ryu provides some useful library for your network 
applications.
    library_bgp_speaker_ref.rst
    library_mrt.rst
    library_ovsdb_manager.rst
+   library_ovsdb.rst
diff --git a/doc/source/library_ovsdb.rst b/doc/source/library_ovsdb.rst
new file mode 100644
index 0000000..df7d170
--- /dev/null
+++ b/doc/source/library_ovsdb.rst
@@ -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:
diff --git a/ryu/lib/ovs/bridge.py b/ryu/lib/ovs/bridge.py
index e48052f..9753fa2 100644
--- a/ryu/lib/ovs/bridge.py
+++ b/ryu/lib/ovs/bridge.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 """
-slimmed down version of OVSBridge in quantum agent
+Wrapper utility library of :py:mod:`ryu.lib.ovs.vsctl`
 """
 
 import functools
@@ -92,6 +92,26 @@ class TunnelPort(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,
                  exception=None):
@@ -105,9 +125,25 @@ class OVSBridge(object):
         self.br_name = None
 
     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)
 
     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):
             raise ValueError('Invalid OVSDB address: %s' % self.ovsdb_addr)
         if self.br_name is None:
@@ -126,16 +162,37 @@ class OVSBridge(object):
         return command.result[0].name
 
     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])
         self.run_command([command])
         return command.result[0]
 
     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.args.extend(controllers)
         self.run_command([command])
 
     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])
         self.run_command([command])
 
@@ -245,30 +302,72 @@ class OVSBridge(object):
         self.run_command([command])
 
     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))
         self.run_command([command])
         assert len(command.result) == 1
         return command.result[0]
 
     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)
         assert isinstance(val, dict)
         return val
 
     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')
 
     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(
             'del-port', (self.br_name, port_name), '--if-exists')
         self.run_command([command])
 
     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')
         assert len(ofport_list) == 1
         return int(ofport_list[0])
 
     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, ))
         self.run_command([command])
         return command.result
@@ -297,6 +396,16 @@ class OVSBridge(object):
 
     def add_tunnel_port(self, name, tunnel_type, remote_ip,
                         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()
         if key:
             options += ',key=%(key)s' % locals()
@@ -314,15 +423,32 @@ class OVSBridge(object):
 
     def add_gre_port(self, name, remote_ip,
                      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,
                              local_ip=local_ip, key=key, ofport=ofport)
 
     def add_vxlan_port(self, name, remote_ip,
                        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,
                              local_ip=local_ip, key=key, ofport=ofport)
 
     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))
         self.run_command([command])
 
@@ -396,6 +522,9 @@ class OVSBridge(object):
         return 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 []
         command_qos = ovs_vsctl.VSCtlCommand(
             'set-qos',
@@ -409,6 +538,9 @@ class OVSBridge(object):
         return None
 
     def del_qos(self, port_name):
+        """
+        Deletes the Qos rule on the given port.
+        """
         command = ovs_vsctl.VSCtlCommand(
             'del-qos',
             [port_name])
diff --git a/ryu/lib/ovs/vsctl.py b/ryu/lib/ovs/vsctl.py
index b18b5ef..f3355a1 100644
--- a/ryu/lib/ovs/vsctl.py
+++ b/ryu/lib/ovs/vsctl.py
@@ -14,6 +14,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""
+``ovs-vsctl`` command like library to speak OVSDB protocol
+"""
 
 from __future__ import print_function
 
@@ -53,9 +56,9 @@ def valid_ovsdb_addr(addr):
 
     The valid formats are:
 
-    - unix:file
-    - tcp:ip:port
-    - ssl:ip:port
+    - ``unix:file``
+    - ``tcp:ip:port``
+    - ``ssl:ip:port``
 
     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 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):
         super(VSCtlCommand, self).__init__()
@@ -978,6 +1009,13 @@ class VSCtlCommand(StringifyMixin):
 
 
 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):
         self.schema_helper = None
@@ -1237,6 +1275,19 @@ class VSCtl(object):
         self._do_main(commands)
 
     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:
             self._run_command(commands)
         else:
-- 
2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to