Skip to content

Instantly share code, notes, and snippets.

@otherwiseguy
Created November 12, 2020 01:26
Show Gist options
  • Save otherwiseguy/3f0443b07880cdbb24e15610dc1dc04b to your computer and use it in GitHub Desktop.
Save otherwiseguy/3f0443b07880cdbb24e15610dc1dc04b to your computer and use it in GitHub Desktop.
Handle schema changes
import logging
import json
import time
from ovs.db import custom_index
from ovs.db import idl
from ovsdbapp.backend.ovs_idl import connection
from ovsdbapp.backend.ovs_idl import event
from ovsdbapp.backend.ovs_idl import vlog
from ovsdbapp.schema.ovn_southbound import impl_idl
logging.basicConfig()
vlog.use_python_logger()
class AgentEvent(event.RowEvent):
GLOBAL = True
event_name = 'AgentEvent'
def __init__(self):
super().__init__((self.ROW_CREATE, self.ROW_UPDATE), 'Chassis_Private',
None)
def run(self, event, row, updates=None):
print(event, row)
class MyIdl(connection.OvsdbIdl):
def __init__(self, *args, **kwargs):
self.event_handler = event.RowEventHandler()
super().__init__(*args, **kwargs)
def notify(self, event, row, updates=None):
# __send_monitor_request() is called after notify() in python-ovs, but
# RowEventHandler pushes processing the notification to a different
# thread, so I think we have to process these schema changes here or
# we might miss monitoring the new table. We could create a list of
# "in the connection thread" events to match...
if (event == 'create' and row._table.name == 'Database' and
row.name == 'OVN_Southbound'):
sh = idl.SchemaHelper(None, json.loads(row.schema[0]))
# We need to set up the schema helper exactly how we did in the
# from_server() call. This should be an approximation, but breaking
# those out into a setup_schema() method would be ideal I think.
for table in self.tables:
if table in sh.schema_json['tables']:
sh.register_table(table)
if 'Chassis_Private' in sh.schema_json['tables']:
sh.register_table('Chassis_Private')
schema = sh.get_idl_schema()
self._db = schema
self.tables = schema.tables
for table in schema.tables.values():
for column in table.columns.values():
if not hasattr(column, 'alert'):
column.alert = True
table.need_table = False
table.rows = custom_index.IndexedRows(table)
table.idl = self
table.condition = [True]
table.cond_changed = False
# RowEventHandler events lose easy access to the idl by losing self
# I don't know whether this is good or bad. :p
else:
self.event_handler.notify(event, row, updates)
def row_repr(self):
return "{table}({data})".format(
table=self._table.name,
data=", ".join("{col}={val}".format(col=c,
val=getattr(self, c, '<unset>'))
for c in sorted(self._table.columns)))
idl.Row.__repr__ = idl.Row.__str__ = row_repr
conn = "tcp:127.0.0.1:6642"
i = MyIdl.from_server(conn, 'OVN_Southbound')
i.event_handler.watch_event(AgentEvent())
c = connection.Connection(idl=i, timeout=3)
api = impl_idl.OvnSbApiIdlImpl(c)
while True:
print('Chassis_Private' in api.tables)
time.sleep(2)
@otherwiseguy
Copy link
Author

otherwiseguy commented Nov 12, 2020

It would be nice if Idl.__init__() broke out the the table setup into a helper function that we could just call instead of re-implementing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment