diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py index 688d7a4043b..c853055638d 100644 --- a/lib/ansible/modules/cloud/docker/docker_container.py +++ b/lib/ansible/modules/cloud/docker/docker_container.py @@ -2505,18 +2505,34 @@ class ContainerManager(DockerBaseClass): self.results['changed'] = True response = None if not self.check_mode: - try: - response = self.client.remove_container(container_id, v=volume_state, link=link, force=force) - except NotFound as exc: - pass - except APIError as exc: - if exc.response.status_code == 409 and ('removal of container ' in exc.explanation and - ' is already in progress' in exc.explanation): + count = 0 + while True: + try: + response = self.client.remove_container(container_id, v=volume_state, link=link, force=force) + except NotFound as exc: pass - else: + except APIError as exc: + if 'Unpause the container before stopping or killing' in exc.explanation: + # New docker versions do not allow containers to be removed if they are paused + # Make sure we don't end up in an infinite loop + if count == 3: + self.fail("Error removing container %s (tried to unpause three times): %s" % (container_id, str(exc))) + count += 1 + # Unpause + try: + self.client.unpause(container=container_id) + except Exception as exc2: + self.fail("Error unpausing container %s for removal: %s" % (container_id, str(exc2))) + # Now try again + continue + if 'removal of container ' in exc.explanation and ' is already in progress' in exc.explanation: + pass + else: + self.fail("Error removing container %s: %s" % (container_id, str(exc))) + except Exception as exc: self.fail("Error removing container %s: %s" % (container_id, str(exc))) - except Exception as exc: - self.fail("Error removing container %s: %s" % (container_id, str(exc))) + # We only loop when explicitly requested by 'continue' + break return response def container_update(self, container_id, update_parameters): @@ -2554,13 +2570,32 @@ class ContainerManager(DockerBaseClass): self.results['changed'] = True response = None if not self.check_mode: - try: - if self.parameters.stop_timeout: - response = self.client.stop(container_id, timeout=self.parameters.stop_timeout) - else: - response = self.client.stop(container_id) - except Exception as exc: - self.fail("Error stopping container %s: %s" % (container_id, str(exc))) + count = 0 + while True: + try: + if self.parameters.stop_timeout: + response = self.client.stop(container_id, timeout=self.parameters.stop_timeout) + else: + response = self.client.stop(container_id) + except APIError as exc: + if 'Unpause the container before stopping or killing' in exc.explanation: + # New docker versions do not allow containers to be removed if they are paused + # Make sure we don't end up in an infinite loop + if count == 3: + self.fail("Error removing container %s (tried to unpause three times): %s" % (container_id, str(exc))) + count += 1 + # Unpause + try: + self.client.unpause(container=container_id) + except Exception as exc2: + self.fail("Error unpausing container %s for removal: %s" % (container_id, str(exc2))) + # Now try again + continue + self.fail("Error stopping container %s: %s" % (container_id, str(exc))) + except Exception as exc: + self.fail("Error stopping container %s: %s" % (container_id, str(exc))) + # We only loop when explicitly requested by 'continue' + break return response