diff --git a/zun/compute/manager.py b/zun/compute/manager.py index 8cafa5156..dc3d4eeb5 100644 --- a/zun/compute/manager.py +++ b/zun/compute/manager.py @@ -924,8 +924,8 @@ class Manager(periodic_task.PeriodicTasks): except Exception as e: LOG.exception("Unexpected exception while uploading image: %s", six.text_type(e)) - self.driver.delete_image(context, snapshot_image.id, - 'glance') + self.driver.delete_committed_image(context, snapshot_image.id, + glance.GlanceDriver()) self.driver.delete_image(context, container_image_id, 'docker') raise @@ -952,8 +952,8 @@ class Manager(periodic_task.PeriodicTasks): except exception.DockerError as e: LOG.error("Error occurred while calling docker commit API: %s", six.text_type(e)) - self.driver.delete_image(context, snapshot_image.id, - 'glance') + self.driver.delete_committed_image(context, snapshot_image.id, + glance.GlanceDriver()) raise finally: if unpause: @@ -975,8 +975,8 @@ class Manager(periodic_task.PeriodicTasks): LOG.debug('Deleting image...') # TODO(hongbin): Let caller pass down image_driver instead of using # CONF.default_image_driver - self.driver.delete_image(context, image.image_id, - CONF.default_image_driver) + if image.image_id: + self.driver.delete_image(context, image.image_id) image.destroy(context, image.uuid) def image_pull(self, context, image): diff --git a/zun/container/docker/driver.py b/zun/container/docker/driver.py index fc0159033..e9fe9af50 100644 --- a/zun/container/docker/driver.py +++ b/zun/container/docker/driver.py @@ -141,6 +141,7 @@ class DockerDriver(driver.ContainerDriver): return docker.get_image(name) def delete_image(self, context, img_id, image_driver=None): + image = self.inspect_image(img_id)['RepoTags'][0] if image_driver: image_driver_list = [image_driver.lower()] else: @@ -148,11 +149,24 @@ class DockerDriver(driver.ContainerDriver): for driver_name in image_driver_list: try: image_driver = img_driver.load_image_driver(driver_name) - image_driver.delete_image(context, img_id) + if driver_name == 'glance': + image_driver.delete_image_tar(context, image) + elif driver_name == 'docker': + image_driver.delete_image(context, img_id) except exception.ZunException: LOG.exception('Unknown exception occurred while deleting ' 'image %s', img_id) + def delete_committed_image(self, context, img_id, image_driver): + try: + image_driver.delete_committed_image(context, img_id) + except Exception as e: + LOG.exception('Unknown exception occurred while' + 'deleting image %s: %s', + img_id, + six.text_type(e)) + raise exception.ZunException(six.text_type(e)) + def images(self, repo, quiet=False): with docker_utils.docker_client() as docker: return docker.images(repo, quiet) diff --git a/zun/container/driver.py b/zun/container/driver.py index ea19ce0dc..a6607615b 100644 --- a/zun/container/driver.py +++ b/zun/container/driver.py @@ -286,5 +286,8 @@ class ContainerDriver(object): image_driver): raise NotImplementedError() - def delete_image(context, img_id, **kwargs): + def delete_committed_image(self, context, img_id, image_driver): + raise NotImplementedError() + + def delete_image(self, context, img_id, image_driver): raise NotImplementedError() diff --git a/zun/image/driver.py b/zun/image/driver.py index b87501404..ddece18eb 100644 --- a/zun/image/driver.py +++ b/zun/image/driver.py @@ -85,3 +85,11 @@ class ContainerImageDriver(object): def delete_image(self, context, img_id): """Delete an image.""" raise NotImplementedError() + + def delete_committed_image(self, context, img_id, image_driver): + """Delete a committed image.""" + raise NotImplementedError() + + def delete_image_tar(self, context, image): + """Delete an image.""" + raise NotImplementedError() diff --git a/zun/image/glance/driver.py b/zun/image/glance/driver.py index 7c6010910..85135c95c 100644 --- a/zun/image/glance/driver.py +++ b/zun/image/glance/driver.py @@ -156,9 +156,9 @@ class GlanceDriver(driver.ContainerImageDriver): except Exception as e: raise exception.ZunException(six.text_type(e)) - def delete_image(self, context, img_id): - """Delete an image.""" - LOG.debug('Delete an image %s in glance', img_id) + def delete_committed_image(self, context, img_id): + """Delete a committed image.""" + LOG.debug('Delete the committed image %s in glance', img_id) try: return utils.delete_image(context, img_id) except Exception as e: @@ -167,3 +167,17 @@ class GlanceDriver(driver.ContainerImageDriver): img_id, six.text_type(e)) raise exception.ZunException(six.text_type(e)) + + def delete_image_tar(self, context, image): + """Delete image tar file that pull from glance""" + repo = image.split(':')[0] + tag = image.split(':')[1] + image = self._search_image_on_host(context, repo, tag) + if image: + if self._verify_md5sum_for_image(image): + tarfile = image.get('path') + try: + os.unlink(tarfile) + except Exception as e: + LOG.exception('Cannot delete tar file %s', tarfile) + raise exception.ZunException(six.text_type(e)) diff --git a/zun/tests/unit/compute/test_compute_manager.py b/zun/tests/unit/compute/test_compute_manager.py index ae519c87c..7990e505f 100644 --- a/zun/tests/unit/compute/test_compute_manager.py +++ b/zun/tests/unit/compute/test_compute_manager.py @@ -1210,7 +1210,7 @@ class TestManager(base.TestCase): @mock.patch.object(ContainerActionEvent, 'event_start') @mock.patch.object(ContainerActionEvent, 'event_finish') - @mock.patch.object(fake_driver, 'delete_image') + @mock.patch.object(fake_driver, 'delete_committed_image') @mock.patch.object(fake_driver, 'commit') @mock.patch.object(fake_driver, 'pause') @mock.patch.object(fake_driver, 'unpause') diff --git a/zun/tests/unit/container/docker/test_docker_driver.py b/zun/tests/unit/container/docker/test_docker_driver.py index 0ade4b94a..d6ed9ac35 100644 --- a/zun/tests/unit/container/docker/test_docker_driver.py +++ b/zun/tests/unit/container/docker/test_docker_driver.py @@ -72,11 +72,14 @@ class TestDockerDriver(base.DriverTestCase): self.driver.get_image(name='image_name') self.mock_docker.get_image.assert_called_once_with('image_name') - def test_delete_image(self): - self.mock_docker.remove_image = mock.Mock() - mock_image = mock.MagicMock() - self.driver.delete_image(self.context, mock_image) - self.mock_docker.remove_image.assert_called_once_with(mock_image) + @mock.patch('zun.image.glance.driver.GlanceDriver.delete_image_tar') + def test_delete_image(self, mock_delete_image): + self.mock_docker.inspect_image = mock.Mock( + return_value={'RepoTags': ['ubuntu:1']}) + img_id = '1234' + self.driver.delete_image(self.context, img_id, 'glance') + self.mock_docker.inspect_image.assert_called_once_with(img_id) + self.assertTrue(mock_delete_image.called) def test_load_image(self): self.mock_docker.load_image = mock.Mock() diff --git a/zun/tests/unit/image/glance/test_driver.py b/zun/tests/unit/image/glance/test_driver.py index 5a2643cd9..b213842aa 100644 --- a/zun/tests/unit/image/glance/test_driver.py +++ b/zun/tests/unit/image/glance/test_driver.py @@ -155,10 +155,10 @@ class TestDriver(base.BaseTestCase): self.assertTrue(mock_update_image.called) @mock.patch('zun.image.glance.utils.delete_image') - def test_delete_image(self, mock_delete_image): + def test_delete_committed_image(self, mock_delete_image): image_meta = mock.MagicMock() image_meta.id = '1234' mock_delete_image.return_value = [image_meta] - ret = self.driver.delete_image(None, 'id') + ret = self.driver.delete_committed_image(None, 'id') self.assertEqual(1, len(ret)) self.assertTrue(mock_delete_image.called)