[lxc-devel] [pylxd/master] Fix the ws4py connection handling for container execution

rockstar on Github lxc-bot at linuxcontainers.org
Tue Oct 25 02:41:27 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 921 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20161025/e2b8521a/attachment.bin>
-------------- next part --------------
From e72bf605af95d7233f70ba8b996c298d20ea19d1 Mon Sep 17 00:00:00 2001
From: Paul Hummer <paul.hummer at canonical.com>
Date: Mon, 24 Oct 2016 20:35:16 -0600
Subject: [PATCH] Fix the ws4py connection handling for container execution

This branch does a number of things. First, it simplifies _StdinWebsocket,
as we don't need most of what existed there. It closes immediately
after connection (and the command doesn't execute unless stdin is
also connected).

_CommandWebsocketClient learned how to pre-emptively close a connection.
We were previously waiting for the command to time out, which is why
the execute call was taking so long. This fixes #182.

The while loop that waits for the commands to complete had too long of
a delay, and had too much logic for whether the loop should continue
to wait. That while loop was also simplified.
---
 pylxd/models/container.py | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/pylxd/models/container.py b/pylxd/models/container.py
index 6f82ca2..6c1fdb5 100644
--- a/pylxd/models/container.py
+++ b/pylxd/models/container.py
@@ -207,7 +207,7 @@ def execute(self, commands, environment={}):
 
         manager = WebSocketManager()
 
-        stdin = _StdinWebsocket(manager, self.client.websocket_url)
+        stdin = _StdinWebsocket(self.client.websocket_url)
         stdin.resource = '{}?secret={}'.format(parsed.path, fds['0'])
         stdin.connect()
         stdout = _CommandWebsocketClient(manager, self.client.websocket_url)
@@ -219,13 +219,8 @@ def execute(self, commands, environment={}):
 
         manager.start()
 
-        while True:  # pragma: no cover
-            for websocket in manager.websockets.values():
-                if not websocket.terminated:
-                    break
-            else:
-                break
-            time.sleep(1)
+        while len(manager.websockets.values()) > 0:
+            time.sleep(.1)
 
         return stdout.data, stderr.data
 
@@ -310,25 +305,31 @@ def handshake_ok(self):
         self.buffer = []
 
     def received_message(self, message):
+        if len(message.data) == 0:
+            self.close()
+            self.manager.remove(self)
         if message.encoding:
             self.buffer.append(message.data.decode(message.encoding))
         else:
             self.buffer.append(message.data.decode('utf-8'))
 
+    def closed(self, code, reason=None):
+        print("Connection closed with code {} and reason {}".format(code, reason))
+
     @property
     def data(self):
         return ''.join(self.buffer)
 
 
 class _StdinWebsocket(WebSocketBaseClient):  # pragma: no cover
-    """A websocket client for handling stdin."""
+    """A websocket client for handling stdin.
 
-    def __init__(self, manager, *args, **kwargs):
-        self.manager = manager
-        super(_StdinWebsocket, self).__init__(*args, **kwargs)
+    The nature of stdin in Container.execute means that we don't
+    ever use this connection. It is closed as soon as it completes
+    the handshake.
+    """
 
     def handshake_ok(self):
-        self.manager.add(self)
         self.close()
 
 


More information about the lxc-devel mailing list