From 38013de3665f0fedf157c6f22b89925a0d0828fe Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 8 Jun 2016 23:50:44 +0100 Subject: [PATCH] Stream image data in load_image() to avoid out-of-memory Reading the entire tar file into memory can result in out-of-memory conditions such as this traceback: Traceback (most recent call last): File "/tmp/ansible_YELTSu/ansible_module_docker_image.py", line 486, in load_image self.client.load_image(image_data) File "/usr/local/lib/python2.7/dist-packages/docker/api/image.py", line 147, in load_image res = self._post(self._url("/images/load"), data=data) ... File "/usr/lib/python2.7/httplib.py", line 997, in endheaders self._send_output(message_body) File "/usr/lib/python2.7/httplib.py", line 848, in _send_output msg += message_body MemoryError Luckily docker-py's load_image(), which calls requests post(), accepts a file-like object instead of a string. Pass in the file object to avoid reading the full file into memory. This allows larger tar files to load succesfully. Signed-off-by: Stefan Hajnoczi --- lib/ansible/modules/cloud/docker/docker_image.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/ansible/modules/cloud/docker/docker_image.py b/lib/ansible/modules/cloud/docker/docker_image.py index 03bcd8a3e7..309d92a328 100644 --- a/lib/ansible/modules/cloud/docker/docker_image.py +++ b/lib/ansible/modules/cloud/docker/docker_image.py @@ -474,19 +474,22 @@ class ImageManager(DockerBaseClass): :return: image dict ''' try: - self.log("Reading image data from %s" % self.load_path) + self.log("Opening image %s" % self.load_path) image_tar = open(self.load_path, 'r') - image_data = image_tar.read() - image_tar.close() except Exception as exc: - self.fail("Error reading image data %s - %s" % (self.load_path, str(exc))) + self.fail("Error opening image %s - %s" % (self.load_path, str(exc))) try: self.log("Loading image from %s" % self.load_path) - self.client.load_image(image_data) + self.client.load_image(image_tar) except Exception as exc: self.fail("Error loading image %s - %s" % (self.name, str(exc))) + try: + image_tar.close() + except Exception as exc: + self.fail("Error closing image %s - %s" % (self.name, str(exc))) + return self.client.find_image(self.name, self.tag)