diff options
-rw-r--r-- | ryu/services/protocols/ovsdb/client.py | 70 | ||||
-rw-r--r-- | ryu/services/protocols/ovsdb/manager.py | 23 |
2 files changed, 90 insertions, 3 deletions
diff --git a/ryu/services/protocols/ovsdb/client.py b/ryu/services/protocols/ovsdb/client.py index 7c20eb2a..0f62f86e 100644 --- a/ryu/services/protocols/ovsdb/client.py +++ b/ryu/services/protocols/ovsdb/client.py @@ -15,6 +15,7 @@ import collections import errno +import six import uuid from ovs import jsonrpc @@ -132,6 +133,68 @@ def discover_system_id(idl): return system_id +def _filter_schemas(schemas, schema_tables, exclude_table_columns): + """Wrapper method for _filter_schema to filter multiple schemas.""" + return [_filter_schema(s, schema_tables, exclude_table_columns) + for s in schemas] + + +def _filter_schema(schema, schema_tables, exclude_table_columns): + """Filters a schema to only include the specified tables in the + schema_tables parameter. This will also filter out any colums for + included tables that reference tables that are not included + in the schema_tables parameter + + :param schema: Schema dict to be filtered + :param schema_tables: List of table names to filter on. + EX: ['Bridge', 'Controller', 'Interface'] + NOTE: This list is case sensitive. + :return: Schema dict: + filtered if the schema_table parameter contains table names, + else the original schema dict + """ + + tables = {} + for tbl_name, tbl_data in schema['tables'].iteritems(): + if not schema_tables or tbl_name in schema_tables: + columns = {} + + exclude_columns = exclude_table_columns.get(tbl_name, []) + for col_name, col_data in tbl_data['columns'].iteritems(): + if col_name in exclude_columns: + continue + + # NOTE(Alan Quillin) Needs to check and remove + # and columns that have references to tables that + # are not to be configured + type_ = col_data.get('type') + if type_: + if type_ and isinstance(type_, dict): + key = type_.get('key') + if key and isinstance(key, dict): + ref_tbl = key.get('refTable') + if ref_tbl and isinstance(ref_tbl, + six.string_types): + if ref_tbl not in schema_tables: + continue + value = type_.get('value') + if value and isinstance(value, dict): + ref_tbl = value.get('refTable') + if ref_tbl and isinstance(ref_tbl, + six.string_types): + if ref_tbl not in schema_tables: + continue + + columns[col_name] = col_data + + tbl_data['columns'] = columns + tables[tbl_name] = tbl_data + + schema['tables'] = tables + + return schema + + # NOTE(jkoelker) Wrap ovs's Idl to accept an existing session, and # trigger callbacks on changes class Idl(idl.Idl): @@ -218,7 +281,8 @@ class RemoteOvsdb(app_manager.RyuApp): @classmethod def factory(cls, sock, address, probe_interval=None, min_backoff=None, - max_backoff=None, *args, **kwargs): + max_backoff=None, schema_tables=None, + schema_exclude_columns={}, *args, **kwargs): ovs_stream = stream.Stream(sock, None, None) connection = jsonrpc.Connection(ovs_stream) schemas = discover_schemas(connection) @@ -226,6 +290,10 @@ class RemoteOvsdb(app_manager.RyuApp): if not schemas: return + if schema_tables or schema_exclude_columns: + schemas = _filter_schemas(schemas, schema_tables, + schema_exclude_columns) + fsm = reconnect.Reconnect(now()) fsm.set_name('%s:%s' % address) fsm.enable(now()) diff --git a/ryu/services/protocols/ovsdb/manager.py b/ryu/services/protocols/ovsdb/manager.py index a2b8a7e2..86a2d1ff 100644 --- a/ryu/services/protocols/ovsdb/manager.py +++ b/ryu/services/protocols/ovsdb/manager.py @@ -36,7 +36,14 @@ opts = (cfg.StrOpt('address', default='0.0.0.0', help='OVSDB address'), cfg.StrOpt('mngr-privkey', default=None, help='manager private key'), cfg.StrOpt('mngr-cert', default=None, help='manager certificate'), cfg.ListOpt('whitelist', default=[], - help='Whitelist of address to allow to connect')) + help='Whitelist of address to allow to connect'), + cfg.ListOpt('schema-tables', default=[], + help='Tables in the OVSDB schema to configure'), + cfg.ListOpt('schema-exclude-columns', default=[], + help='Table columns in the OVSDB schema to filter out. ' + 'Values should be in the format: <table>.<column>.' + 'Ex: Bridge.netflow,Interface.statistics') + ) cfg.CONF.register_opts(opts, 'ovsdb') @@ -119,10 +126,22 @@ class OVSDB(app_manager.RyuApp): return self.send_event(client_name, ev) def _start_remote(self, sock, client_address): + schema_tables = cfg.CONF.ovsdb.schema_tables + schema_ex_col = {} + if cfg.CONF.ovsdb.schema_exclude_columns: + for c in cfg.CONF.ovsdb.schema_exclude_columns: + tbl, col = c.split('.') + if tbl in schema_ex_col: + schema_ex_col[tbl].append(col) + else: + schema_ex_col[tbl] = [col] + app = client.RemoteOvsdb.factory(sock, client_address, probe_interval=self._probe_interval, min_backoff=self._min_backoff, - max_backoff=self._max_backoff) + max_backoff=self._max_backoff, + schema_tables=schema_tables, + schema_exclude_columns=schema_ex_col) if app: self._clients[app.name] = app |