From patchwork Tue Jul 10 19:26:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Numan Siddique X-Patchwork-Id: 942166 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41QBz25R0cz9rxs for ; Wed, 11 Jul 2018 05:26:54 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 61A67DC5; Tue, 10 Jul 2018 19:26:50 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 5C384D9E for ; Tue, 10 Jul 2018 19:26:49 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 90D3D76A for ; Tue, 10 Jul 2018 19:26:48 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C1E0A4075798 for ; Tue, 10 Jul 2018 19:26:47 +0000 (UTC) Received: from nusiddiq.redhat (unknown [10.67.116.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4BE47111AF21; Tue, 10 Jul 2018 19:26:44 +0000 (UTC) From: nusiddiq@redhat.com To: dev@openvswitch.org Date: Wed, 11 Jul 2018 00:56:39 +0530 Message-Id: <20180710192639.31368-1-nusiddiq@redhat.com> In-Reply-To: <20180710192616.31277-1-nusiddiq@redhat.com> References: <20180710192616.31277-1-nusiddiq@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 10 Jul 2018 19:26:47 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 10 Jul 2018 19:26:47 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'nusiddiq@redhat.com' RCPT:'' X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 1/2] ovs python: ovs.stream.open_block() returns success even if the remote is unreachable X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Numan Siddique The python function ovs.socket_util.check_connection_completion() uses select() (provided by python) to monitor the socket file descriptor. The select() returns 1 when the file descriptor becomes ready. For error cases like - 111 (Connection refused) and 113 (No route to host) (POLLERR), ovs.poller._SelectSelect.poll() expects the exceptfds list to be set by select(). But that is not the case. As per the select() man page, writefds list will be set for POLLERR. Please see "Correspondence between select() and poll() notifications" section of select(2) man page. Because of this behavior, ovs.socket_util.check_connection_completion() returns success even if the remote is unreachable or not listening on the port. This patch fixes this issue by adding a wrapper function - check_connection_completion_status() which calls sock.connect_ex() to get the status of the connection if ovs.socket_util.check_connection_completion() returns success. The test cases added fails without the fix in this patch. Signed-off-by: Numan Siddique --- python/ovs/socket_util.py | 34 ++++++++++++++++++++++++++++++++++ python/ovs/stream.py | 16 +++++++++++++--- tests/automake.mk | 1 + tests/ovsdb-idl.at | 16 ++++++++++++++++ tests/test-stream.py | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 tests/test-stream.py diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py index 403104936..91f4532ea 100644 --- a/python/ovs/socket_util.py +++ b/python/ovs/socket_util.py @@ -256,6 +256,40 @@ def inet_open_active(style, target, default_port, dscp): return get_exception_errno(e), None +def check_connection_completion_status(sock, target, default_port): + status = check_connection_completion(sock) + if status: + return status + + try: + address = inet_parse_active(target, default_port) + except ValueError: + # It's not a valid tcp target. + return status + + # For tcp connections, check_connection_completion function returns 0 + # when the select for the socket fd signals. But it doesn't really + # verify the connection was established or not. So call connect again on + # the socket to get the status. + try: + err = sock.connect_ex(address) + except socket.error as e: + err = get_exception_errno(e) + if sys.platform == 'win32' and error == errno.WSAEWOULDBLOCK: + # WSAEWOULDBLOCK would be the equivalent on Windows + # for EINPROGRESS on Unix. + err = err.EINPROGRESS + + if err == errno.EINPROGRESS or err == errno.EALREADY: + return errno.EINPROGRESS + + if err == 0 or err == errno.EISCONN: + return 0 + + sock.close() + return err + + def get_exception_errno(e): """A lot of methods on Python socket objects raise socket.error, but that exception is documented as having two completely different forms of diff --git a/python/ovs/stream.py b/python/ovs/stream.py index 5996497a5..7d5227469 100644 --- a/python/ovs/stream.py +++ b/python/ovs/stream.py @@ -119,6 +119,7 @@ class Stream(object): bInitialState=False) self.name = name + self.suffix = name.split(":", 1)[1] if status == errno.EAGAIN: self.state = Stream.__S_CONNECTING elif status == 0: @@ -191,8 +192,16 @@ class Stream(object): if error: return error, None else: - status = ovs.socket_util.check_connection_completion(sock) - return 0, cls(sock, name, status) + err = ovs.socket_util.check_connection_completion_status( + sock, suffix, 0) + if err == errno.EAGAIN or err == errno.EINPROGRESS: + status = errno.EAGAIN + err = 0 + elif err == 0: + status = 0 + else: + status = err + return err, cls(sock, name, status) @staticmethod def _open(suffix, dscp): @@ -246,7 +255,8 @@ class Stream(object): def __scs_connecting(self): if self.socket is not None: - retval = ovs.socket_util.check_connection_completion(self.socket) + retval = ovs.socket_util.check_connection_completion_status( + self.socket, self.suffix, 0) assert retval != errno.EINPROGRESS elif sys.platform == 'win32': if self.retry_connect: diff --git a/tests/automake.mk b/tests/automake.mk index 8224e5a4a..0abf29d47 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -421,6 +421,7 @@ CHECK_PYFILES = \ tests/test-l7.py \ tests/test-ovsdb.py \ tests/test-reconnect.py \ + tests/test-stream.py \ tests/MockXenAPI.py \ tests/test-unix-socket.py \ tests/test-unixctl.py \ diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at index 58935faf3..d4d283db4 100644 --- a/tests/ovsdb-idl.at +++ b/tests/ovsdb-idl.at @@ -1720,3 +1720,19 @@ OVSDB_CHECK_IDL_COMPOUND_INDEX_WITH_REF([set, simple3 idl-compound-index-with-re 007: check simple4: empty 008: End test ]]) + +m4_define([CHECK_STREAM_OPEN_BLOCK_PY], + [AT_SETUP([$1]) + AT_SKIP_IF([test $2 = no]) + AT_KEYWORDS([Check PY Stream open block - $3]) + AT_CHECK([ovsdb_start_idltest "ptcp:0:127.0.0.1"]) + PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT]) + WRONG_PORT=$(($TCP_PORT+1)) + AT_CHECK([$3 $srcdir/test-stream.py tcp:127.0.0.1:$TCP_PORT], [0], [ignore]) + AT_CHECK([$3 $srcdir/test-stream.py tcp:127.0.0.1:$WRONG_PORT], [1], [ignore]) + OVSDB_SERVER_SHUTDOWN + AT_CHECK([$3 $srcdir/test-stream.py tcp:127.0.0.1:$TCP_PORT], [1], [ignore]) + AT_CLEANUP]) + +CHECK_STREAM_OPEN_BLOCK_PY([Check PY2 Stream open block], [$HAVE_PYTHON], [$PYTHON]) +CHECK_STREAM_OPEN_BLOCK_PY([Check PY3 Stream open block], [$HAVE_PYTHON], [$PYTHON3]) diff --git a/tests/test-stream.py b/tests/test-stream.py new file mode 100644 index 000000000..4a5117501 --- /dev/null +++ b/tests/test-stream.py @@ -0,0 +1,32 @@ +# Copyright (c) 2018, Red Hat Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys + +import ovs.stream + + +def main(argv): + remote = argv[1] + err, stream = ovs.stream.Stream.open_block( + ovs.stream.Stream.open(remote)) + + if err or stream is None: + sys.exit(1) + + sys.exit(0) + + +if __name__ == '__main__': + main(sys.argv) From patchwork Tue Jul 10 19:27:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Numan Siddique X-Patchwork-Id: 942167 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41QBzj3GT6z9rxs for ; Wed, 11 Jul 2018 05:27:29 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 525E3EF5; Tue, 10 Jul 2018 19:27:11 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 5EC4AEE0 for ; Tue, 10 Jul 2018 19:27:10 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 6CB376BA for ; Tue, 10 Jul 2018 19:27:09 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B1AEA40363A8 for ; Tue, 10 Jul 2018 19:27:08 +0000 (UTC) Received: from nusiddiq.redhat (unknown [10.67.116.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id 313392166BA2; Tue, 10 Jul 2018 19:27:05 +0000 (UTC) From: nusiddiq@redhat.com To: dev@openvswitch.org Date: Wed, 11 Jul 2018 00:57:00 +0530 Message-Id: <20180710192700.31440-1-nusiddiq@redhat.com> In-Reply-To: <20180710192616.31277-1-nusiddiq@redhat.com> References: <20180710192616.31277-1-nusiddiq@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Tue, 10 Jul 2018 19:27:08 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Tue, 10 Jul 2018 19:27:08 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'nusiddiq@redhat.com' RCPT:'' X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 2/2] python jsonrpc: Allow jsonrpc_session to have more than one remote. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Numan Siddique 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 --- python/ovs/db/idl.py | 20 +++++++++++++++- python/ovs/jsonrpc.py | 39 ++++++++++++++++++++++++------- tests/ovsdb-idl.at | 54 +++++++++++++++++++++++++++++++++++++++++++ tests/test-ovsdb.py | 13 ++++++++--- 4 files changed, 114 insertions(+), 12 deletions(-) diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py index 64eb1a886..d5bd21535 100644 --- a/python/ovs/db/idl.py +++ b/python/ovs/db/idl.py @@ -101,6 +101,9 @@ class Idl(object): ovs.jsonrpc.session.open(). The connection will maintain an in-memory replica of the remote database. + 'remote' can be comma separated multiple remotes and each remote + should be in a form acceptable to ovs.jsonrpc.session.open(). + 'schema_helper' should be an instance of the SchemaHelper class which generates schema for the remote database. The caller may have cut it down by removing tables or columns that are not of interest. The IDL @@ -127,7 +130,8 @@ class Idl(object): self.tables = schema.tables self.readonly = schema.readonly self._db = schema - self._session = ovs.jsonrpc.Session.open(remote, + remotes = self._parse_remotes(remote) + self._session = ovs.jsonrpc.Session.open_multiple(remotes, probe_interval=probe_interval) self._monitor_request_id = None self._last_seqno = None @@ -155,6 +159,20 @@ class Idl(object): table.condition = [True] table.cond_changed = False + def _parse_remotes(self, remote): + # If remote is - + # "tcp:10.0.0.1:6641,unix:/tmp/db.sock,t,s,tcp:10.0.0.2:6642" + # this function returns + # ["tcp:10.0.0.1:6641", "unix:/tmp/db.sock,t,s", tcp:10.0.0.2:6642"] + remotes = [] + for r in remote.split(','): + r_length = len(remotes) + if r.find(":") == -1 and r_length: + remotes[r_length - 1] = remotes[r_length - 1] + "," + r + else: + remotes.append(r) + return remotes + def index_create(self, table, name): """Create a named multi-column index on a table""" return self.tables[table].rows.index_create(name) diff --git a/python/ovs/jsonrpc.py b/python/ovs/jsonrpc.py index 7c24e574a..4873cff98 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,38 @@ 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], 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 +464,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 +508,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 +518,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 +603,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/tests/ovsdb-idl.at b/tests/ovsdb-idl.at index d4d283db4..d5787c5d2 100644 --- a/tests/ovsdb-idl.at +++ b/tests/ovsdb-idl.at @@ -106,6 +106,32 @@ 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 + m4_if([$2], [], [], + [AT_CHECK([ovsdb-client transact tcp:127.0.0.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_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 +158,32 @@ 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]) + 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 +230,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..ed5d21b0c 100644 --- a/tests/test-ovsdb.py +++ b/tests/test-ovsdb.py @@ -595,9 +595,16 @@ def do_idl(schema_file, remote, *commands): 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 + 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)