Fix failed mounts in podman connector and handle errors (#57741)

Like it's described in issue #57740 ansible podman fails to run
because of failed mount of rootless container.
pull/57500/head
Sergey 5 years ago committed by ansibot
parent 0d2ffdd5a6
commit 7910361b52

@ -0,0 +1,2 @@
bugfixes:
- ansible-podman connection plugin - Fix case when mount of podman container fails and files can't be copied to/from container. Also add error handling in case of failed podman commands. (https://github.com/ansible/ansible/issues/57740)

@ -14,6 +14,7 @@ import shlex
import shutil import shutil
import subprocess import subprocess
from ansible.errors import AnsibleError
from ansible.module_utils._text import to_bytes, to_native from ansible.module_utils._text import to_bytes, to_native
from ansible.plugins.connection import ConnectionBase, ensure_connect from ansible.plugins.connection import ConnectionBase, ensure_connect
from ansible.utils.display import Display from ansible.utils.display import Display
@ -68,7 +69,7 @@ class Connection(ConnectionBase):
self._mount_point = None self._mount_point = None
self.user = self._play_context.remote_user self.user = self._play_context.remote_user
def _podman(self, cmd, cmd_args=None, in_data=None): def _podman(self, cmd, cmd_args=None, in_data=None, use_container_id=True):
""" """
run podman executable run podman executable
@ -77,7 +78,9 @@ class Connection(ConnectionBase):
:param in_data: data passed to podman's stdin :param in_data: data passed to podman's stdin
:return: return code, stdout, stderr :return: return code, stdout, stderr
""" """
local_cmd = ['podman', cmd, self._container_id] local_cmd = ['podman', cmd]
if use_container_id:
local_cmd.append(self._container_id)
if cmd_args: if cmd_args:
local_cmd += cmd_args local_cmd += cmd_args
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd] local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
@ -87,6 +90,9 @@ class Connection(ConnectionBase):
stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate(input=in_data) stdout, stderr = p.communicate(input=in_data)
display.vvvvv("STDOUT %s" % stdout)
display.vvvvv("STDERR %s" % stderr)
display.vvvvv("RC CODE %s" % p.returncode)
stdout = to_bytes(stdout, errors='surrogate_or_strict') stdout = to_bytes(stdout, errors='surrogate_or_strict')
stderr = to_bytes(stderr, errors='surrogate_or_strict') stderr = to_bytes(stderr, errors='surrogate_or_strict')
return p.returncode, stdout, stderr return p.returncode, stdout, stderr
@ -98,8 +104,11 @@ class Connection(ConnectionBase):
""" """
super(Connection, self)._connect() super(Connection, self)._connect()
rc, self._mount_point, stderr = self._podman("mount") rc, self._mount_point, stderr = self._podman("mount")
self._mount_point = self._mount_point.strip() if rc != 0:
display.vvvvv("MOUNTPOINT %s RC %s STDERR %r" % (self._mount_point, rc, stderr)) display.v("Failed to mount container %s: %s" % (self._container_id, stderr.strip()))
else:
self._mount_point = self._mount_point.strip()
display.vvvvv("MOUNTPOINT %s RC %s STDERR %r" % (self._mount_point, rc, stderr))
self._connected = True self._connected = True
@ensure_connect @ensure_connect
@ -121,23 +130,35 @@ class Connection(ConnectionBase):
""" Place a local file located in 'in_path' inside container at 'out_path' """ """ Place a local file located in 'in_path' inside container at 'out_path' """
super(Connection, self).put_file(in_path, out_path) super(Connection, self).put_file(in_path, out_path)
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._container_id) display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._container_id)
if not self._mount_point:
real_out_path = self._mount_point + to_bytes(out_path, errors='surrogate_or_strict') rc, stdout, stderr = self._podman(
shutil.copyfile( "cp", [in_path, self._container_id + ":" + out_path], use_container_id=False)
to_bytes(in_path, errors='surrogate_or_strict'), if rc != 0:
to_bytes(real_out_path, errors='surrogate_or_strict') raise AnsibleError("Failed to copy file from %s to %s in container %s\n%s" % (
) in_path, out_path, self._container_id, stderr))
else:
real_out_path = self._mount_point + to_bytes(out_path, errors='surrogate_or_strict')
shutil.copyfile(
to_bytes(in_path, errors='surrogate_or_strict'),
to_bytes(real_out_path, errors='surrogate_or_strict')
)
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
""" obtain file specified via 'in_path' from the container and place it at 'out_path' """ """ obtain file specified via 'in_path' from the container and place it at 'out_path' """
super(Connection, self).fetch_file(in_path, out_path) super(Connection, self).fetch_file(in_path, out_path)
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._container_id) display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._container_id)
if not self._mount_point:
real_in_path = self._mount_point + to_bytes(in_path, errors='surrogate_or_strict') rc, stdout, stderr = self._podman(
shutil.copyfile( "cp", [self._container_id + ":" + in_path, out_path], use_container_id=False)
to_bytes(real_in_path, errors='surrogate_or_strict'), if rc != 0:
to_bytes(out_path, errors='surrogate_or_strict') raise AnsibleError("Failed to fetch file from %s to %s from container %s\n%s" % (
) in_path, out_path, self._container_id, stderr))
else:
real_in_path = self._mount_point + to_bytes(in_path, errors='surrogate_or_strict')
shutil.copyfile(
to_bytes(real_in_path, errors='surrogate_or_strict'),
to_bytes(out_path, errors='surrogate_or_strict')
)
def close(self): def close(self):
""" unmount container's filesystem """ """ unmount container's filesystem """

Loading…
Cancel
Save