From: Isaku Yamahata <[email protected]>

Signed-off-by: Isaku Yamahata <[email protected]>
---
 ryu/lib/ovs/vsctl.py | 393 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 393 insertions(+)

diff --git a/ryu/lib/ovs/vsctl.py b/ryu/lib/ovs/vsctl.py
index 19bc067..bda1dd6 100644
--- a/ryu/lib/ovs/vsctl.py
+++ b/ryu/lib/ovs/vsctl.py
@@ -18,7 +18,9 @@
 import gevent
 import itertools
 import logging
+import operator
 import os
+import sys
 import weakref
 
 import ovs.db.data
@@ -213,6 +215,21 @@ class VSCtlContext(object):
         self.bridges[name] = vsctl_bridge
         return vsctl_bridge
 
+    def del_cached_bridge(self, vsctl_bridge):
+        assert not vsctl_bridge.ports
+        assert not vsctl_bridge.children
+
+        parent = vsctl_bridge.parent
+        if parent:
+            parent.children.remove(vsctl_bridge)
+            vsctl_bridge.parent = None  # break circular reference
+        ovsrec_bridge = vsctl_bridge.br_cfg
+        if ovsrec_bridge:
+            ovsrec_bridge.delete()
+            self.ovs_delete_bridge(ovsrec_bridge)
+
+        del self.bridges[vsctl_bridge.name]
+
     def add_port_to_cache(self, vsctl_bridge_parent, ovsrec_port):
         tag = getattr(ovsrec_port, vswitch_idl.OVSREC_PORT_COL_TAG, None)
         if (tag is not None and tag >= 0 and tag < 4096):
@@ -428,6 +445,16 @@ class VSCtlContext(object):
                                     vswitch_idl.OVSREC_BRIDGE_COL_PORTS,
                                     ovsrec_port)
 
+    def ovs_insert_bridge(self, ovsrec_bridge):
+        self._column_insert(self.ovs,
+                            vswitch_idl.OVSREC_OPEN_VSWITCH_COL_BRIDGES,
+                            ovsrec_bridge)
+
+    def ovs_delete_bridge(self, ovsrec_bridge):
+        self._column_delete(self.ovs,
+                            vswitch_idl.OVSREC_OPEN_VSWITCH_COL_BRIDGES,
+                            ovsrec_bridge)
+
     def del_port(self, vsctl_port):
         if vsctl_port.bridge().parent:
             ovsrec_bridge = vsctl_port.bridge().parent.br_cfg
@@ -439,6 +466,13 @@ class VSCtlContext(object):
             self.del_cached_iface(vsctl_iface)
         self.del_cached_port(vsctl_port)
 
