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