From: Numan Siddique <[email protected]> Python IDL implementation doesn't have the support to connect to the cluster dbs. This patch adds this support. We are still missing the support in python idl class to connect to the cluster master. That support will be added in an upcoming patch.
This patch is similar to the commit 8cf6bbb184 which added multiple remote support in the C jsonrpc implementation. Signed-off-by: Numan Siddique <[email protected]> --- python/ovs/jsonrpc.py | 40 +++++++++++++++++++++++------ python/ovs/stream.py | 2 ++ tests/ovsdb-idl.at | 59 +++++++++++++++++++++++++++++++++++++++++++ tests/test-ovsdb.py | 22 +++++++++++++--- 4 files changed, 111 insertions(+), 12 deletions(-) diff --git a/python/ovs/jsonrpc.py b/python/ovs/jsonrpc.py index 7c24e574a..154083766 100644 --- a/python/ovs/jsonrpc.py +++ b/python/ovs/jsonrpc.py @@ -14,6 +14,7 @@ import codecs import errno import os +import random import sys import ovs.json @@ -368,12 +369,17 @@ class Connection(object): class Session(object): """A JSON-RPC session with reconnection.""" - def __init__(self, reconnect, rpc): + def __init__(self, reconnect, rpc, remotes): self.reconnect = reconnect self.rpc = rpc self.stream = None self.pstream = None self.seqno = 0 + if type(remotes) != list: + remotes = [remotes] + self.remotes = remotes + random.shuffle(self.remotes) + self.next_remote = 0 @staticmethod def open(name, probe_interval=None): @@ -393,28 +399,39 @@ class Session(object): 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. """ + return Session.open_multiple(name.split(','), + probe_interval=probe_interval) + + @staticmethod + def open_multiple(remotes, probe_interval=None): reconnect = ovs.reconnect.Reconnect(ovs.timeval.msec()) - reconnect.set_name(name) + session = Session(reconnect, None, remotes) + session.pick_remote() reconnect.enable(ovs.timeval.msec()) - - if ovs.stream.PassiveStream.is_valid_name(name): + reconnect.set_backoff_free_tries(len(remotes)) + if ovs.stream.PassiveStream.is_valid_name(reconnect.get_name()): reconnect.set_passive(True, ovs.timeval.msec()) - if not ovs.stream.stream_or_pstream_needs_probes(name): + if not ovs.stream.stream_or_pstream_needs_probes(reconnect.get_name()): reconnect.set_probe_interval(0) elif probe_interval is not None: reconnect.set_probe_interval(probe_interval) - return Session(reconnect, None) + return session @staticmethod def open_unreliably(jsonrpc): reconnect = ovs.reconnect.Reconnect(ovs.timeval.msec()) + session = Session(reconnect, None, [jsonrpc.name]) reconnect.set_quiet(True) - reconnect.set_name(jsonrpc.name) + session.pick_remote() reconnect.set_max_tries(0) reconnect.connected(ovs.timeval.msec()) - return Session(reconnect, jsonrpc) + return session + + def pick_remote(self): + self.reconnect.set_name(self.remotes[self.next_remote]) + self.next_remote = (self.next_remote + 1) % len(self.remotes) def close(self): if self.rpc is not None: @@ -448,6 +465,8 @@ class Session(object): self.reconnect.connecting(ovs.timeval.msec()) else: self.reconnect.connect_failed(ovs.timeval.msec(), error) + self.stream = None + self.pick_remote() elif self.pstream is None: error, self.pstream = ovs.stream.PassiveStream.open(name) if not error: @@ -490,6 +509,7 @@ class Session(object): if error != 0: self.reconnect.disconnected(ovs.timeval.msec(), error) self.__disconnect() + self.pick_remote() elif self.stream is not None: self.stream.run() error = self.stream.connect() @@ -499,6 +519,7 @@ class Session(object): self.stream = None elif error != errno.EAGAIN: self.reconnect.connect_failed(ovs.timeval.msec(), error) + self.pick_remote() self.stream.close() self.stream = None @@ -583,3 +604,6 @@ class Session(object): def force_reconnect(self): self.reconnect.force_reconnect(ovs.timeval.msec()) + + def get_num_of_remotes(self): + return len(self.remotes) diff --git a/python/ovs/stream.py b/python/ovs/stream.py index 7d5227469..94c3ffd1b 100644 --- a/python/ovs/stream.py +++ b/python/ovs/stream.py @@ -22,6 +22,8 @@ import ovs.socket_util import ovs.vlog import six +import datetime + try: from OpenSSL import SSL diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at index d4d283db4..294b7e25c 100644 --- a/tests/ovsdb-idl.at +++ b/tests/ovsdb-idl.at @@ -106,6 +106,36 @@ m4_define([OVSDB_CHECK_IDL_TCP_PY], OVSDB_CHECK_IDL_TCP_PYN([$1 - Python3], [$2], [$3], [$4], [$5], [$6], [$HAVE_PYTHON3], [$PYTHON3])]) +# same as OVSDB_CHECK_IDL but uses the Python IDL implementation with tcp +# with multiple remotes with only one remote reachable +m4_define([OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PYN], + [AT_SETUP([$1 - tcp]) + AT_SKIP_IF([test $7 = no]) + AT_KEYWORDS([ovsdb server idl positive Python with tcp socket $5]) + AT_CHECK([ovsdb_start_idltest "ptcp:0:127.0.0.1"]) + PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT]) + WRONG_PORT_1=$((TCP_PORT + 1)) + WRONG_PORT_2=$((TCP_PORT + 2)) + remote=tcp:127.0.0.1:$WRONG_PORT_1,tcp:127.0.0.1:$TCP_PORT,tcp:127.0.0.1:$WRONG_PORT_2 + #remote=tcp:127.0.0.1:$TCP_PORT + m4_if([$2], [], [], + [AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT $2], [0], [ignore], [ignore])]) + echo "Hi dude .. calling test-ovsdbpy" + AT_CHECK([$8 $srcdir/test-ovsdb.py -t10 idl $srcdir/idltest.ovsschema $remote $3], + [0], [stdout], [ignore]) + echo "test-ovsdb returned.. checking " + AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]), + [0], [$4]) + echo "shutting down server" + OVSDB_SERVER_SHUTDOWN + AT_CLEANUP]) + +m4_define([OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PY], + [OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PYN([$1 - Python2 (multiple remotes)], [$2], [$3], [$4], [$5], [$6], + [$HAVE_PYTHON], [$PYTHON]) + OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PYN([$1 - Python3 (multiple remotes)], [$2], [$3], [$4], [$5], [$6], + [$HAVE_PYTHON3], [$PYTHON3])]) + # same as OVSDB_CHECK_IDL but uses the Python IDL implementation with tcp6 m4_define([OVSDB_CHECK_IDL_TCP6_PYN], [AT_SETUP([$1 - tcp6]) @@ -132,6 +162,33 @@ m4_define([OVSDB_CHECK_IDL_TCP6_PY], OVSDB_CHECK_IDL_TCP6_PYN([$1 - Python3], [$2], [$3], [$4], [$5], [$6], [$HAVE_PYTHON3], [$PYTHON3])]) +m4_define([OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PYN], + [AT_SETUP([$1 - tcp6]) + AT_SKIP_IF([test $7 = no]) + AT_SKIP_IF([test "$IS_WIN32" = "yes"]) + AT_SKIP_IF([test $HAVE_IPV6 = no]) + AT_KEYWORDS([ovsdb server idl positive Python with tcp6 socket $5]) + AT_CHECK([ovsdb_start_idltest "ptcp:0:[[::1]]"]) + PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT]) + echo "TCP_PORT=$TCP_PORT" + WRONG_PORT_1=$((TCP_PORT + 1)) + WRONG_PORT_2=$((TCP_PORT + 2)) + remote="tcp:[[::1]]:$WRONG_PORT_1,tcp:[[::1]]:$TCP_PORT,tcp:[[::1]]:$WRONG_PORT_2" + m4_if([$2], [], [], + [AT_CHECK([ovsdb-client transact "tcp:[[::1]]:$TCP_PORT" $2], [0], [ignore], [ignore])]) + AT_CHECK([$8 $srcdir/test-ovsdb.py -t10 idl $srcdir/idltest.ovsschema $remote $3], + [0], [stdout], [ignore]) + AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]), + [0], [$4]) + OVSDB_SERVER_SHUTDOWN + AT_CLEANUP]) + +m4_define([OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PY], + [OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PYN([$1 - Python2 (multiple remotes)], [$2], [$3], [$4], [$5], [$6], + [$HAVE_PYTHON], [$PYTHON]) + OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PYN([$1 - Python3 (multiple remotes)], [$2], [$3], [$4], [$5], [$6], + [$HAVE_PYTHON3], [$PYTHON3])]) + # same as OVSDB_CHECK_IDL but uses the Python IDL implementation with SSL m4_define([OVSDB_CHECK_IDL_SSL_PYN], [AT_SETUP([$1 - SSL]) @@ -178,7 +235,9 @@ m4_define([OVSDB_CHECK_IDL], OVSDB_CHECK_IDL_PY($@) OVSDB_CHECK_IDL_REGISTER_COLUMNS_PY($@) OVSDB_CHECK_IDL_TCP_PY($@) + OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PY($@) OVSDB_CHECK_IDL_TCP6_PY($@) + OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PY($@) OVSDB_CHECK_IDL_SSL_PY($@)]) # This test uses the Python IDL implementation with passive tcp diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py index ec6035447..a2d34505d 100644 --- a/tests/test-ovsdb.py +++ b/tests/test-ovsdb.py @@ -17,6 +17,7 @@ from __future__ import print_function import getopt import os import re +import socket import sys import uuid @@ -25,6 +26,7 @@ import ovs.db.schema import ovs.db.types import ovs.ovsuuid import ovs.poller +import ovs.socket_util import ovs.stream import ovs.util from ovs.db import data @@ -252,6 +254,7 @@ def print_idl(idl, step): if not n: print("%03d: empty" % step) + sys.stdout.flush() @@ -553,7 +556,6 @@ def update_condition(idl, commands): table = command[0] cond = ovs.json.from_string(command[1]) - idl.cond_change(table, cond) @@ -594,10 +596,20 @@ def do_idl(schema_file, remote, *commands): if "simple3" in idl.tables: idl.index_create("simple3", "simple3_by_name") + if commands: - error, stream = ovs.stream.Stream.open_block( - ovs.stream.Stream.open(remote)) - if error: + remotes = remote.split(',') + stream = None + remote_to_connect = None + stream = None + for r in remotes: + error, stream = ovs.stream.Stream.open_block( + ovs.stream.Stream.open(r)) + if not error and stream: + break + stream = None + + if not stream: sys.stderr.write("failed to connect to \"%s\"" % remote) sys.exit(1) rpc = ovs.jsonrpc.Connection(stream) @@ -691,10 +703,12 @@ def do_idl(schema_file, remote, *commands): if rpc: rpc.close() + while idl.change_seqno == seqno and not idl.run(): poller = ovs.poller.Poller() idl.wait(poller) poller.block() + print_idl(idl, step) step += 1 idl.close() -- 2.17.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
