mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 17:28:08 +00:00
parent
a581eeba54
commit
1532b3ed9b
@ -25,6 +25,7 @@ import psutil
|
||||
import shlex
|
||||
import aiohttp
|
||||
import json
|
||||
import os
|
||||
|
||||
from ...ubridge.hypervisor import Hypervisor
|
||||
from .docker_error import *
|
||||
@ -84,7 +85,8 @@ class DockerVM(BaseVM):
|
||||
"adapters": self.adapters,
|
||||
"console": self.console,
|
||||
"start_command": self.start_command,
|
||||
"environment": self.environment
|
||||
"environment": self.environment,
|
||||
"vm_directory": self.working_dir
|
||||
}
|
||||
|
||||
@property
|
||||
@ -118,9 +120,31 @@ class DockerVM(BaseVM):
|
||||
return "running"
|
||||
return "exited"
|
||||
|
||||
@asyncio.coroutine
|
||||
def _get_image_informations(self):
|
||||
"""
|
||||
:returns: Dictionnary informations about the container image
|
||||
"""
|
||||
result = yield from self.manager.query("GET", "images/{}/json".format(self._image))
|
||||
return result
|
||||
|
||||
def _mount_binds(self, image_infos):
|
||||
"""
|
||||
:returns: Return the path that we need to map to local folders
|
||||
"""
|
||||
binds = []
|
||||
for volume in image_infos.get("ContainerConfig", {}).get("Volumes", {}).keys():
|
||||
source = os.path.join(self.working_dir, os.path.relpath(volume, "/"))
|
||||
os.makedirs(source, exist_ok=True)
|
||||
binds.append("{}:{}".format(source, volume))
|
||||
return binds
|
||||
|
||||
@asyncio.coroutine
|
||||
def create(self):
|
||||
"""Creates the Docker container."""
|
||||
|
||||
image_infos = yield from self._get_image_informations()
|
||||
|
||||
params = {
|
||||
"Name": self._name,
|
||||
"Image": self._image,
|
||||
@ -130,8 +154,10 @@ class DockerVM(BaseVM):
|
||||
"StdinOnce": False,
|
||||
"HostConfig": {
|
||||
"CapAdd": ["ALL"],
|
||||
"Privileged": True
|
||||
}
|
||||
"Privileged": True,
|
||||
"Binds": self._mount_binds(image_infos)
|
||||
},
|
||||
"Volumes": {}
|
||||
}
|
||||
if self._start_command:
|
||||
params.update({"Cmd": shlex.split(self._start_command)})
|
||||
|
@ -159,10 +159,14 @@ DOCKER_OBJECT_SCHEMA = {
|
||||
"description": "Docker environment",
|
||||
"type": ["string", "null"],
|
||||
"minLength": 0,
|
||||
},
|
||||
"vm_directory": {
|
||||
"decription": "Path to the VM working directory",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": False,
|
||||
"required": ["vm_id", "project_id", "image", "container_id", "adapters", "console", "start_command", "environment"]
|
||||
"required": ["vm_id", "project_id", "image", "container_id", "adapters", "console", "start_command", "environment", "vm_directory"]
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
import pytest
|
||||
import uuid
|
||||
import asyncio
|
||||
import os
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.ubridge.ubridge_error import UbridgeNamespaceError
|
||||
@ -54,7 +55,8 @@ def test_json(vm, project):
|
||||
'adapters': 1,
|
||||
'console': vm.console,
|
||||
'start_command': vm.start_command,
|
||||
'environment': vm.environment
|
||||
'environment': vm.environment,
|
||||
'vm_directory': vm.working_dir
|
||||
}
|
||||
|
||||
|
||||
@ -75,8 +77,10 @@ def test_create(loop, project, manager):
|
||||
"HostConfig":
|
||||
{
|
||||
"CapAdd": ["ALL"],
|
||||
"Binds": [],
|
||||
"Privileged": True
|
||||
},
|
||||
"Volumes": {},
|
||||
"NetworkDisabled": True,
|
||||
"Name": "test",
|
||||
"Image": "ubuntu"
|
||||
@ -102,8 +106,10 @@ def test_create_start_cmd(loop, project, manager):
|
||||
"HostConfig":
|
||||
{
|
||||
"CapAdd": ["ALL"],
|
||||
"Binds": [],
|
||||
"Privileged": True
|
||||
},
|
||||
"Volumes": {},
|
||||
"Cmd": ["/bin/ls"],
|
||||
"NetworkDisabled": True,
|
||||
"Name": "test",
|
||||
@ -130,12 +136,11 @@ def test_create_environment(loop, project, manager):
|
||||
"HostConfig":
|
||||
{
|
||||
"CapAdd": ["ALL"],
|
||||
"Binds": [],
|
||||
"Privileged": True
|
||||
},
|
||||
"Env": [
|
||||
"YES=1",
|
||||
"NO=0"
|
||||
],
|
||||
"Env": ["YES=1", "NO=0"],
|
||||
"Volumes": {},
|
||||
"NetworkDisabled": True,
|
||||
"Name": "test",
|
||||
"Image": "ubuntu"
|
||||
@ -161,8 +166,10 @@ def test_create_image_not_available(loop, project, manager):
|
||||
"HostConfig":
|
||||
{
|
||||
"CapAdd": ["ALL"],
|
||||
"Binds": [],
|
||||
"Privileged": True
|
||||
},
|
||||
"Volumes": {},
|
||||
"NetworkDisabled": True,
|
||||
"Name": "test",
|
||||
"Image": "ubuntu"
|
||||
@ -358,11 +365,13 @@ def test_update(loop, vm):
|
||||
"HostConfig":
|
||||
{
|
||||
"CapAdd": ["ALL"],
|
||||
"Binds": [],
|
||||
"Privileged": True
|
||||
},
|
||||
"NetworkDisabled": True,
|
||||
"Name": "test",
|
||||
"Image": "ubuntu"
|
||||
"Volumes": {},
|
||||
"NetworkDisabled": True,
|
||||
"Name": "test",
|
||||
"Image": "ubuntu"
|
||||
})
|
||||
|
||||
|
||||
@ -602,3 +611,29 @@ def test_get_log(loop, vm):
|
||||
with asyncio_patch("gns3server.modules.docker.Docker.http_query", return_value=mock_query) as mock:
|
||||
images = loop.run_until_complete(asyncio.async(vm._get_log()))
|
||||
mock.assert_called_with("GET", "containers/e90e34656842/logs", params={"stderr": 1, "stdout": 1}, data={})
|
||||
|
||||
|
||||
def test_get_image_informations(project, manager, loop):
|
||||
response = {
|
||||
}
|
||||
with asyncio_patch("gns3server.modules.docker.Docker.query", return_value=response) as mock:
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu")
|
||||
loop.run_until_complete(asyncio.async(vm._get_image_informations()))
|
||||
mock.assert_called_with("GET", "images/ubuntu/json")
|
||||
|
||||
|
||||
def test_mount_binds(vm, tmpdir):
|
||||
image_infos = {
|
||||
"ContainerConfig": {
|
||||
"Volumes": {
|
||||
"/test/experimental": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dst = os.path.join(vm.working_dir, "test/experimental")
|
||||
assert vm._mount_binds(image_infos) == [
|
||||
"{}:{}".format(dst, "/test/experimental")
|
||||
]
|
||||
|
||||
assert os.path.exists(dst)
|
||||
|
Loading…
Reference in New Issue
Block a user