mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-13 20:08:55 +00:00
parent
78c154e376
commit
34f5a6f82c
@ -46,31 +46,43 @@ class Docker(BaseManager):
|
||||
self._connected = False
|
||||
# Allow locking during ubridge operations
|
||||
self.ubridge_lock = asyncio.Lock()
|
||||
self._version_checked = False
|
||||
self._session = None
|
||||
self._connector = None
|
||||
|
||||
@asyncio.coroutine
|
||||
def connector(self):
|
||||
if not self._connected or self._connector.closed:
|
||||
if not sys.platform.startswith("linux"):
|
||||
raise DockerError("Docker is supported only on Linux")
|
||||
|
||||
def session(self):
|
||||
if not self._connected or self._session.closed:
|
||||
try:
|
||||
self._connector = aiohttp.connector.UnixConnector(self._server_url, conn_timeout=2)
|
||||
self._connected = True
|
||||
connector = self.connector()
|
||||
self._session = aiohttp.ClientSession(connector=connector)
|
||||
version = yield from self.query("GET", "version")
|
||||
except (aiohttp.errors.ClientOSError, FileNotFoundError):
|
||||
self._connected = False
|
||||
raise DockerError("Can't connect to docker daemon")
|
||||
|
||||
if parse_version(version["ApiVersion"]) < parse_version(DOCKER_MINIMUM_API_VERSION):
|
||||
raise DockerError("Docker API version is {}. GNS3 requires a minimum API version of {}".format(version["ApiVersion"], DOCKER_MINIMUM_API_VERSION))
|
||||
return self._session
|
||||
|
||||
def connector(self):
|
||||
if self._connector is None or self._connector.closed:
|
||||
if not sys.platform.startswith("linux"):
|
||||
raise DockerError("Docker is supported only on Linux")
|
||||
try:
|
||||
self._connector = aiohttp.connector.UnixConnector(self._server_url, conn_timeout=2)
|
||||
except (aiohttp.errors.ClientOSError, FileNotFoundError):
|
||||
raise DockerError("Can't connect to docker daemon")
|
||||
return self._connector
|
||||
|
||||
@asyncio.coroutine
|
||||
def unload(self):
|
||||
yield from super().unload()
|
||||
if self._connected:
|
||||
self._connector.close()
|
||||
if self._session and not self._session.closed:
|
||||
yield from self._session.close()
|
||||
if self._connector and not self._connector.closed:
|
||||
yield from self._connector.close()
|
||||
|
||||
@asyncio.coroutine
|
||||
def query(self, method, path, data={}, params={}):
|
||||
@ -108,9 +120,8 @@ class Docker(BaseManager):
|
||||
data = json.dumps(data)
|
||||
url = "http://docker/" + path
|
||||
try:
|
||||
if self._session is None or self._session.closed is True:
|
||||
self._session = aiohttp.ClientSession(connector=(yield from self.connector()))
|
||||
response = yield from self._session.request(
|
||||
session = yield from self.session()
|
||||
response = yield from session.request(
|
||||
method,
|
||||
url,
|
||||
params=params,
|
||||
@ -147,7 +158,7 @@ class Docker(BaseManager):
|
||||
|
||||
url = "http://docker/" + path
|
||||
connection = yield from aiohttp.ws_connect(url,
|
||||
connector=(yield from self.connector()),
|
||||
connector=self.connector(),
|
||||
origin="http://docker",
|
||||
autoping=True)
|
||||
return connection
|
||||
|
@ -19,7 +19,7 @@ import pytest
|
||||
import asyncio
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from tests.utils import asyncio_patch
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
from gns3server.compute.docker import Docker
|
||||
from gns3server.compute.docker.docker_error import DockerError
|
||||
|
||||
@ -28,6 +28,8 @@ from gns3server.compute.docker.docker_error import DockerError
|
||||
def vm():
|
||||
vm = Docker()
|
||||
vm._connected = True
|
||||
vm._session = MagicMock()
|
||||
vm._session.closed = False
|
||||
return vm
|
||||
|
||||
|
||||
@ -42,14 +44,14 @@ def test_query_success(loop, vm):
|
||||
return b'{"c": false}'
|
||||
|
||||
response.read.side_effect = read
|
||||
with asyncio_patch("aiohttp.client.ClientSession.request", return_value=response) as mock:
|
||||
data = loop.run_until_complete(asyncio.async(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
mock.assert_called_with('POST',
|
||||
'http://docker/test',
|
||||
data='{"a": true}',
|
||||
headers={'content-type': 'application/json'},
|
||||
params={'b': 1},
|
||||
timeout=300)
|
||||
vm._session.request = AsyncioMagicMock(return_value=response)
|
||||
data = loop.run_until_complete(asyncio.async(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
vm._session.request.assert_called_with('POST',
|
||||
'http://docker/test',
|
||||
data='{"a": true}',
|
||||
headers={'content-type': 'application/json'},
|
||||
params={'b': 1},
|
||||
timeout=300)
|
||||
|
||||
assert data == {"c": False}
|
||||
|
||||
@ -64,15 +66,15 @@ def test_query_error(loop, vm):
|
||||
return b"NOT FOUND"
|
||||
|
||||
response.read.side_effect = read
|
||||
with asyncio_patch("aiohttp.client.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(DockerError):
|
||||
data = loop.run_until_complete(asyncio.async(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
mock.assert_called_with('POST',
|
||||
'http://docker/test',
|
||||
data='{"a": true}',
|
||||
headers={'content-type': 'application/json'},
|
||||
params={'b': 1},
|
||||
timeout=300)
|
||||
vm._session.request = AsyncioMagicMock(return_value=response)
|
||||
with pytest.raises(DockerError):
|
||||
data = loop.run_until_complete(asyncio.async(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
vm._session.request.assert_called_with('POST',
|
||||
'http://docker/test',
|
||||
data='{"a": true}',
|
||||
headers={'content-type': 'application/json'},
|
||||
params={'b': 1},
|
||||
timeout=300)
|
||||
|
||||
|
||||
def test_query_error_json(loop, vm):
|
||||
@ -85,15 +87,15 @@ def test_query_error_json(loop, vm):
|
||||
return b'{"message": "Error"}'
|
||||
|
||||
response.read.side_effect = read
|
||||
with asyncio_patch("aiohttp.client.ClientSession.request", return_value=response) as mock:
|
||||
with pytest.raises(DockerError):
|
||||
data = loop.run_until_complete(asyncio.async(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
mock.assert_called_with('POST',
|
||||
'http://docker/test',
|
||||
data='{"a": true}',
|
||||
headers={'content-type': 'application/json'},
|
||||
params={'b': 1},
|
||||
timeout=300)
|
||||
vm._session.request = AsyncioMagicMock(return_value=response)
|
||||
with pytest.raises(DockerError):
|
||||
data = loop.run_until_complete(asyncio.async(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
vm._session.request.assert_called_with('POST',
|
||||
'http://docker/test',
|
||||
data='{"a": true}',
|
||||
headers={'content-type': 'application/json'},
|
||||
params={'b': 1},
|
||||
timeout=300)
|
||||
|
||||
|
||||
def test_list_images(loop):
|
||||
|
Loading…
Reference in New Issue
Block a user