diff options
author | Alan Quillin <alanquillin@gmail.com> | 2016-05-03 12:54:28 -0400 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-05-10 05:31:24 +0900 |
commit | 7db022bf71fe3de9f6e7d4550e017c6d1cd70c10 (patch) | |
tree | 35091ac1cfacf73825765540ecb243d70902ae36 | |
parent | dbe67437428da79506f9d08050a81f8b28ac4699 (diff) |
Enable filtering the OVSDB schema tables/columns
Adds the ability to filter the OVSDB scheme to only include specified
tables from the config as well as filter out (exclude) specific table
columns. If neither of the values are defined in the config, then the
discovered schema is used unchanged. The is needed to calm down noise with
unused tables/columns to help with scale problems on hosts with a large
number of bridges and interfaces.
Signed-off-by: Alan Quillin <alanquillin@gmail.com>
Acked-By: Jason Kölker <jason@koelker.net>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-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 |