[lxc-devel] [pylxd/master] Interactive Execute on Container

felix-engelmann on Github lxc-bot at linuxcontainers.org
Sat Dec 15 14:54:02 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 637 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20181215/86b7ddf0/attachment.bin>
-------------- next part --------------
From 817cdfb99d9c86cca54d69a9f951a3b492ae0c79 Mon Sep 17 00:00:00 2001
From: Felix Engelmann <fe-github at nlogn.org>
Date: Fri, 14 Dec 2018 13:48:13 +0100
Subject: [PATCH 1/3] Added interactive execute on container to connect with WS

Signed-off-by: Felix Engelmann <fe-github at nlogn.org>
---
 pylxd/models/container.py | 40 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/pylxd/models/container.py b/pylxd/models/container.py
index 354c8967..7abbc273 100644
--- a/pylxd/models/container.py
+++ b/pylxd/models/container.py
@@ -437,6 +437,46 @@ def execute(
             return _ContainerExecuteResult(
                 operation.metadata['return'], stdout.data, stderr.data)
 
+    def interactive_execute(
+            self, commands, environment=None
+    ):
+        """Execute a command on the container interactively and return websocket.
+
+        In pylxd 2.2, this method will be renamed `execute` and the existing
+        `execute` method removed.
+
+        :param commands: The command and arguments as a list of strings (most likely a shell)
+        :type commands: [str]
+        :param environment: The environment variables to pass with the command
+        :type environment: {str: str}
+        :returns: A link to an interactive websocket and a control socket
+        :rtype: dict
+        """
+        if not _ws4py_installed:
+            raise ValueError(
+                'This feature requires the optional ws4py library.')
+        if isinstance(commands, six.string_types):
+            raise TypeError("First argument must be a list.")
+
+        if environment is None:
+            environment = {}
+
+        response = self.api['exec'].post(json={
+            'command': commands,
+            'environment': environment,
+            'wait-for-websocket': True,
+            'interactive': True,
+        })
+
+        fds = response.json()['metadata']['metadata']['fds']
+        operation_id = response.json()['operation']\
+            .split('/')[-1].split('?')[0]
+        parsed = parse.urlparse(
+            self.client.api.operations[operation_id].websocket._api_endpoint)
+
+        return {'ws': '{}?secret={}'.format(parsed.path, fds['0']),
+                'control': '{}?secret={}'.format(parsed.path, fds['control']),}
+
     def migrate(self, new_client, wait=False):
         """Migrate a container.
 

From 244d3f6bc4e1ed69a0f8c0a18d3c12c2037f618d Mon Sep 17 00:00:00 2001
From: Felix Engelmann <fe-github at nlogn.org>
Date: Sat, 15 Dec 2018 15:43:29 +0100
Subject: [PATCH 2/3] Cleanup of interactive_execute

Signed-off-by: Felix Engelmann <fe-github at nlogn.org>
---
 doc/source/containers.rst |  2 ++
 pylxd/models/container.py | 14 ++++++--------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/doc/source/containers.rst b/doc/source/containers.rst
index 864855ea..336ecf2b 100644
--- a/doc/source/containers.rst
+++ b/doc/source/containers.rst
@@ -64,6 +64,8 @@ Container methods
     a list, in the form of `subprocess.Popen` with each item of the command
     as a separate item in the list. Returns a tuple of `(exit_code, stdout, stderr)`.
     This method will block while the command is executed.
+  - `interactive_execute` - Execute a command on the container. It will return
+    an interactive websocket and the execution only starts after a client connected to the websocket.
   - `migrate` - Migrate the container. The first argument is a client
     connection to the destination server. This call is asynchronous, so
     `wait=True` is optional. The container on the new client is returned.
diff --git a/pylxd/models/container.py b/pylxd/models/container.py
index 7abbc273..e33e3c23 100644
--- a/pylxd/models/container.py
+++ b/pylxd/models/container.py
@@ -440,17 +440,15 @@ def execute(
     def interactive_execute(
             self, commands, environment=None
     ):
-        """Execute a command on the container interactively and return websocket.
+        """Execute a command on the container interactively and returns websockets.
 
-        In pylxd 2.2, this method will be renamed `execute` and the existing
-        `execute` method removed.
-
-        :param commands: The command and arguments as a list of strings (most likely a shell)
+        :param commands: The command and arguments as a list of strings
+           (most likely a shell)
         :type commands: [str]
         :param environment: The environment variables to pass with the command
         :type environment: {str: str}
-        :returns: A link to an interactive websocket and a control socket
-        :rtype: dict
+        :returns: Two urls to an interactive websocket and a control socket
+        :rtype: {'ws':str,'control':str}
         """
         if not _ws4py_installed:
             raise ValueError(
@@ -475,7 +473,7 @@ def interactive_execute(
             self.client.api.operations[operation_id].websocket._api_endpoint)
 
         return {'ws': '{}?secret={}'.format(parsed.path, fds['0']),
-                'control': '{}?secret={}'.format(parsed.path, fds['control']),}
+                'control': '{}?secret={}'.format(parsed.path, fds['control'])}
 
     def migrate(self, new_client, wait=False):
         """Migrate a container.

From 1e2444ac2bd29dd864660130fbb2079c71dd43b5 Mon Sep 17 00:00:00 2001
From: Felix Engelmann <fe-github at nlogn.org>
Date: Sat, 15 Dec 2018 15:50:19 +0100
Subject: [PATCH 3/3] Added testcase for interactive execute

Signed-off-by: Felix Engelmann <fe-github at nlogn.org>
---
 pylxd/tests/models/test_container.py | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/pylxd/tests/models/test_container.py b/pylxd/tests/models/test_container.py
index c71097d1..10b88b08 100644
--- a/pylxd/tests/models/test_container.py
+++ b/pylxd/tests/models/test_container.py
@@ -236,6 +236,14 @@ def test_execute_string(self):
 
         self.assertRaises(TypeError, an_container.execute, 'apt-get update')
 
+    def test_interactive_execute(self):
+        an_container = models.Container(self.client, name='an-container')
+
+        result = an_container.interactive_execute(['/bin/bash'])
+
+        self.assertEqual(result['ws'],'/1.0/operations/operation-abc/websocket?secret=abc')
+        self.assertEqual(result['control'],'/1.0/operations/operation-abc/websocket?secret=jkl')
+
     def test_migrate(self):
         """A container is migrated."""
         from pylxd.client import Client


More information about the lxc-devel mailing list