[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