From 477091207d52e5f036712a4413bdb725d416da86 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Fri, 11 Nov 2016 10:38:59 +0100 Subject: [PATCH] Better handle compute unavailable errors Fix #775 --- gns3server/controller/__init__.py | 4 ++-- gns3server/controller/compute.py | 7 +++++-- gns3server/controller/node.py | 4 ++-- gns3server/controller/project.py | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index 602571c2..d275795b 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -24,7 +24,7 @@ import aiohttp from ..config import Config from .project import Project -from .compute import Compute +from .compute import Compute, ComputeError from .notification import Notification from .symbols import Symbols from ..version import __version__ @@ -84,7 +84,7 @@ class Controller: try: yield from compute.close() # We don't care if a compute is down at this step - except (aiohttp.errors.ClientOSError, aiohttp.web_exceptions.HTTPError, OSError): + except (ComputeError, aiohttp.web_exceptions.HTTPError, OSError): pass yield from self.gns3vm.exit_vm() self._computes = {} diff --git a/gns3server/controller/compute.py b/gns3server/controller/compute.py index 16baa7d9..77c77d3d 100644 --- a/gns3server/controller/compute.py +++ b/gns3server/controller/compute.py @@ -362,7 +362,7 @@ class Compute: if not self._connected and not self._closed: try: response = yield from self._run_http_query("GET", "/capabilities") - except (aiohttp.errors.ClientOSError, aiohttp.errors.ClientRequestError, aiohttp.ClientResponseError): + except ComputeError: # Try to reconnect after 2 seconds if server unavailable only if not during tests (otherwise we create a ressources usage bomb) if not hasattr(sys, "_called_from_test") or not sys._called_from_test: asyncio.get_event_loop().call_later(2, lambda: asyncio.async(self.connect())) @@ -465,7 +465,10 @@ class Compute: data = send_data(data) else: data = json.dumps(data) - response = yield from self._session().request(method, url, headers=headers, data=data, auth=self._auth, chunked=chunked, timeout=timeout) + try: + response = yield from self._session().request(method, url, headers=headers, data=data, auth=self._auth, chunked=chunked, timeout=timeout) + except (aiohttp.errors.ClientOSError, aiohttp.errors.ClientRequestError, aiohttp.ClientResponseError) as e: + raise ComputeError(str(e)) body = yield from response.read() if body and not raw: body = body.decode() diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py index 8aff659c..a7dd6de1 100644 --- a/gns3server/controller/node.py +++ b/gns3server/controller/node.py @@ -22,7 +22,7 @@ import uuid import os -from .compute import ComputeConflict +from .compute import ComputeConflict, ComputeError from .ports.port_factory import PortFactory, StandardPortFactory, DynamipsPortFactory from ..utils.images import images_directories from ..utils.qt import qt_font_to_style @@ -399,7 +399,7 @@ class Node: try: yield from self.post("/stop", timeout=240) # We don't care if a node is down at this step - except (aiohttp.errors.ClientOSError, aiohttp.errors.ClientHttpProcessingError, aiohttp.web.HTTPError): + except (ComputeError, aiohttp.errors.ClientHttpProcessingError, aiohttp.web.HTTPError): pass except asyncio.TimeoutError: raise aiohttp.web.HTTPRequestTimeout(text="Timeout when stopping {}".format(self._name)) diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index 872295f6..e994ab30 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -27,6 +27,7 @@ import tempfile from uuid import UUID, uuid4 from .node import Node +from .compute import ComputeError from .snapshot import Snapshot from .drawing import Drawing from .topology import project_to_topology, load_topology @@ -541,7 +542,7 @@ class Project: try: yield from compute.post("/projects/{}/close".format(self._id)) # We don't care if a compute is down at this step - except (aiohttp.errors.ClientOSError, aiohttp.web.HTTPError, aiohttp.ClientResponseError, TimeoutError): + except (ComputeError, aiohttp.web.HTTPError, aiohttp.ClientResponseError, TimeoutError): pass self._cleanPictures() self._status = "closed" @@ -646,7 +647,7 @@ class Project: try: yield from compute.post("/projects/{}/close".format(self._id)) # We don't care if a compute is down at this step - except (aiohttp.errors.ClientOSError, aiohttp.web.HTTPNotFound, aiohttp.web.HTTPConflict): + except (ComputeError, aiohttp.web.HTTPNotFound, aiohttp.web.HTTPConflict): pass shutil.copy(path + ".backup", path) self._status = "closed"