Hi Tim,

Thank you for your reporting.

I could reproduce the same problem, but this problem is on "ovs" python library
and not on Ryu...

My Script:
=====
from ryu.lib.ovs import vsctl

OVSDB_ADDR = 'tcp:127.0.0.1:6640'


# Equivalent to
# $ ovs-vsctl get Port bond0 interfaces
ovs_vsctl = vsctl.VSCtl(OVSDB_ADDR)
command = vsctl.VSCtlCommand('get', ('Port', 'bond0', 'interfaces'))
ovs_vsctl.run_command([command])
print('*** %s' % command)
=====

Also, I added some "print" for debugging:
=====
$ git diff
diff --git a/ryu/lib/ovs/vsctl.py b/ryu/lib/ovs/vsctl.py
index 2391c90..4bc5c90 100644
--- a/ryu/lib/ovs/vsctl.py
+++ b/ryu/lib/ovs/vsctl.py
@@ -792,6 +792,10 @@ class VSCtlContext(object):
         return column, value

     def get_column(self, ovsrec_row, column, key=None, if_exists=False):
+        print(type(ovsrec_row))
+        print(ovsrec_row._table.columns)
+        print(ovsrec_row.name)
+        print(ovsrec_row.interfaces)
         value = getattr(ovsrec_row, column, None)
         if isinstance(value, dict) and key is not None:
             value = value.get(key, None)
=====

Port info:
=====
$ ovs-vsctl list Port bond0
_uuid               : d1c90fc5-1be7-4449-87ed-be4886eb27c3
bond_active_slave   : "16:a5:69:64:4b:2f"
bond_downdelay      : 0
bond_fake_iface     : false
bond_mode           : []
bond_updelay        : 0
cvlans              : []
external_ids        : {}
fake_bridge         : false
interfaces : [5efc3ba8-6fd1-4f0c-83bf-74ff6e3f2909, a756d290-62f0-4030-a5b6-fcc3a5e8b662]
lacp                : []
mac                 : []
name                : "bond0"
other_config        : {}
protected           : false
qos                 : []
rstp_statistics     : {}
rstp_status         : {}
statistics          : {}
status              : {}
tag                 : []
trunks              : []
vlan_mode           : []
=====

Traceback messages:
=====
$ python test_lib_ovs.py
<class 'ovs.db.idl.Row'>
{'interfaces': <ovs.db.schema.ColumnSchema object at 0x7fc19d22af28>, 'name': <ovs.db.schema.ColumnSchema object at 0x7fc19d1ac208>}
bond0
Traceback (most recent call last):
  File "test_lib_ovs.py", line 372, in <module>
    ovs_vsctl.run_command([command])
File "<...>/python3.5/site-packages/ryu/lib/ovs/vsctl.py", line 1245, in run_command
    self._run_command(commands)
File "<...>/python3.5/site-packages/ryu/lib/ovs/vsctl.py", line 1241, in _run_command
    self._do_main(commands)
  File "<...>/python3.5/site-packages/ryu/lib/ovs/vsctl.py", line 1147, in 
_do_main
    if self._do_vsctl(idl_, commands):
File "<...>/python3.5/site-packages/ryu/lib/ovs/vsctl.py", line 1082, in _do_vsctl
    command._run(ctx, command)
  File "<...>/python3.5/site-packages/ryu/lib/ovs/vsctl.py", line 2169, in 
_cmd_get
    ctx, table_name, record_id, column_keys, id_, if_exists)
  File "<...>/python3.5/site-packages/ryu/lib/ovs/vsctl.py", line 2154, in _get
    result.append(ctx.get_column(ovsrec_row, column, key, if_exists))
File "<...>/python3.5/site-packages/ryu/lib/ovs/vsctl.py", line 798, in get_column
    print(ovsrec_row.interfaces)
  File "<...>/python3.5/site-packages/ovs/db/idl.py", line 829, in __getattr__
    return datum.to_python(_uuid_to_row)
  File "<...>/python3.5/site-packages/ovs/db/data.py", line 499, in to_python
    dk = uuid_to_row(k.value, self.type.key)
  File "<...>/python3.5/site-packages/ovs/db/idl.py", line 663, in _uuid_to_row
    return base.ref_table.rows.get(atom)
AttributeError: 'TableSchema' object has no attribute 'rows'
=====

Although "ovs.db.idl.Row" class has "interfaces" column, it seems to fail to
convert the column into Python representation.
I guess we need to contact to OVS dev team to solve this issue.


Thanks,
Iwase


On 2017年12月19日 03:44, Tim Ireland wrote:

I’m writing a wrapper around the vsctl command so I can collect data about a remote ovs instance.  I have a need to get the mapping from each Interface to it’s corresponding Port.  Using the “get” command, I can fetch all data that is visible in the "ovsdb-client dump" command for a Port, except the “interfaces” column of the “Port” table.

# ovs-vsctl list Port bond0
_uuid               : a2198907-9d08-4872-bcf6-f87a8b111e35
bond_active_slave   : "00:e0:ed:75:bb:07"
bond_downdelay      : 0
bond_fake_iface     : false
bond_mode           : balance-slb
bond_updelay        : 0
external_ids        : {}
fake_bridge         : false
interfaces          : [98f33062-83dd-4c0b-a0c7-400eaecd9dc3, c8ba39a6-2642-4c66-95d1-9f1a4b4c57ff]
lacp                : []
mac                 : []
name                : "bond0"
other_config        : {bond-rebalance="10000"}
qos                 : []
rstp_statistics     : {}
rstp_status         : {}
statistics          : {}
status              : {}
tag                 : []
trunks              : []
vlan_mode           : []

