@@ -14,6 +14,7 @@
import errno
import os
+import sys
import six
@@ -274,6 +275,8 @@ class Connection(object):
except UnicodeError:
error = errno.EILSEQ
if error:
+ if sys.platform == "win32" and error == errno.WSAEWOULDBLOCK:
+ error = errno.EAGAIN
if error == errno.EAGAIN:
return error, None
else:
@@ -17,6 +17,7 @@ import os
import os.path
import random
import socket
+import sys
import six
from six.moves import range
@@ -53,6 +54,23 @@ def free_short_name(short_name):
link_name = os.path.dirname(short_name)
ovs.fatal_signal.unlink_file_now(link_name)
+def compat_read_unix_socket(path):
+ try:
+ file_handle = open(path, "r+")
+ except IOError as e:
+ vlog.warn("%s: open: %s" % (path, e.strerror))
+ raise socket.error(errno.ENOENT)
+
+ return int(file_handle.readline())
+
+def compat_write_unix_socket(path, port):
+ try:
+ file_handle = open(path, "w")
+ except IOError as e:
+ vlog.warn("%s: open: %s" % (path, e.strerror))
+ raise socket.error(errno.ENOENT)
+
+ file_handle.write(str(port))
def make_unix_socket(style, nonblock, bind_path, connect_path, short=False):
"""Creates a Unix domain socket in the given 'style' (either
@@ -65,7 +83,10 @@ def make_unix_socket(style, nonblock, bind_path, connect_path, short=False):
None."""
try:
- sock = socket.socket(socket.AF_UNIX, style)
+ if sys.platform == "win32":
+ sock = socket.socket(socket.AF_INET, style)
+ else:
+ sock = socket.socket(socket.AF_UNIX, style)
except socket.error as e:
return get_exception_errno(e), None
@@ -81,17 +102,28 @@ def make_unix_socket(style, nonblock, bind_path, connect_path, short=False):
return e.errno, None
ovs.fatal_signal.add_file_to_unlink(bind_path)
- sock.bind(bind_path)
+ if sys.platform == "win32":
+ sock.bind(("127.0.0.1", 0))
+ compat_write_unix_socket(bind_path, sock.getsockname()[1])
+ else:
+ sock.bind(bind_path)
- try:
- os.fchmod(sock.fileno(), 0o700)
- except OSError as e:
- pass
+ try:
+ os.fchmod(sock.fileno(), 0o700)
+ except OSError as e:
+ pass
if connect_path is not None:
try:
- sock.connect(connect_path)
+ if sys.platform == "win32":
+ port = compat_read_unix_socket(connect_path)
+ sock.connect(("127.0.0.1", port))
+ else:
+ sock.connect(connect_path)
except socket.error as e:
- if get_exception_errno(e) != errno.EINPROGRESS:
+ error = get_exception_errno(e)
+ if sys.platform == "win32" and error == errno.WSAEWOULDBLOCK:
+ error = errno.EINPROGRESS
+ if error != errno.EINPROGRESS:
raise
return 0, sock
except socket.error as e:
@@ -15,7 +15,7 @@
import errno
import os
import socket
-
+import sys
import six
import ovs.poller
@@ -136,6 +136,8 @@ class Stream(object):
if not error:
while True:
error = stream.connect()
+ if sys.platform == "win32" and error == errno.WSAEWOULDBLOCK:
+ error = errno.EAGAIN
if error != errno.EAGAIN:
break
stream.run()
@@ -338,7 +340,7 @@ class PassiveStream(object):
try:
sock, addr = self.socket.accept()
ovs.socket_util.set_nonblocking(sock)
- if (sock.family == socket.AF_UNIX):
+ if (sys.platform != "win32") and (sock.family == socket.AF_UNIX):
return 0, Stream(sock, "unix:%s" % addr, 0)
return 0, Stream(sock, 'ptcp:%s:%s' % (addr[0],
str(addr[1])), 0)
@@ -15,6 +15,7 @@
import copy
import errno
import os
+import sys
import six
from six.moves import range
@@ -147,6 +148,8 @@ class UnixctlServer(object):
def run(self):
for _ in range(10):
error, stream = self._listener.accept()
+ if sys.platform == "win32" and error == errno.WSAEWOULDBLOCK:
+ error = errno.EAGAIN
if not error:
rpc = ovs.jsonrpc.Connection(stream)
self._conns.append(UnixctlConnection(rpc))
@@ -154,8 +157,8 @@ class UnixctlServer(object):
break
else:
# XXX: rate-limit
- vlog.warn("%s: accept failed: %s" % (self._listener.name,
- os.strerror(error)))
+ vlog.warn("%s: accept failed: %s %d %d" % (self._listener.name,
+ os.strerror(error), error))
for conn in copy.copy(self._conns):
error = conn.run()
@@ -188,8 +191,12 @@ class UnixctlServer(object):
if path is not None:
path = "punix:%s" % ovs.util.abs_file_name(ovs.dirs.RUNDIR, path)
else:
- path = "punix:%s/%s.%d.ctl" % (ovs.dirs.RUNDIR,
- ovs.util.PROGRAM_NAME, os.getpid())
+ if sys.platform == "win32":
+ path = "punix:%s/%s.ctl" % (ovs.dirs.RUNDIR,
+ ovs.util.PROGRAM_NAME)
+ else:
+ path = "punix:%s/%s.%d.ctl" % (ovs.dirs.RUNDIR,
+ ovs.util.PROGRAM_NAME, os.getpid())
if version is None:
version = ovs.version.VERSION
AF_UNIX sockets are not supported on Windows. Instead of an AF_UNIX socket use localhost tcp connections to communicate between components. This makes the python sockets compatible with the ones used in Windows applications. In case the socket returns WSAEWOULDBLOCK, it is replaced by EAGAIN error in order to be compatible with Windows. Signed-off-by: Paul-Daniel Boca <pboca@cloudbasesolutions.com> --- python/ovs/jsonrpc.py | 3 +++ python/ovs/socket_util.py | 48 ++++++++++++++++++++++++++++++++++++-------- python/ovs/stream.py | 6 ++++-- python/ovs/unixctl/server.py | 15 ++++++++++---- 4 files changed, 58 insertions(+), 14 deletions(-)