+    def del_bridge(self, vsctl_bridge):
+        for child in vsctl_bridge.children.copy():
+            self.del_bridge(child)
+        for vsctl_port in vsctl_bridge.ports.copy():
+            self.del_port(vsctl_port)
+        self.del_cached_bridge(vsctl_bridge)
+
     def add_port(self, br_name, port_name, may_exist, fake_iface,
                  iface_names, settings=None):
         """
@@ -504,6 +538,77 @@ class VSCtlContext(object):
         for ovsrec_iface in ifaces:
             self.add_iface_to_cache(vsctl_port, ovsrec_iface)
 
+    def add_bridge(self, br_name, parent_name=None, vlan=0, may_exist=False):
+        self.populate_cache()
+        if may_exist:
+            vsctl_bridge = self.find_bridge(br_name, False)
+            if vsctl_bridge:
+                if not parent_name:
+                    if vsctl_bridge.parent:
+                        vsctl_fatal('"--may-exist add-vsctl_bridge %s" '
+                                    'but %s is a VLAN bridge for VLAN %d' %
+                                    (br_name, br_name, vsctl_bridge.vlan))
+                else:
+                    if not vsctl_bridge.parent:
+                        vsctl_fatal('"--may-exist add-vsctl_bridge %s %s %d" '
+                                    'but %s is not a VLAN bridge' %
+                                    (br_name, parent_name, vlan, br_name))
+                    elif vsctl_bridge.parent.name != parent_name:
+                        vsctl_fatal('"--may-exist add-vsctl_bridge %s %s %d" '
+                                    'but %s has the wrong parent %s' %
+                                    (br_name, parent_name, vlan,
+                                     br_name, vsctl_bridge.parent.name))
+                    elif vsctl_bridge.vlan != vlan:
+                        vsctl_fatal('"--may-exist add-vsctl_bridge %s %s %d" '
+                                    'but %s is a VLAN bridge for the wrong '
+                                    'VLAN %d' %
+                                    (br_name, parent_name, vlan, br_name,
+                                     vsctl_bridge.vlan))
+                return
+
+        self.check_conflicts(br_name,
+                             'cannot create a bridge named %s' % br_name)
+
+        txn = self.txn
+        tables = self.idl.tables
+        if not parent_name:
+            ovsrec_iface = txn.insert(
+                tables[vswitch_idl.OVSREC_TABLE_INTERFACE])
+            ovsrec_iface.name = br_name
+            ovsrec_iface.type = 'internal'
+
+            ovsrec_port = txn.insert(tables[vswitch_idl.OVSREC_TABLE_PORT])
+            ovsrec_port.name = br_name
+            ovsrec_port.interfaces = [ovsrec_iface]
+            ovsrec_port.fake_bridge = False
+
+            ovsrec_bridge = txn.insert(tables[vswitch_idl.OVSREC_TABLE_BRIDGE])
+            ovsrec_bridge.name = br_name
+            ovsrec_bridge.ports = [ovsrec_port]
+
+            self.ovs_insert_bridge(ovsrec_bridge)
+        else:
+            parent = self.find_bridge(parent_name, False)
+            if parent and parent.parent:
+                vsctl_fatal('cannot create bridge with fake bridge as parent')
+            if not parent:
+                vsctl_fatal('parent bridge %s does not exist' % parent_name)
+
+            ovsrec_iface = txn.insert(
+                tables[vswitch_idl.OVSREC_TABLE_INTERFACE])
+            ovsrec_iface.name = br_name
+            ovsrec_iface.type = 'internal'
+
+            ovsrec_port = txn.insert(tables[vswitch_idl.OVSREC_TABLE_PORT])
+            ovsrec_port.name = br_name
+            ovsrec_port.interfaces = [ovsrec_iface]
+            ovsrec_port.fake_bridge = True
+            ovsrec_port.tag = [vlan]
+
+            self.bridge_insert_port(parent.br_cfg, ovsrec_port)
+
+        self.invalidate_cache()
+
     @staticmethod
     def parse_column_key_value(table_schema, setting_string):
         """
@@ -615,6 +720,15 @@ class VSCtlContext(object):
         return ovsrec_row
 
 
+class _CmdShowTable(object):
+    def __init__(self, table, name_column, columns, recurse):
+        super(_CmdShowTable, self).__init__()
+        self.table = table
+        self.name_column = name_column
+        self.columns = columns
+        self.recurse = recurse
+
+
 class _VSCtlRowID(object):
     def __init__(self, table, name_column, uuid_column):
         super(_VSCtlRowID, self).__init__()
