diff --git a/zun/common/exception.py b/zun/common/exception.py index 90c950be3..5f664d43b 100644 --- a/zun/common/exception.py +++ b/zun/common/exception.py @@ -345,3 +345,7 @@ class ContainerRunningException(ZunException): message = _("The container %(id)s is running." "Please stop and delete the container.") code = 409 + + +class DockerError(ZunException): + message = _("Docker internal error: %(error_msg)s.") diff --git a/zun/compute/manager.py b/zun/compute/manager.py index 53ec1aa18..6e0ec9f98 100644 --- a/zun/compute/manager.py +++ b/zun/compute/manager.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import six + from oslo_log import log as logging from zun.common import exception @@ -32,6 +34,11 @@ class Manager(object): super(Manager, self).__init__() self.driver = driver.load_container_driver(container_driver) + def _fail_container(self, container): + container.status = fields.ContainerStatus.ERROR + container.task_state = None + container.save() + def container_create(self, context, container): utils.spawn_n(self._do_container_create, context, container) @@ -43,21 +50,26 @@ class Manager(object): container.save() try: self.driver.pull_image(container.image) + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + self._fail_container(container) + return except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) - container.status = fields.ContainerStatus.ERROR - container.task_state = None - container.save() + self._fail_container(container) return container.task_state = fields.TaskState.CONTAINER_CREATING container.save() try: container = self.driver.create(container) + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + container.status = fields.ContainerStatus.ERROR except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) - if not isinstance(e, exception.ZunException): - e = exception.ZunException("Unexpected Error: %s" % str(e)) container.status = fields.ContainerStatus.ERROR finally: container.task_state = None @@ -70,6 +82,10 @@ class Manager(object): try: self.driver.delete(container) return container + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) if e.response.status_code == 409: @@ -82,6 +98,10 @@ class Manager(object): LOG.debug('Listing container...', context=context) try: return self.driver.list() + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) raise e @@ -94,6 +114,10 @@ class Manager(object): container = self.driver.show(container) container.save() return container + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) raise e @@ -106,6 +130,10 @@ class Manager(object): container = self.driver.reboot(container) container.save() return container + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) raise e @@ -118,6 +146,10 @@ class Manager(object): container = self.driver.stop(container) container.save() return container + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) raise e @@ -130,6 +162,10 @@ class Manager(object): container = self.driver.start(container) container.save() return container + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) raise e @@ -142,6 +178,10 @@ class Manager(object): container = self.driver.pause(container) container.save() return container + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s,"), str(e)) raise e @@ -154,6 +194,10 @@ class Manager(object): container = self.driver.unpause(container) container.save() return container + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) raise e @@ -164,6 +208,10 @@ class Manager(object): container=container) try: return self.driver.show_logs(container) + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) raise e @@ -175,6 +223,10 @@ class Manager(object): container=container) try: return self.driver.execute(container, command) + except exception.DockerError as e: + LOG.error(_LE("Error occured while calling docker API: %s"), + six.text_type(e)) + raise e except Exception as e: LOG.exception(_LE("Unexpected exception: %s"), str(e)) raise e diff --git a/zun/container/docker/driver.py b/zun/container/docker/driver.py index 12cb23111..b13139581 100644 --- a/zun/container/docker/driver.py +++ b/zun/container/docker/driver.py @@ -17,6 +17,7 @@ import six from oslo_config import cfg from oslo_log import log as logging +from zun.common import exception from zun.common.utils import check_container_id from zun.container.docker import utils as docker_utils from zun.container import driver @@ -37,7 +38,10 @@ class DockerDriver(driver.ContainerDriver): with docker_utils.docker_client() as docker: LOG.debug('Pulling image %s' % image) image_repo, image_tag = docker_utils.parse_docker_image(image) - docker.pull(image_repo, tag=image_tag) + try: + docker.pull(image_repo, tag=image_tag) + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) def create(self, container): with docker_utils.docker_client() as docker: @@ -63,18 +67,24 @@ class DockerDriver(driver.ContainerDriver): except errors.APIError as e: container.status = fields.ContainerStatus.ERROR container.status_reason = six.text_type(e) - raise + raise exception.DockerError(error_msg=six.text_type(e)) container.save() return container def delete(self, container): with docker_utils.docker_client() as docker: - if container.container_id: - docker.remove_container(container.container_id) + try: + if container.container_id: + docker.remove_container(container.container_id) + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) def list(self): with docker_utils.docker_client() as docker: - return docker.list_instances() + try: + return docker.list_instances() + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) def show(self, container): with docker_utils.docker_client() as docker: @@ -88,7 +98,7 @@ class DockerDriver(driver.ContainerDriver): if '404' in str(api_error): container.status = fields.ContainerStatus.ERROR return container - raise + raise exception.DockerError(error_msg=six.text_type(api_error)) status = result.get('State') if status: @@ -105,54 +115,76 @@ class DockerDriver(driver.ContainerDriver): @check_container_id def reboot(self, container): with docker_utils.docker_client() as docker: - docker.restart(container.container_id) - container.status = fields.ContainerStatus.RUNNING - return container + try: + docker.restart(container.container_id) + container.status = fields.ContainerStatus.RUNNING + return container + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) @check_container_id def stop(self, container): with docker_utils.docker_client() as docker: - docker.stop(container.container_id) - container.status = fields.ContainerStatus.STOPPED - return container + try: + docker.stop(container.container_id) + container.status = fields.ContainerStatus.STOPPED + return container + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) @check_container_id def start(self, container): with docker_utils.docker_client() as docker: - docker.start(container.container_id) - container.status = fields.ContainerStatus.RUNNING - return container + try: + docker.start(container.container_id) + container.status = fields.ContainerStatus.RUNNING + return container + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) @check_container_id def pause(self, container): with docker_utils.docker_client() as docker: - docker.pause(container.container_id) - container.status = fields.ContainerStatus.PAUSED - return container + try: + docker.pause(container.container_id) + container.status = fields.ContainerStatus.PAUSED + return container + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) @check_container_id def unpause(self, container): with docker_utils.docker_client() as docker: - docker.unpause(container.container_id) - container.status = fields.ContainerStatus.RUNNING - return container + try: + docker.unpause(container.container_id) + container.status = fields.ContainerStatus.RUNNING + return container + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) @check_container_id def show_logs(self, container): with docker_utils.docker_client() as docker: - return docker.get_container_logs(container.container_id) + try: + return docker.get_container_logs(container.container_id) + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) @check_container_id def execute(self, container, command): with docker_utils.docker_client() as docker: - if docker_utils.is_docker_library_version_atleast('1.2.0'): - create_res = docker.exec_create( - container.container_id, command, True, True, False) - exec_output = docker.exec_start(create_res, False, False, - False) - else: - exec_output = docker.execute(container.container_id, command) - return exec_output + try: + if docker_utils.is_docker_library_version_atleast('1.2.0'): + create_res = docker.exec_create( + container.container_id, command, True, True, False) + exec_output = docker.exec_start(create_res, False, False, + False) + else: + exec_output = docker.execute( + container.container_id, command) + return exec_output + except errors.APIError as e: + raise exception.DockerError(error_msg=six.text_type(e)) def _encode_utf8(self, value): if six.PY2 and not isinstance(value, unicode):