summaryrefslogtreecommitdiff
path: root/contrib/python/podman/libs/_containers_attach.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/python/podman/libs/_containers_attach.py')
-rw-r--r--contrib/python/podman/libs/_containers_attach.py98
1 files changed, 30 insertions, 68 deletions
diff --git a/contrib/python/podman/libs/_containers_attach.py b/contrib/python/podman/libs/_containers_attach.py
index bd73542b9..df12fa998 100644
--- a/contrib/python/podman/libs/_containers_attach.py
+++ b/contrib/python/podman/libs/_containers_attach.py
@@ -1,16 +1,11 @@
"""Exported method Container.attach()."""
+import collections
import fcntl
-import os
-import select
-import signal
-import socket
+import logging
import struct
import sys
import termios
-import tty
-
-CONMON_BUFSZ = 8192
class Mixin:
@@ -20,10 +15,8 @@ class Mixin:
"""Attach to container's PID1 stdin and stdout.
stderr is ignored.
+ PseudoTTY work is done in start().
"""
- if not self.containerrunning:
- raise Exception('you can only attach to running containers')
-
if stdin is None:
stdin = sys.stdin.fileno()
@@ -41,73 +34,42 @@ class Mixin:
)
# This is the control socket where resizing events are sent to conmon
- ctl_socket = attach['sockets']['control_socket']
+ # attach['sockets']['control_socket']
+ self.pseudo_tty = collections.namedtuple(
+ 'PseudoTTY',
+ ['stdin', 'stdout', 'io_socket', 'control_socket', 'eot'])(
+ stdin,
+ stdout,
+ attach['sockets']['io_socket'],
+ attach['sockets']['control_socket'],
+ eot,
+ )
- def resize_handler(signum, frame):
- """Send the new window size to conmon.
+ @property
+ def resize_handler(self):
+ """Send the new window size to conmon."""
- The method arguments are not used.
- """
- packed = fcntl.ioctl(stdout, termios.TIOCGWINSZ,
+ def wrapped(signum, frame):
+ packed = fcntl.ioctl(self.pseudo_tty.stdout, termios.TIOCGWINSZ,
struct.pack('HHHH', 0, 0, 0, 0))
rows, cols, _, _ = struct.unpack('HHHH', packed)
+ logging.debug('Resize window({}x{}) using {}'.format(
+ rows, cols, self.pseudo_tty.control_socket))
+
# TODO: Need some kind of timeout in case pipe is blocked
- with open(ctl_socket, 'w') as skt:
+ with open(self.pseudo_tty.control_socket, 'w') as skt:
# send conmon window resize message
skt.write('1 {} {}\n'.format(rows, cols))
- def log_handler(signum, frame):
- """Send command to reopen log to conmon.
+ return wrapped
+
+ @property
+ def log_handler(self):
+ """Send command to reopen log to conmon."""
- The method arguments are not used.
- """
- with open(ctl_socket, 'w') as skt:
+ def wrapped(signum, frame):
+ with open(self.pseudo_tty.control_socket, 'w') as skt:
# send conmon reopen log message
skt.write('2\n')
- try:
- # save off the old settings for terminal
- original_attr = termios.tcgetattr(stdout)
- tty.setraw(stdin)
-
- # initialize containers window size
- resize_handler(None, sys._getframe(0))
-
- # catch any resizing events and send the resize info
- # to the control fifo "socket"
- signal.signal(signal.SIGWINCH, resize_handler)
-
- except termios.error:
- original_attr = None
-
- try:
- # TODO: socket.SOCK_SEQPACKET may not be supported in Windows
- with socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) as skt:
- # Prepare socket for communicating with conmon/container
- skt.connect(io_socket)
- skt.sendall(b'\n')
-
- sources = [skt, stdin]
- while sources:
- readable, _, _ = select.select(sources, [], [])
- if skt in readable:
- data = skt.recv(CONMON_BUFSZ)
- if not data:
- sources.remove(skt)
-
- # Remove source marker when writing
- os.write(stdout, data[1:])
-
- if stdin in readable:
- data = os.read(stdin, CONMON_BUFSZ)
- if not data:
- sources.remove(stdin)
-
- skt.sendall(data)
-
- if eot in data:
- sources.clear()
- finally:
- if original_attr:
- termios.tcsetattr(stdout, termios.TCSADRAIN, original_attr)
- signal.signal(signal.SIGWINCH, signal.SIG_DFL)
+ return wrapped