@@ -826,19 +940,53 @@ class VSCtl(object):
         :type commands: list of VSCtlCommand
         """
         all_commands = {
+            # Open vSwitch commands.
+            'init': (None, self._cmd_init),
+            'show': (self._pre_cmd_show, self._cmd_show),
+
+            # Bridge commands.
+            'add-br': (self._pre_add_br, self._cmd_add_br),
+            'del-br': (self._pre_get_info, self._cmd_del_br),
+            'list-br': (self._pre_get_info, self._cmd_list_br),
+
             # Port. commands
             'list-ports': (self._pre_get_info, self._cmd_list_ports),
             'add-port': (self._pre_cmd_add_port, self._cmd_add_port),
             'del-port': (self._pre_get_info, self._cmd_del_port),
+            # 'add-bond':
+            # 'port-to-br':
+
+            # Interface commands.
+            'list-ifaces': (self._pre_get_info, self._cmd_list_ifaces),
+            # 'iface-to-br':
 
             # Controller commands.
+            'get-controller': (self._pre_controller, self._cmd_get_controller),
             'del-controller': (self._pre_controller, self._cmd_del_controller),
             'set-controller': (self._pre_controller, self._cmd_set_controller),
+            # 'get-fail-mode':
+            # 'del-fail-mode':
+            # 'set-fail-mode':
+
+            # Manager commands.
+            # 'get-manager':
+            # 'del-manager':
+            # 'set-manager':
+
+            # Switch commands.
+            # 'emer-reset':
 
             # Database commands.
+            # 'comment':
             'get': (self._pre_cmd_get, self._cmd_get),
+            # 'list':
             'find': (self._pre_cmd_find, self._cmd_find),
             'set': (self._pre_cmd_set, self._cmd_set),
+            # 'add':
+            'clear': (self._pre_cmd_clear, self._cmd_clear),
+            # 'create':
+            # 'destroy':
+            # 'wait-until':
 
             # for quantum_adapter
             'list-ifaces-verbose': (self._pre_cmd_list_ifaces_verbose,
@@ -857,6 +1005,112 @@ class VSCtl(object):
             with gevent.Timeout(timeout_msec * 1000, exception):
                 self._run_command(commands)
 
+    # commands
+    def _cmd_init(self, _ctx, _command):
+        # nothing. Just check connection to ovsdb
+        pass
+
+    _CMD_SHOW_TABLES = [
+        _CmdShowTable(vswitch_idl.OVSREC_TABLE_OPEN_VSWITCH, None,
+                      [vswitch_idl.OVSREC_OPEN_VSWITCH_COL_MANAGER_OPTIONS,
+                       vswitch_idl.OVSREC_OPEN_VSWITCH_COL_BRIDGES,
+                       vswitch_idl.OVSREC_OPEN_VSWITCH_COL_OVS_VERSION],
+                      False),
+        _CmdShowTable(vswitch_idl.OVSREC_TABLE_BRIDGE,
+                      vswitch_idl.OVSREC_BRIDGE_COL_NAME,
+                      [vswitch_idl.OVSREC_BRIDGE_COL_CONTROLLER,
+                       vswitch_idl.OVSREC_BRIDGE_COL_FAIL_MODE,
+                       vswitch_idl.OVSREC_BRIDGE_COL_PORTS],
+                      False),
+        _CmdShowTable(vswitch_idl.OVSREC_TABLE_PORT,
+                      vswitch_idl.OVSREC_PORT_COL_NAME,
+                      [vswitch_idl.OVSREC_PORT_COL_TAG,
+                       vswitch_idl.OVSREC_PORT_COL_TRUNKS,
+                       vswitch_idl.OVSREC_PORT_COL_INTERFACES],
+                      False),
+        _CmdShowTable(vswitch_idl.OVSREC_TABLE_INTERFACE,
+                      vswitch_idl.OVSREC_INTERFACE_COL_NAME,
+                      [vswitch_idl.OVSREC_INTERFACE_COL_TYPE,
+                       vswitch_idl.OVSREC_INTERFACE_COL_OPTIONS],
+                      False),
+        _CmdShowTable(vswitch_idl.OVSREC_TABLE_CONTROLLER,
+                      vswitch_idl.OVSREC_CONTROLLER_COL_TARGET,
+                      [vswitch_idl.OVSREC_CONTROLLER_COL_IS_CONNECTED],
+                      False),
+        _CmdShowTable(vswitch_idl.OVSREC_TABLE_MANAGER,
+                      vswitch_idl.OVSREC_MANAGER_COL_TARGET,
+                      [vswitch_idl.OVSREC_MANAGER_COL_IS_CONNECTED],
+                      False),
+    ]
+
+    def _pre_cmd_show(self, _ctx, _command):
+        schema_helper = self.schema_helper
+        for show in self._CMD_SHOW_TABLES:
+            schema_helper.register_table(show.table)
+            if show.name_column:
+                schema_helper.register_columns(show.table, [show.name_column])
+            schema_helper.register_columns(show.table, show.columns)
+
+    @staticmethod
+    def _cmd_show_find_table_by_row(row):
+        for show in VSCtl._CMD_SHOW_TABLES:
+            if show.table == row._table.name:
+                return show
+        return None
+
+    @staticmethod
+    def _cmd_show_find_table_by_name(name):
+        for show in VSCtl._CMD_SHOW_TABLES:
+            if show.table == name:
+                return show
+        return None
+
+    @staticmethod
+    def _cmd_show_row(ctx, row, level):
+        _INDENT_SIZE = 4  # # of spaces per indent
+        show = VSCtl._cmd_show_find_table_by_row(row)
+        output = ''
+
+        output += ' ' * level * _INDENT_SIZE
+        if show and show.name_column:
+            output += '%s ' % show.table
+            datum = getattr(row, show.name_column)
+            output += datum
+        else:
+            output += str(row.uuid)
+        output += '\n'
+
+        if not show or show.recurse:
+            return
+
+        show.recurse = True
+        for column in show.columns:
+            datum = row._data[column]
+            key = datum.type.key
+            if (key.type == ovs.db.types.UuidType and key.ref_table_name):
+                ref_show = VSCtl._cmd_show_find_table_by_name(
+                    key.ref_table_name)
+                if ref_show:
+                    for atom in datum.values:
+                        ref_row = ctx.idl.tables[ref_show.table].rows.get(
+                            atom.value)
+                        if ref_row:
+                            VSCtl._cmd_show_row(ctx, ref_row, level + 1)
+                    continue
+
+            if not datum.is_default():
+                output += ' ' * (level + 1) * _INDENT_SIZE
+                output += '%s: %s\n' % (column, datum)
+
+        show.recurse = False
+        return output
+
+    def _cmd_show(self, ctx, command):
+        for row in ctx.idl.tables[
+                self._CMD_SHOW_TABLES[0].table].rows.values():
+            output = self._cmd_show_row(ctx, row, 0)
+            command.result = output
+
     def _pre_get_info(self, _ctx, _command):
         schema_helper = self.schema_helper
 
@@ -879,6 +1133,43 @@ class VSCtl(object):
             vswitch_idl.OVSREC_TABLE_INTERFACE,
             [vswitch_idl.OVSREC_INTERFACE_COL_NAME])
 
+    def _cmd_list_br(self, ctx, command):
+        ctx.populate_cache()
+        command.result = sorted(ctx.bridges.keys())
+
+    def _pre_add_br(self, ctx, command):
+        self._pre_get_info(ctx, command)
+
+        schema_helper = self.schema_helper
+        schema_helper.register_columns(
+            vswitch_idl.OVSREC_TABLE_INTERFACE,
+            [vswitch_idl.OVSREC_INTERFACE_COL_TYPE])
+
+    def _cmd_add_br(self, ctx, command):
+        br_name = command.args[0]
+        if len(command.args) == 1:
+            parent_name = None
+            vlan = 0
+        elif len(command.args) == 3:
+            parent_name = command.args[1]
+            vlan = int(command.args[2])
+            if vlan < 0 or vlan > 4095:
+                vsctl_fatal("vlan must be between 0 and 4095 %d" % vlan)
+        else:
+            vsctl_fatal('this command takes exactly 1 or 3 argument')
+
+        ctx.add_bridge(br_name, parent_name, vlan)
+
+    def _del_br(self, ctx, br_name, must_exist=False):
+        ctx.populate_cache()
+        br = ctx.find_bridge(br_name, must_exist)
+        if br:
+            ctx.del_bridge(br)
+
+    def _cmd_del_br(self, ctx, command):
+        br_name = command.args[0]
+        self._del_br(ctx, br_name)
+
     def _list_ports(self, ctx, br_name):
         ctx.populate_cache()
         br = ctx.find_bridge(br_name, True)
@@ -962,6 +1253,25 @@ class VSCtl(object):
         br_name = command.args[0] if len(command.args) == 2 else None
         self._del_port(ctx, br_name, target, must_exist, with_iface)
 
+    def _list_ifaces(self, ctx, br_name):
+        ctx.populate_cache()
+
+        br = ctx.find_bridge(br_name, True)
+        ctx.verify_ports()
+
+        iface_names = set()
+        for vsctl_port in br.ports:
+            for vsctl_iface in vsctl_port.ifaces:
+                iface_name = vsctl_iface.iface_cfg.name
+                if iface_name != br_name:
+                    iface_names.add(iface_name)
+        return iface_names
+
+    def _cmd_list_ifaces(self, ctx, command):
+        br_name = command.args[0]
+        iface_names = self._list_ifaces(ctx, br_name)
+        command.result = sorted(iface_names)
+
     def _pre_cmd_list_ifaces_verbose(self, ctx, command):
         self._pre_get_info(ctx, command)
         schema_helper = self.schema_helper
@@ -1028,6 +1338,17 @@ class VSCtl(object):
             vswitch_idl.OVSREC_TABLE_CONTROLLER,
             [vswitch_idl.OVSREC_CONTROLLER_COL_TARGET])
 
+    def _get_controller(self, ctx, br_name):
+        ctx.populate_cache()
+        br = ctx.find_bridge(br_name, True)
+        self._verify_controllers(br.br_cfg)
+        return set(controller.target for controller in br.br_cfg.controller)
+
+    def _cmd_get_controller(self, ctx, command):
+        br_name = command.args[0]
+        controller_names = self._get_controller(ctx, br_name)
+        command.result = sorted(controller_names)
+
     def _delete_controllers(self, ovsrec_controllers):
         for controller in ovsrec_controllers:
             controller.delete()
@@ -1339,3 +1660,75 @@ class VSCtl(object):
                              for column_key_value in command.args[2:]]
 
         self._set(ctx, table_name, record_id, column_key_values)
+
+    def _pre_clear(self, ctx, table_name, column):
+        self._pre_get_table(ctx, table_name)
+        self._pre_get_column(ctx, table_name, column)
+        self._check_mutable(table_name, column)
+
+    def _pre_cmd_clear(self, ctx, command):
+        table_name = command.args[0]
+        column = command.args[2]
+        self._pre_clear(ctx, table_name, column)
+
+    def _clear(self, ctx, table_name, record_id, column):
+        vsctl_table = self._get_table(table_name)
+        ovsrec_row = ctx.must_get_row(vsctl_table, record_id)
+        column_schema = ctx.idl.tables[table_name].columns[column]
+        if column_schema.type.n_min > 0:
+            vsctl_fatal('"clear" operation cannot be applied to column %s '
+                        'of table %s, which is not allowed to be empty' %
+                        (column, table_name))
+
+        # assuming that default datum is empty.
+        default_datum = ovs.db.data.Datum.default(column_schema.type)
+        setattr(ovsrec_row, column,
+                default_datum.to_python(ovs.db.idl._uuid_to_row))
+        ctx.invalidate_cache()
+
+    def _cmd_clear(self, ctx, command):
+        table_name = command.args[0]
+        record_id = command.args[1]
+        column = command.args[2]
+        self._clear(ctx, table_name, record_id, column)
+
+
+#
+# Create constants from ovs db schema
+#
+
+def schema_print(schema_location, prefix):
+    prefix = prefix.upper()
+
+    json = ovs.json.from_file(schema_location)
+    schema = ovs.db.schema.DbSchema.from_json(json)
+
+    print '# Do NOT edit.'
+    print '# This is automatically generated.'
+    print '# created based on version %s' % (schema.version or 'unknown')
+    print ''
+    print ''
+    print '%s_DB_NAME = \'%s\'' % (prefix, schema.name)
+    for table in sorted(schema.tables.values(),
+                        key=operator.attrgetter('name')):
+        print ''
+        print '%s_TABLE_%s = \'%s\'' % (prefix,
+                                        table.name.upper(), table.name)
+        for column in sorted(table.columns.values(),
+                             key=operator.attrgetter('name')):
+            print '%s_%s_COL_%s = \'%s\'' % (prefix, table.name.upper(),
+                                             column.name.upper(),
+                                             column.name)
+
+
+def main():
+    if len(sys.argv) <= 2:
+        print 'Usage: %s <schema file> <prefix>' % sys.argv[0]
+
+    location = sys.argv[1]
+    prefix = sys.argv[2]
+    schema_print(location, prefix)
+
+
+if __name__ == '__main__':
+    main()
-- 
1.7.12


------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to