On Fri, Jan 4, 2019 at 5:26 PM Numan Siddique <[email protected]> wrote:
> Hi Ted, > > This patch is failing the below test cases for me. All are python3 > related. Can you please > take a look if that's the case with you as well ? > ****** > 2139: simple idl, writing via IDL with unicode - Python3 FAILED ( > ovsdb-idl.at:456) > 2141: simple idl, writing via IDL with unicode - Python3 - > register_columns FAILED (ovsdb-idl.at:456) > 2143: simple idl, writing via IDL with unicode - Python3 - tcp FAILED ( > ovsdb-idl.at:456) > 2145: simple idl, writing via IDL with unicode - Python3 (multiple > remotes) - tcp FAILED (ovsdb-idl.at:456) > 2147: simple idl, writing via IDL with unicode - Python3 - tcp6 FAILED ( > ovsdb-idl.at:456) > 2149: simple idl, writing via IDL with unicode - Python3 (multiple > remotes) - tcp6 FAILED (ovsdb-idl.at:456) > 2151: simple idl, writing via IDL with unicode - Python3 - SSL FAILED ( > ovsdb-idl.at:456) > 2153: simple idl, writing large data via IDL with unicode - Python3 FAILED > (ovsdb-idl.at:490) > ********** > These failures are not related to this patch. Please ignore. There seems to be some issues with python3.7 with unicode in Fedora 29 and I think Timothy is planning to submit a patch to fix these failures. Thanks Numan > Please see some comments below. > > Thanks > Numan > > On Fri, Jan 4, 2019 at 7:47 AM Ted Elhourani <[email protected]> > wrote: > >> The Python IDL implementation supports ovsdb cluster connections. >> This patch is a follow up to commit 31e434fc98, it adds the option of >> connecting to the leader (the default) in the Raft-based cluster. It >> mimics >> the exisiting C IDL support for clusters introduced in commit 1b1d2e6daa. >> >> The _Server database schema is first requested, then a monitor of the >> Database table in the _Server Database. Method __check_server_db verifies >> the eligibility of the server. If the attempt to obtain a monitor of the >> _Server database fails and a cluster id was not provided this >> implementation >> proceeds to request the data monitor. If a cluster id was provided via the >> set_cluster_id method then the connection is aborted and a connection to a >> different node is instead attempted, until a valid cluster node is found. >> Thus, when supplied, cluster id is interpreted as the intention to only >> allow connections to a clustered database. If not supplied, connections to >> standalone nodes, or nodes that do not have the _Server database are >> allowed. change_seqno is not incremented in the case of Database table >> updates. >> Signed-off-by: Ted Elhourani <[email protected]> >> --- >> python/ovs/db/idl.py | 217 >> ++++++++++++++++++++++++++++++++++++++++++++---- >> python/ovs/reconnect.py | 3 + >> tests/ovsdb-idl.at | 62 +++++++------- >> 3 files changed, 237 insertions(+), 45 deletions(-) >> >> diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py >> index 250e897..f989548 100644 >> --- a/python/ovs/db/idl.py >> +++ b/python/ovs/db/idl.py >> @@ -38,6 +38,7 @@ ROW_DELETE = "delete" >> OVSDB_UPDATE = 0 >> OVSDB_UPDATE2 = 1 >> >> +CLUSTERED = "clustered" >> >> class Idl(object): >> """Open vSwitch Database Interface Definition Language (OVSDB IDL). >> @@ -92,10 +93,12 @@ class Idl(object): >> """ >> >> IDL_S_INITIAL = 0 >> - IDL_S_MONITOR_REQUESTED = 1 >> - IDL_S_MONITOR_COND_REQUESTED = 2 >> + IDL_S_SERVER_SCHEMA_REQUESTED = 1 >> + IDL_S_SERVER_MONITOR_REQUESTED = 2 >> + IDL_S_DATA_MONITOR_REQUESTED = 3 >> + IDL_S_DATA_MONITOR_COND_REQUESTED = 4 >> >> - def __init__(self, remote, schema_helper, probe_interval=None): >> + def __init__(self, remote, schema_helper, leader_only=True, >> probe_interval=None): >> > > Can you please add the "leader_only" arg at the end. Older clients of > python idl would > break if they were creating Idl object as > my_idl = Idl(remote, helper, 1000) > > > """Creates and returns a connection to the database named >> 'db_name' on >> 'remote', which should be in a form acceptable to >> ovs.jsonrpc.session.open(). The connection will maintain an >> in-memory >> @@ -119,6 +122,9 @@ class Idl(object): >> >> The IDL uses and modifies 'schema' directly. >> >> + If 'leader_only' is set to True (default value) the IDL will >> only monitor >> + and transact with the leader of the cluster. >> + >> If "probe_interval" is zero it disables the connection keepalive >> feature. If non-zero the value will be forced to at least 1000 >> milliseconds. If None it will just use the default value in OVS. >> @@ -137,6 +143,20 @@ class Idl(object): >> self._last_seqno = None >> self.change_seqno = 0 >> self.uuid = uuid.uuid1() >> + >> + # Server monitor. >> + self._server_schema_request_id = None >> + self._server_monitor_request_id = None >> + self._db_change_aware_request_id = None >> + self._server_db_name = '_Server' >> + self._server_db_table = 'Database' >> + self.server_tables = None >> + self._server_db = None >> + self.server_monitor_uuid = uuid.uuid1() >> + self.leader_only = leader_only >> + self.cluster_id = None >> + self._min_index = 0 >> + >> self.state = self.IDL_S_INITIAL >> >> # Database locking. >> @@ -172,6 +192,15 @@ class Idl(object): >> remotes.append(r) >> return remotes >> >> + def set_cluster_id(self, cluster_id): >> + """Set the id of the cluster that this idl must connect to.""" >> + if cluster_id: >> + self.cluster_id = str(cluster_id) >> + else: >> + self.cluster_id = None >> > > Instead of the "if - else", how about just > self.cluster_id = cluster_id > > Can cluster_id be passed as an integer by the caller ? > > > >> + if self.state != self.IDL_S_INITIAL: >> + self.force_reconnect() >> + >> def index_create(self, table, name): >> """Create a named multi-column index on a table""" >> return self.tables[table].rows.index_create(name) >> @@ -222,7 +251,7 @@ class Idl(object): >> if seqno != self._last_seqno: >> self._last_seqno = seqno >> self.__txn_abort_all() >> - self.__send_monitor_request() >> + self.__send_server_schema_request() >> if self.lock_name: >> self.__send_lock_request() >> break >> @@ -230,6 +259,7 @@ class Idl(object): >> msg = self._session.recv() >> if msg is None: >> break >> + >> if (msg.type == ovs.jsonrpc.Message.T_NOTIFY >> and msg.method == "update2" >> and len(msg.params) == 2): >> @@ -239,7 +269,15 @@ class Idl(object): >> and msg.method == "update" >> and len(msg.params) == 2): >> # Database contents changed. >> - self.__parse_update(msg.params[1], OVSDB_UPDATE) >> + if msg.params[0] == str(self.server_monitor_uuid): >> + self.__parse_update(msg.params[1], OVSDB_UPDATE, >> + tables=self.server_tables) >> + self.change_seqno = initial_change_seqno >> + if not self.__check_server_db(): >> + self.force_reconnect() >> + break >> + else: >> + self.__parse_update(msg.params[1], OVSDB_UPDATE) >> elif (msg.type == ovs.jsonrpc.Message.T_REPLY >> and self._monitor_request_id is not None >> and self._monitor_request_id == msg.id): >> @@ -248,17 +286,66 @@ class Idl(object): >> self.change_seqno += 1 >> self._monitor_request_id = None >> self.__clear() >> - if self.state == self.IDL_S_MONITOR_COND_REQUESTED: >> + if self.state == >> self.IDL_S_DATA_MONITOR_COND_REQUESTED: >> self.__parse_update(msg.result, OVSDB_UPDATE2) >> else: >> - assert self.state == self.IDL_S_MONITOR_REQUESTED >> + assert self.state == >> self.IDL_S_DATA_MONITOR_REQUESTED >> self.__parse_update(msg.result, OVSDB_UPDATE) >> - >> except error.Error as e: >> vlog.err("%s: parse error in received schema: %s" >> % (self._session.get_name(), e)) >> self.__error() >> elif (msg.type == ovs.jsonrpc.Message.T_REPLY >> + and self._server_schema_request_id is not None >> + and self._server_schema_request_id == msg.id): >> + # Reply to our "get_schema" of _Server request. >> + try: >> + self._server_schema_request_id = None >> + sh = SchemaHelper(None, msg.result) >> + sh.register_table(self._server_db_table) >> + schema = sh.get_idl_schema() >> + self._server_db = schema >> + self.server_tables = schema.tables >> + self.__send_server_monitor_request() >> + except error.Error as e: >> + vlog.err("%s: error receiving server schema: %s" >> + % (self._session.get_name(), e)) >> + if self.cluster_id: >> + self.__error() >> + break >> + else: >> + self.change_seqno = initial_change_seqno >> + self.__send_monitor_request() >> + elif (msg.type == ovs.jsonrpc.Message.T_REPLY >> + and self._server_monitor_request_id is not None >> + and self._server_monitor_request_id == msg.id): >> + # Reply to our "monitor" of _Server request. >> + try: >> + self._server_monitor_request_id = None >> + self.__parse_update(msg.result, OVSDB_UPDATE, >> + tables=self.server_tables) >> + self.change_seqno = initial_change_seqno >> + if self.__check_server_db(): >> + self.__send_monitor_request() >> + self.__send_db_change_aware() >> + else: >> + self.force_reconnect() >> + break >> + except error.Error as e: >> + vlog.err("%s: parse error in received schema: %s" >> + % (self._session.get_name(), e)) >> + if self.cluster_id: >> + self.__error() >> + break >> + else: >> + self.change_seqno = initial_change_seqno >> + self.__send_monitor_request() >> + elif (msg.type == ovs.jsonrpc.Message.T_REPLY >> + and self._db_change_aware_request_id is not None >> + and self._db_change_aware_request_id == msg.id): >> + # Reply to us notifying the server of our change >> awarness. >> + self._db_change_aware_request_id = None >> + elif (msg.type == ovs.jsonrpc.Message.T_REPLY >> and self._lock_request_id is not None >> and self._lock_request_id == msg.id): >> # Reply to our "lock" request. >> @@ -275,10 +362,20 @@ class Idl(object): >> # Reply to our echo request. Ignore it. >> pass >> elif (msg.type == ovs.jsonrpc.Message.T_ERROR and >> - self.state == self.IDL_S_MONITOR_COND_REQUESTED and >> + self.state == self.IDL_S_DATA_MONITOR_COND_REQUESTED >> and >> self._monitor_request_id == msg.id): >> if msg.error == "unknown method": >> self.__send_monitor_request() >> + elif (msg.type == ovs.jsonrpc.Message.T_ERROR and >> + self._server_schema_request_id is not None and >> + self._server_schema_request_id == msg.id): >> + self._server_schema_request_id = None >> + if self.cluster_id: >> + self.force_reconnect() >> + break >> + else: >> + self.change_seqno = initial_change_seqno >> + self.__send_monitor_request() >> elif (msg.type in (ovs.jsonrpc.Message.T_ERROR, >> ovs.jsonrpc.Message.T_REPLY) >> and self.__txn_process_reply(msg)): >> @@ -440,12 +537,19 @@ class Idl(object): >> if not new_has_lock: >> self.is_lock_contended = True >> >> + def __send_db_change_aware(self): >> + msg = ovs.jsonrpc.Message.create_request("set_db_change_aware", >> + [True]) >> + self._db_change_aware_request_id = msg.id >> + self._session.send(msg) >> + >> def __send_monitor_request(self): >> - if self.state == self.IDL_S_INITIAL: >> - self.state = self.IDL_S_MONITOR_COND_REQUESTED >> + if (self.state in [self.IDL_S_SERVER_MONITOR_REQUESTED, >> + self.IDL_S_INITIAL]): >> + self.state = self.IDL_S_DATA_MONITOR_COND_REQUESTED >> method = "monitor_cond" >> else: >> - self.state = self.IDL_S_MONITOR_REQUESTED >> + self.state = self.IDL_S_DATA_MONITOR_REQUESTED >> method = "monitor" >> >> monitor_requests = {} >> @@ -467,20 +571,50 @@ class Idl(object): >> self._monitor_request_id = msg.id >> self._session.send(msg) >> >> - def __parse_update(self, update, version): >> + def __send_server_schema_request(self): >> + self.state = self.IDL_S_SERVER_SCHEMA_REQUESTED >> + msg = ovs.jsonrpc.Message.create_request( >> + "get_schema", [self._server_db_name, str(self.uuid)]) >> + self._server_schema_request_id = msg.id >> + res = self._session.send(msg) >> + >> + def __send_server_monitor_request(self): >> + self.state = self.IDL_S_SERVER_MONITOR_REQUESTED >> + monitor_requests = {} >> + table = self.server_tables[self._server_db_table] >> + columns = [column for column in six.iterkeys(table.columns)] >> + for column in six.itervalues(table.columns): >> + if not hasattr(column, 'alert'): >> + column.alert = True >> + table.rows = custom_index.IndexedRows(table) >> + table.need_table = False >> + table.idl = self >> + monitor_request = {"columns": columns} >> + monitor_requests[table.name] = [monitor_request] >> + msg = ovs.jsonrpc.Message.create_request( >> + 'monitor', [self._server_db.name, >> + str(self.server_monitor_uuid), >> + monitor_requests]) >> + self._server_monitor_request_id = msg.id >> + self._session.send(msg) >> + >> + def __parse_update(self, update, version, tables=None): >> try: >> - self.__do_parse_update(update, version) >> + if not tables: >> + self.__do_parse_update(update, version, self.tables) >> + else: >> + self.__do_parse_update(update, version, tables) >> except error.Error as e: >> vlog.err("%s: error parsing update: %s" >> % (self._session.get_name(), e)) >> >> - def __do_parse_update(self, table_updates, version): >> + def __do_parse_update(self, table_updates, version, tables): >> if not isinstance(table_updates, dict): >> raise error.Error("<table-updates> is not an object", >> table_updates) >> >> for table_name, table_update in six.iteritems(table_updates): >> - table = self.tables.get(table_name) >> + table = tables.get(table_name) >> if not table: >> raise error.Error('<table-updates> includes unknown ' >> 'table "%s"' % table_name) >> @@ -605,6 +739,57 @@ class Idl(object): >> self.notify(op, row, Row.from_json(self, table, uuid, >> old)) >> return changed >> >> + def __check_server_db(self): >> + """Returns True if this is a valid ovsdb server, False >> otherwise.""" >> > The function name seems a bit confusing. > This function returns True if the server has "_Server" table and if it > is a clustered db, additional checks are done. > May be this function can be broken in 2 separate functions ? > One to check if the server supports '_Server' db and other to check > the status of cluster. > > > + session_name = self._session.get_name() >> + >> + if self._server_db_table not in self.server_tables: >> + vlog.info("%s: server does not have %s table in its %s >> database" >> + % (session_name, self._server_db_table, >> self._server_db_name)) >> + return False >> + >> + rows = self.server_tables[self._server_db_table].rows >> + >> + database = None >> + for row in six.itervalues(rows): >> + if self.cluster_id: >> + if self.cluster_id in \ >> + map(lambda x: str(x)[:4], row.cid): >> + database = row >> + break >> + elif row.name == self._db.name: >> + database = row >> + break >> + >> + if not database: >> + vlog.info("%s: server does not have %s database" >> + % (session_name, self._db.name)) >> + return False >> + >> + if (database.model == CLUSTERED and >> + self._session.get_num_of_remotes() > 1): >> + if not database.schema: >> + vlog.info('%s: clustered database server has not yet >> joined ' >> + 'cluster; trying another server' % >> session_name) >> + return False >> + if not database.connected: >> + vlog.info('%s: clustered database server is >> disconnected ' >> + 'from cluster; trying another server' % >> session_name) >> + return False >> + if (self.leader_only and >> + not database.leader): >> + vlog.info('%s: clustered database server is not cluster >> ' >> + 'leader; trying another server' % session_name) >> + return False >> + if database.index: >> + if database.index[0] < self._min_index: >> + vlog.warn('%s: clustered database server has stale >> data; ' >> + 'trying another server' % session_name) >> + return False >> + self._min_index = database.index[0] >> + >> + return True >> + >> def __column_name(self, column): >> if column.type.key.type == ovs.db.types.UuidType: >> return ovs.ovsuuid.to_json(column.type.key.type.default) >> diff --git a/python/ovs/reconnect.py b/python/ovs/reconnect.py >> index 34cc769..afbe445 100644 >> --- a/python/ovs/reconnect.py >> +++ b/python/ovs/reconnect.py >> @@ -344,6 +344,9 @@ class Reconnect(object): >> else: >> self.info_level("%s: error listening for connections" >> % self.name) >> + elif self.state == Reconnect.Reconnect: >> + self.info_level("%s: connection closed by client" >> + % self.name) >> elif self.backoff < self.max_backoff: >> if self.passive: >> type_ = "listen" >> diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at >> index 8981b5e..46b047f 100644 >> --- a/tests/ovsdb-idl.at >> +++ b/tests/ovsdb-idl.at >> @@ -1466,40 +1466,44 @@ OVSDB_CHECK_IDL_NOTIFY([simple idl verify notify], >> "where": [["i", "==", 0]]}]' \ >> 'reconnect']], >> [[000: empty >> -001: >> {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]} >> -002: event:create, row={i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] >> ua=[] uuid=<1>}, updates=None >> -002: event:create, row={i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] >> ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>}, updates=None >> -002: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> >> -002: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<4> <5>] uuid=<0> >> +000: event:create, row={uuid=<0>}, updates=None >> +000: event:create, row={uuid=<1>}, updates=None >> +001: >> {"error":null,"result":[{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]} >> +002: event:create, row={i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] >> ua=[] uuid=<3>}, updates=None >> +002: event:create, row={i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] >> ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates=None >> +002: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> >> +002: i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<6> <7>] uuid=<2> >> 003: {"error":null,"result":[{"count":2}]} >> -004: event:update, row={i=1 r=2 b=false s=mystring u=<3> ia=[1 2 3] >> ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>}, updates={b=true >> uuid=<0>} >> -004: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> >> -004: i=1 r=2 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<4> <5>] uuid=<0> >> +004: event:update, row={i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] >> ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates={b=true >> uuid=<2>} >> +004: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> >> +004: i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<6> <7>] uuid=<2> >> 005: {"error":null,"result":[{"count":2}]} >> -006: event:update, row={i=0 r=123.5 b=false s= u=<2> ia=[] ra=[] ba=[] >> sa=[] ua=[] uuid=<1>}, updates={r=0 uuid=<1>} >> -006: event:update, row={i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] >> ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>}, updates={r=2 >> uuid=<0>} >> -006: i=0 r=123.5 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> >> -006: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<4> <5>] uuid=<0> >> -007: {"error":null,"result":[{"uuid":["uuid","<6>"]}]} >> -008: event:create, row={i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] >> ba=[false] sa=[] ua=[] uuid=<6>}, updates=None >> -008: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] >> uuid=<6> >> -008: i=0 r=123.5 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1> >> -008: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<4> <5>] uuid=<0> >> +006: event:update, row={i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] >> sa=[] ua=[] uuid=<3>}, updates={r=0 uuid=<3>} >> +006: event:update, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] >> ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates={r=2 >> uuid=<2>} >> +006: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> >> +006: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<6> <7>] uuid=<2> >> +007: {"error":null,"result":[{"uuid":["uuid","<8>"]}]} >> +008: event:create, row={i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] >> ba=[false] sa=[] ua=[] uuid=<8>}, updates=None >> +008: i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] >> uuid=<8> >> +008: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3> >> +008: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<6> <7>] uuid=<2> >> 009: {"error":null,"result":[{"count":2}]} >> -010: event:update, row={i=-1 r=125 b=false s=newstring u=<2> ia=[1] >> ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>}, updates={s= uuid=<6>} >> -010: event:update, row={i=0 r=123.5 b=false s=newstring u=<2> ia=[] >> ra=[] ba=[] sa=[] ua=[] uuid=<1>}, updates={s= uuid=<1>} >> -010: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] >> sa=[] ua=[] uuid=<6> >> -010: i=0 r=123.5 b=false s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] >> uuid=<1> >> -010: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<4> <5>] uuid=<0> >> +010: event:update, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] >> ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>}, updates={s= uuid=<8>} >> +010: event:update, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] >> ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates={s= uuid=<3>} >> +010: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] >> sa=[] ua=[] uuid=<8> >> +010: i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] >> uuid=<3> >> +010: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<6> <7>] uuid=<2> >> 011: {"error":null,"result":[{"count":1}]} >> -012: event:delete, row={i=0 r=123.5 b=false s=newstring u=<2> ia=[] >> ra=[] ba=[] sa=[] ua=[] uuid=<1>}, updates=None >> -012: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] >> sa=[] ua=[] uuid=<6> >> -012: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<4> <5>] uuid=<0> >> +012: event:delete, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] >> ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates=None >> +012: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] >> sa=[] ua=[] uuid=<8> >> +012: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<6> <7>] uuid=<2> >> 013: reconnect >> -014: event:create, row={i=-1 r=125 b=false s=newstring u=<2> ia=[1] >> ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>}, updates=None >> -014: event:create, row={i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] >> ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>}, updates=None >> -014: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] >> sa=[] ua=[] uuid=<6> >> -014: i=1 r=123.5 b=false s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<4> <5>] uuid=<0> >> +014: event:create, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] >> ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>}, updates=None >> +014: event:create, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] >> ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates=None >> +014: event:create, row={uuid=<0>}, updates=None >> +014: event:create, row={uuid=<1>}, updates=None >> +014: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] >> sa=[] ua=[] uuid=<8> >> +014: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] >> sa=[abc def] ua=[<6> <7>] uuid=<2> >> 015: done >> ]]) >> >> > I think it would be good if we have few test cases which starts a cluster > of ovsdb-server's and then > -verify if the client has connected to the cluster leader > - bring down the leader and check if the client connects to the new > leader. > > > Thanks > Numan > > -- >> 1.8.3.1 >> >> _______________________________________________ >> dev mailing list >> [email protected] >> https://mail.openvswitch.org/mailman/listinfo/ovs-dev >> > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