Here is the wrapper class:

class OvsdbClient(object):
/"""Open vSwitch OVSDB client, via ryu vsctl interface."""/
//
//def __init__(self, host, port, logger):
/"""Initialize OvsdbClient./
//
/        Arguments:/
/            host (str): Host running OVS./
/            port (int): OVSDB server port./
/            logger (logging.Logger): Logging instance./
/        """/
//self._logger = logger
         self._vsctl = vsctl.VSCtl('tcp:{}:{}'.format(host, port))

     def run_vsctl_commands(self, commands):
         self._vsctl.run_command(commands, timeout_sec=2)

     def run_command(self, command, args=None):
/"""Run an ovsdb command./
//
/        Arguments:/
/            command (str): The command to execute./
/            args (list): Optional list of arguments to pass to the command./
//
/        Returns:/
/            VSCtlCommand.result: data returned as a result of the command./
/        """/
//args = args if args else []
         vsctl_command = vsctl.VSCtlCommand(command, args=args)
         self.run_vsctl_commands([vsctl_command])
         return vsctl_command.result

     def show(self):
/"""Show the current ovsdb configuration in one large dump."""/
//return self.run_command('show')

     def list(self, table):
/"""List the contents of a single table in ovsdb."""/
//return self.run_command('list', args=[table])

     def get(self, table, record, keys):
/"""Retrieve specific data from ovsdb tables./
//
/        Arguments:/
/            table (str): Ovsdb table name, ex: 'Bridge', 'Port`, etc./
/            record (str): Name of the item in the table, ex: 'br0'/
/            keys (list): List of keys which identify additional settings, ex: 'other_config'/
/        """/
//args = [table, record]
         args.extend(keys)
         return self.run_command('get', args=args)

I am executing a “get” command for the Port table and including “interfaces” in the list of keys.

PORT_KEYS = [vswitch_idl.OVSREC_PORT_COL_NAME,
              vswitch_idl.OVSREC_PORT_COL_BOND_ACTIVE_SLAVE,
              vswitch_idl.OVSREC_PORT_COL_BOND_MODE,
              vswitch_idl.OVSREC_PORT_COL_OTHER_CONFIG,
              vswitch_idl.OVSREC_PORT_COL_LACP,
              vswitch_idl.OVSREC_PORT_COL_EXTERNAL_IDS,
              vswitch_idl.OVSREC_PORT_COL_TAG,
//vswitch_idl.OVSREC_PORT_COL_INTERFACES,
              vswitch_idl.OVSREC_PORT_COL_VLAN_MODE]

data = dict(zip(PORT_KEYS, client.get(vswitch_idl.OVSREC_TABLE_PORT, ‘bond0', self.PORT_KEYS)))

However, of all the keys, the “interfaces” key does not seem to work.

File "/opt/stackstorm/virtualenvs/nutanix/lib/python2.7/site-packages/ryu/lib/ovs/vsctl.py", line 1207, in run_command
     self._run_command(commands)
  File "/opt/stackstorm/virtualenvs/nutanix/lib/python2.7/site-packages/ryu/lib/ovs/vsctl.py", line 1200, in _run_command
     self._do_main(commands)
  File "/opt/stackstorm/virtualenvs/nutanix/lib/python2.7/site-packages/ryu/lib/ovs/vsctl.py", line 1106, in _do_main
     if self._do_vsctl(idl_, commands):
  File "/opt/stackstorm/virtualenvs/nutanix/lib/python2.7/site-packages/ryu/lib/ovs/vsctl.py", line 1041, in _do_vsctl
     command._run(ctx, command)
  File "/opt/stackstorm/virtualenvs/nutanix/lib/python2.7/site-packages/ryu/lib/ovs/vsctl.py", line 2128, in _cmd_get
     ctx, table_name, record_id, column_keys, id_, if_exists)
  File "/opt/stackstorm/virtualenvs/nutanix/lib/python2.7/site-packages/ryu/lib/ovs/vsctl.py", line 2113, in _get
     result.append(ctx.get_column(ovsrec_row, column, key, if_exists))
  File "/opt/stackstorm/virtualenvs/nutanix/lib/python2.7/site-packages/ryu/lib/ovs/vsctl.py", line 767, in get_column
     % (ovsrec_row._table.name, column))
  File "/opt/stackstorm/virtualenvs/nutanix/lib/python2.7/site-packages/ryu/lib/ovs/vsctl.py", line 140, in vsctl_fatal
     raise Exception(msg)        # not call ovs.utils.ovs_fatal for reusability
Exception: Port does not contain a column whose name matches “interfaces"


I can’t seem to find another way to get the interfaces mapping.  There is the “iface-to-br" command, but that seems to suggest that there is a one to one mapping between bridges and ports, which is an assumption I can probably make for now, but will that always be the case?

Regards,

-Tim




------------------------------------------------------------------------------
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


------------------------------------------------------------------------------
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