Clean GNS3 close if one remote server is down. Fixes #1357.

pull/1391/head
grossmj 6 years ago
parent e3c8c9d484
commit a54359d243

@ -481,6 +481,18 @@ class Controller:
if compute in project.computes: if compute in project.computes:
yield from project.close() yield from project.close()
def compute_has_open_project(self, compute):
"""
Check is compute has a project opened.
:returns: True if a project is open
"""
for project in self._projects.values():
if compute in project.computes and project.status == "opened":
return True
return False
@asyncio.coroutine @asyncio.coroutine
def delete_compute(self, compute_id): def delete_compute(self, compute_id):
""" """

@ -409,12 +409,16 @@ class Compute:
log.info("Connecting to compute '{}'".format(self._id)) log.info("Connecting to compute '{}'".format(self._id))
response = yield from self._run_http_query("GET", "/capabilities") response = yield from self._run_http_query("GET", "/capabilities")
except ComputeError as e: except ComputeError as e:
# Try to reconnect after 2 seconds if server unavailable only if not during tests (otherwise we create a ressources usage bomb) log.warning("Cannot connect to compute '{}': {}".format(self._id, e))
# Try to reconnect after 2 seconds if server unavailable only if not during tests (otherwise we create a ressource usage bomb)
if not hasattr(sys, "_called_from_test") or not sys._called_from_test: if not hasattr(sys, "_called_from_test") or not sys._called_from_test:
if self.id != "local" and not self._controller.compute_has_open_project(self):
log.info("Not reconnecting to compute '{}' because there is no project opened on it".format(self._id))
return
self._connection_failure += 1 self._connection_failure += 1
# After 5 failure we close the project using the compute to avoid sync issues # After 5 failure we close the project using the compute to avoid sync issues
if self._connection_failure == 5: if self._connection_failure == 10:
log.warning("Cannot connect to compute '{}': {}".format(self._id, e)) log.error("Could not connect to compute '{}' after multiple attempts: {}".format(self._id, e))
yield from self._controller.close_compute_projects(self) yield from self._controller.close_compute_projects(self)
asyncio.get_event_loop().call_later(2, lambda: asyncio_ensure_future(self._try_reconnect())) asyncio.get_event_loop().call_later(2, lambda: asyncio_ensure_future(self._try_reconnect()))
return return
@ -522,11 +526,7 @@ class Compute:
else: else:
data = json.dumps(data).encode("utf-8") data = json.dumps(data).encode("utf-8")
try: try:
log.debug("Attempting request to compute: {method} {url} {headers}".format( log.debug("Attempting request to compute: {method} {url} {headers}".format(method=method, url=url, headers=headers))
method=method,
url=url,
headers=headers
))
response = yield from self._session().request(method, url, headers=headers, data=data, auth=self._auth, chunked=chunked, timeout=timeout) response = yield from self._session().request(method, url, headers=headers, data=data, auth=self._auth, chunked=chunked, timeout=timeout)
except asyncio.TimeoutError: except asyncio.TimeoutError:
raise ComputeError("Timeout error for {} call to {} after {}s".format(method, url, timeout)) raise ComputeError("Timeout error for {} call to {} after {}s".format(method, url, timeout))
@ -633,7 +633,7 @@ class Compute:
else: else:
images = sorted(images, key=itemgetter('image')) images = sorted(images, key=itemgetter('image'))
except OSError as e: except OSError as e:
raise ComputeError("Can't list images: {}".format(str(e))) raise ComputeError("Cannot list images: {}".format(str(e)))
return images return images
@asyncio.coroutine @asyncio.coroutine

@ -146,7 +146,6 @@ class Project:
} }
) )
def reset(self): def reset(self):
""" """
Called when open/close a project. Cleanup internal stuff Called when open/close a project. Cleanup internal stuff
@ -324,7 +323,7 @@ class Project:
@property @property
def auto_close(self): def auto_close(self):
""" """
Should project automaticaly closed when client Should project automatically closed when client
stop listening for notification stop listening for notification
""" """
return self._auto_close return self._auto_close
@ -765,7 +764,6 @@ class Project:
except KeyError: except KeyError:
pass pass
for pict in pictures: for pict in pictures:
os.remove(os.path.join(self.pictures_directory, pict)) os.remove(os.path.join(self.pictures_directory, pict))
except OSError as e: except OSError as e:

Loading…
Cancel
Save