From 5a28b9409a40890008a3d2bb11c9ca4208da7264 Mon Sep 17 00:00:00 2001
From: Julien Duponchelle <julien@duponchelle.info>
Date: Wed, 6 Jan 2016 14:46:45 +0100
Subject: [PATCH] Fix Crash at startup when docker is not installed

Fix #384
---
 gns3server/modules/docker/__init__.py | 21 +++++++++++++++++----
 gns3server/server.py                  |  3 ---
 tests/modules/docker/test_docker.py   |  5 +++++
 3 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/gns3server/modules/docker/__init__.py b/gns3server/modules/docker/__init__.py
index 56a6f48c..48216050 100644
--- a/gns3server/modules/docker/__init__.py
+++ b/gns3server/modules/docker/__init__.py
@@ -40,12 +40,25 @@ class Docker(BaseManager):
     def __init__(self):
         super().__init__()
         self._server_url = '/var/run/docker.sock'
-        self._connector = aiohttp.connector.UnixConnector(self._server_url)
+        self._connected = False
         # Allow locking during ubridge operations
         self.ubridge_lock = asyncio.Lock()
 
+    @asyncio.coroutine
+    def connector(self):
+        if not self._connected:
+            try:
+                self._connector = aiohttp.connector.UnixConnector(self._server_url)
+                self._connected = True
+                yield from self.query("GET", "info")
+            except (aiohttp.errors.ClientOSError, FileNotFoundError):
+                self._connected = False
+                raise DockerError("Can't connect to docker daemon")
+        return self._connector
+
     def __del__(self):
-        self._connector.close()
+        if self._connected:
+            self._connector.close()
 
     @asyncio.coroutine
     def query(self, method, path, data={}, params={}):
@@ -80,7 +93,7 @@ class Docker(BaseManager):
         response = yield from aiohttp.request(
             method,
             url,
-            connector=self._connector,
+            connector=(yield from self.connector()),
             params=params,
             data=data,
             headers={"content-type": "application/json", },
@@ -107,7 +120,7 @@ class Docker(BaseManager):
 
         url = "http://docker/" + path
         connection = yield from aiohttp.ws_connect(url,
-                                                   connector=self._connector,
+                                                   connector=(yield from self.connector()),
                                                    origin="http://docker",
                                                    autoping=True)
         return connection
diff --git a/gns3server/server.py b/gns3server/server.py
index e543aa46..a0155b2e 100644
--- a/gns3server/server.py
+++ b/gns3server/server.py
@@ -249,9 +249,6 @@ class Server:
         if server_config.getboolean("shell"):
             asyncio.async(self.start_shell())
 
-        from gns3server.modules.docker import Docker
-        asyncio.async(Docker.instance().query("GET", "info"))
-
         try:
             self._loop.run_forever()
         except TypeError as e:
diff --git a/tests/modules/docker/test_docker.py b/tests/modules/docker/test_docker.py
index ad6c0edb..d15d2e64 100644
--- a/tests/modules/docker/test_docker.py
+++ b/tests/modules/docker/test_docker.py
@@ -27,6 +27,7 @@ from gns3server.modules.docker.docker_error import DockerError
 def test_query_success(loop):
 
     vm = Docker()
+    vm._connector = MagicMock()
     response = MagicMock()
     response.status = 200
 
@@ -50,6 +51,8 @@ def test_query_success(loop):
 def test_query_error(loop):
 
     vm = Docker()
+    vm._connected = True
+    vm._connector = MagicMock()
     response = MagicMock()
     response.status = 404
 
@@ -72,6 +75,8 @@ def test_query_error(loop):
 def test_query_error_json(loop):
 
     vm = Docker()
+    vm._connected = True
+    vm._connector = MagicMock()
     response = MagicMock()
     response.status = 404