mirror of
https://github.com/GNS3/gns3-server
synced 2025-02-20 03:52:00 +00:00
Merge branch '1.5' into 2.0
This commit is contained in:
commit
cb7dbfb256
15
CHANGELOG
15
CHANGELOG
@ -1,5 +1,20 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 1.5.0rc1 01/06/2016
|
||||||
|
|
||||||
|
* Save an restore docker permission
|
||||||
|
* Export the list of volumes to a env variable accessible in the container
|
||||||
|
* Fix a crash when docker start command is None
|
||||||
|
* Ubridge 0.9.4 is require
|
||||||
|
* Generate a MAC address using the project + node UUID. Ref #522.
|
||||||
|
* Catch extra args in windows signal handler
|
||||||
|
* Allow to block network traffic originating from the host OS for vmnet interfaces (Windows only).
|
||||||
|
* Fix an import error when you have no GNS3 VM
|
||||||
|
* Warn if you can not export a file due to permission issue
|
||||||
|
* Do not delete adapters when stopping a VMware VM. Ref #1066.
|
||||||
|
* Allocate a new vmnet interface if vmnet 0 1 or 8 is set to a custom adapter. Set adapter type to all adapters regardless if already configured or added by GNS3.
|
||||||
|
* Set default VMware VM adapter type to e1000.
|
||||||
|
|
||||||
## 1.5.0b1 23/05/2016
|
## 1.5.0b1 23/05/2016
|
||||||
|
|
||||||
* Allow an IOS router to stop even the Dynamips hypervisor command fail to be sent. Ref #488.
|
* Allow an IOS router to stop even the Dynamips hypervisor command fail to be sent. Ref #488.
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import stat
|
||||||
import logging
|
import logging
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import shutil
|
import shutil
|
||||||
@ -230,11 +231,13 @@ class BaseNode:
|
|||||||
"""
|
"""
|
||||||
Delete the node (including all its files).
|
Delete the node (including all its files).
|
||||||
"""
|
"""
|
||||||
|
def set_rw(operation, name, exc):
|
||||||
|
os.chmod(name, stat.S_IWRITE)
|
||||||
|
|
||||||
directory = self.project.node_working_directory(self)
|
directory = self.project.node_working_directory(self)
|
||||||
if os.path.exists(directory):
|
if os.path.exists(directory):
|
||||||
try:
|
try:
|
||||||
yield from wait_run_in_executor(shutil.rmtree, directory)
|
yield from wait_run_in_executor(shutil.rmtree, directory, onerror=set_rw)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise aiohttp.web.HTTPInternalServerError(text="Could not delete the node working directory: {}".format(e))
|
raise aiohttp.web.HTTPInternalServerError(text="Could not delete the node working directory: {}".format(e))
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ class DockerVM(BaseNode):
|
|||||||
self._console_http_path = console_http_path
|
self._console_http_path = console_http_path
|
||||||
self._console_http_port = console_http_port
|
self._console_http_port = console_http_port
|
||||||
self._console_websocket = None
|
self._console_websocket = None
|
||||||
|
self._volumes = []
|
||||||
|
|
||||||
if adapters is None:
|
if adapters is None:
|
||||||
self.adapters = 1
|
self.adapters = 1
|
||||||
@ -135,8 +136,9 @@ class DockerVM(BaseNode):
|
|||||||
|
|
||||||
@start_command.setter
|
@start_command.setter
|
||||||
def start_command(self, command):
|
def start_command(self, command):
|
||||||
command = command.strip()
|
if command:
|
||||||
if len(command) == 0:
|
command = command.strip()
|
||||||
|
if command is None or len(command) == 0:
|
||||||
self._start_command = None
|
self._start_command = None
|
||||||
else:
|
else:
|
||||||
self._start_command = command
|
self._start_command = command
|
||||||
@ -206,6 +208,8 @@ class DockerVM(BaseNode):
|
|||||||
network_config = self._create_network_config()
|
network_config = self._create_network_config()
|
||||||
binds.append("{}:/etc/network:rw".format(network_config))
|
binds.append("{}:/etc/network:rw".format(network_config))
|
||||||
|
|
||||||
|
self._volumes = ["/etc/network"]
|
||||||
|
|
||||||
volumes = image_infos.get("ContainerConfig", {}).get("Volumes")
|
volumes = image_infos.get("ContainerConfig", {}).get("Volumes")
|
||||||
if volumes is None:
|
if volumes is None:
|
||||||
return binds
|
return binds
|
||||||
@ -213,6 +217,7 @@ class DockerVM(BaseNode):
|
|||||||
source = os.path.join(self.working_dir, os.path.relpath(volume, "/"))
|
source = os.path.join(self.working_dir, os.path.relpath(volume, "/"))
|
||||||
os.makedirs(source, exist_ok=True)
|
os.makedirs(source, exist_ok=True)
|
||||||
binds.append("{}:{}".format(source, volume))
|
binds.append("{}:{}".format(source, volume))
|
||||||
|
self._volumes.append(volume)
|
||||||
|
|
||||||
return binds
|
return binds
|
||||||
|
|
||||||
@ -293,6 +298,8 @@ class DockerVM(BaseNode):
|
|||||||
|
|
||||||
# Give the information to the container on how many interface should be inside
|
# Give the information to the container on how many interface should be inside
|
||||||
params["Env"].append("GNS3_MAX_ETHERNET=eth{}".format(self.adapters - 1))
|
params["Env"].append("GNS3_MAX_ETHERNET=eth{}".format(self.adapters - 1))
|
||||||
|
# Give the information to the container the list of volume path mounted
|
||||||
|
params["Env"].append("GNS3_VOLUMES={}".format(":".join(self._volumes)))
|
||||||
|
|
||||||
if self._environment:
|
if self._environment:
|
||||||
params["Env"] += [e.strip() for e in self._environment.split("\n")]
|
params["Env"] += [e.strip() for e in self._environment.split("\n")]
|
||||||
@ -385,6 +392,25 @@ class DockerVM(BaseNode):
|
|||||||
self._telnet_servers.append((yield from asyncio.start_server(server.run, self._manager.port_manager.console_host, self.aux)))
|
self._telnet_servers.append((yield from asyncio.start_server(server.run, self._manager.port_manager.console_host, self.aux)))
|
||||||
log.debug("Docker container '%s' started listen for auxilary telnet on %d", self.name, self.aux)
|
log.debug("Docker container '%s' started listen for auxilary telnet on %d", self.name, self.aux)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def _fix_permissions(self):
|
||||||
|
"""
|
||||||
|
Because docker run as root we need to fix permission and ownership to allow user to interact
|
||||||
|
with it from their filesystem and do operation like file delete
|
||||||
|
"""
|
||||||
|
for volume in self._volumes:
|
||||||
|
log.debug("Docker container '{name}' [{image}] fix ownership on {path}".format(
|
||||||
|
name=self._name, image=self._image, path=volume))
|
||||||
|
process = yield from asyncio.subprocess.create_subprocess_exec(
|
||||||
|
"docker",
|
||||||
|
"exec",
|
||||||
|
self._cid,
|
||||||
|
"/gns3/bin/busybox",
|
||||||
|
"sh",
|
||||||
|
"-c",
|
||||||
|
"(/gns3/bin/busybox find \"{path}\" -depth -print0 | /gns3/bin/busybox xargs -0 /gns3/bin/busybox stat -c '%a:%u:%g:%n' > \"{path}/.gns3_perms\") && /gns3/bin/busybox chmod -R u+rX \"{path}\" && /gns3/bin/busybox chown {uid}:{gid} -R \"{path}\"".format(uid=os.getuid(), gid=os.getgid(), path=volume))
|
||||||
|
yield from process.wait()
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _start_vnc(self):
|
def _start_vnc(self):
|
||||||
"""
|
"""
|
||||||
@ -508,6 +534,8 @@ class DockerVM(BaseNode):
|
|||||||
if state == "paused":
|
if state == "paused":
|
||||||
yield from self.unpause()
|
yield from self.unpause()
|
||||||
|
|
||||||
|
yield from self._fix_permissions()
|
||||||
|
|
||||||
# t=5 number of seconds to wait before killing the container
|
# t=5 number of seconds to wait before killing the container
|
||||||
try:
|
try:
|
||||||
yield from self.manager.query("POST", "containers/{}/stop".format(self._cid), params={"t": 5})
|
yield from self.manager.query("POST", "containers/{}/stop".format(self._cid), params={"t": 5})
|
||||||
|
@ -28,6 +28,20 @@ if [ ! -d /tmp/gns3/bin ]; then
|
|||||||
/gns3/bin/busybox --install -s /tmp/gns3/bin
|
/gns3/bin/busybox --install -s /tmp/gns3/bin
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Restore file permission
|
||||||
|
for i in $(echo "$GNS3_VOLUMES" | tr ":" "\n")
|
||||||
|
do
|
||||||
|
if [ -f "$i/.gns3_perms" ]
|
||||||
|
then
|
||||||
|
while IFS=: read PERMS OWNER GROUP FILE
|
||||||
|
do
|
||||||
|
chmod "$PERMS" "$FILE"
|
||||||
|
chown "${OWNER}:${GROUP}" "$FILE"
|
||||||
|
done < "$i/.gns3_perms"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
# /etc/hosts
|
# /etc/hosts
|
||||||
[ -s /etc/hosts ] || cat > /etc/hosts << __EOF__
|
[ -s /etc/hosts ] || cat > /etc/hosts << __EOF__
|
||||||
127.0.1.1 $HOSTNAME
|
127.0.1.1 $HOSTNAME
|
||||||
@ -60,3 +74,4 @@ ifup -a -f
|
|||||||
# continue normal docker startup
|
# continue normal docker startup
|
||||||
PATH="$OLD_PATH"
|
PATH="$OLD_PATH"
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ import subprocess
|
|||||||
import shlex
|
import shlex
|
||||||
import asyncio
|
import asyncio
|
||||||
import socket
|
import socket
|
||||||
import random
|
|
||||||
import gns3server
|
import gns3server
|
||||||
|
|
||||||
from gns3server.utils import parse_version
|
from gns3server.utils import parse_version
|
||||||
@ -493,9 +492,10 @@ class QemuVM(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if not mac_address:
|
if not mac_address:
|
||||||
self._mac_address = "12:34:%02x:%02x:%02x:00" % (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
|
# use the node UUID to generate a random MAC address
|
||||||
|
self._mac_address = "00:%s:%s:%s:%s:00" % (self.project.id[-4:-2], self.project.id[-2:], self.id[-4:-2], self.id[-2:])
|
||||||
else:
|
else:
|
||||||
self._mac_address = mac_address[:8] + ":%02x:%02x:00" % (random.randint(0, 255), random.randint(0, 255))
|
self._mac_address = mac_address
|
||||||
|
|
||||||
log.info('QEMU VM "{name}" [{id}]: MAC address changed to {mac_addr}'.format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}]: MAC address changed to {mac_addr}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
|
@ -120,15 +120,15 @@ class Hypervisor(UBridgeHypervisor):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _check_ubridge_version(self):
|
def _check_ubridge_version(self):
|
||||||
"""
|
"""
|
||||||
Checks if the ubridge executable version is >= 0.9.3
|
Checks if the ubridge executable version is >= 0.9.4
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
output = yield from subprocess_check_output(self._path, "-v", cwd=self._working_dir)
|
output = yield from subprocess_check_output(self._path, "-v", cwd=self._working_dir)
|
||||||
match = re.search("ubridge version ([0-9a-z\.]+)", output)
|
match = re.search("ubridge version ([0-9a-z\.]+)", output)
|
||||||
if match:
|
if match:
|
||||||
version = match.group(1)
|
version = match.group(1)
|
||||||
if parse_version(version) < parse_version("0.9.3"):
|
if parse_version(version) < parse_version("0.9.4"):
|
||||||
raise UbridgeError("uBridge executable version must be >= 0.9.3")
|
raise UbridgeError("uBridge executable version must be >= 0.9.4")
|
||||||
else:
|
else:
|
||||||
raise UbridgeError("Could not determine uBridge version for {}".format(self._path))
|
raise UbridgeError("Could not determine uBridge version for {}".format(self._path))
|
||||||
except (OSError, subprocess.SubprocessError) as e:
|
except (OSError, subprocess.SubprocessError) as e:
|
||||||
|
@ -16,24 +16,26 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import functools
|
||||||
import asyncio
|
import asyncio
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def wait_run_in_executor(func, *args):
|
def wait_run_in_executor(func, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Run blocking code in a different thread and wait
|
Run blocking code in a different thread and wait
|
||||||
for the result.
|
for the result.
|
||||||
|
|
||||||
:param func: Run this function in a different thread
|
:param func: Run this function in a different thread
|
||||||
:param args: Parameters of the function
|
:param args: Parameters of the function
|
||||||
|
:param kwargs: Keyword parameters of the function
|
||||||
:returns: Return the result of the function
|
:returns: Return the result of the function
|
||||||
"""
|
"""
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
future = loop.run_in_executor(None, func, *args)
|
future = loop.run_in_executor(None, functools.partial(func, *args, **kwargs))
|
||||||
yield from asyncio.wait([future])
|
yield from asyncio.wait([future])
|
||||||
return future.result()
|
return future.result()
|
||||||
|
|
||||||
|
@ -105,8 +105,9 @@ def test_create(loop, project, manager):
|
|||||||
"Hostname": "test",
|
"Hostname": "test",
|
||||||
"Image": "ubuntu:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Env": [
|
"Env": [
|
||||||
"GNS3_MAX_ETHERNET=eth0"
|
"GNS3_MAX_ETHERNET=eth0",
|
||||||
],
|
"GNS3_VOLUMES=/etc/network"
|
||||||
|
],
|
||||||
"Entrypoint": ["/gns3/init.sh"],
|
"Entrypoint": ["/gns3/init.sh"],
|
||||||
"Cmd": ["/bin/sh"]
|
"Cmd": ["/bin/sh"]
|
||||||
})
|
})
|
||||||
@ -142,8 +143,9 @@ def test_create_with_tag(loop, project, manager):
|
|||||||
"Hostname": "test",
|
"Hostname": "test",
|
||||||
"Image": "ubuntu:16.04",
|
"Image": "ubuntu:16.04",
|
||||||
"Env": [
|
"Env": [
|
||||||
"GNS3_MAX_ETHERNET=eth0"
|
"GNS3_MAX_ETHERNET=eth0",
|
||||||
],
|
"GNS3_VOLUMES=/etc/network"
|
||||||
|
],
|
||||||
"Entrypoint": ["/gns3/init.sh"],
|
"Entrypoint": ["/gns3/init.sh"],
|
||||||
"Cmd": ["/bin/sh"]
|
"Cmd": ["/bin/sh"]
|
||||||
})
|
})
|
||||||
@ -184,8 +186,9 @@ def test_create_vnc(loop, project, manager):
|
|||||||
"Image": "ubuntu:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Env": [
|
"Env": [
|
||||||
"GNS3_MAX_ETHERNET=eth0",
|
"GNS3_MAX_ETHERNET=eth0",
|
||||||
|
"GNS3_VOLUMES=/etc/network",
|
||||||
"DISPLAY=:42"
|
"DISPLAY=:42"
|
||||||
],
|
],
|
||||||
"Entrypoint": ["/gns3/init.sh"],
|
"Entrypoint": ["/gns3/init.sh"],
|
||||||
"Cmd": ["/bin/sh"]
|
"Cmd": ["/bin/sh"]
|
||||||
})
|
})
|
||||||
@ -226,8 +229,9 @@ def test_create_start_cmd(loop, project, manager):
|
|||||||
"Hostname": "test",
|
"Hostname": "test",
|
||||||
"Image": "ubuntu:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Env": [
|
"Env": [
|
||||||
"GNS3_MAX_ETHERNET=eth0"
|
"GNS3_MAX_ETHERNET=eth0",
|
||||||
]
|
"GNS3_VOLUMES=/etc/network"
|
||||||
|
]
|
||||||
})
|
})
|
||||||
assert vm._cid == "e90e34656806"
|
assert vm._cid == "e90e34656806"
|
||||||
|
|
||||||
@ -258,6 +262,7 @@ def test_create_environment(loop, project, manager):
|
|||||||
},
|
},
|
||||||
"Env": [
|
"Env": [
|
||||||
"GNS3_MAX_ETHERNET=eth0",
|
"GNS3_MAX_ETHERNET=eth0",
|
||||||
|
"GNS3_VOLUMES=/etc/network",
|
||||||
"YES=1",
|
"YES=1",
|
||||||
"NO=0"
|
"NO=0"
|
||||||
],
|
],
|
||||||
@ -315,8 +320,9 @@ def test_create_image_not_available(loop, project, manager):
|
|||||||
"Hostname": "test",
|
"Hostname": "test",
|
||||||
"Image": "ubuntu:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Env": [
|
"Env": [
|
||||||
"GNS3_MAX_ETHERNET=eth0"
|
"GNS3_MAX_ETHERNET=eth0",
|
||||||
],
|
"GNS3_VOLUMES=/etc/network"
|
||||||
|
],
|
||||||
"Entrypoint": ["/gns3/init.sh"],
|
"Entrypoint": ["/gns3/init.sh"],
|
||||||
"Cmd": ["/bin/sh"]
|
"Cmd": ["/bin/sh"]
|
||||||
})
|
})
|
||||||
@ -479,12 +485,14 @@ def test_restart(loop, vm):
|
|||||||
def test_stop(loop, vm):
|
def test_stop(loop, vm):
|
||||||
vm._ubridge_hypervisor = MagicMock()
|
vm._ubridge_hypervisor = MagicMock()
|
||||||
vm._ubridge_hypervisor.is_running.return_value = True
|
vm._ubridge_hypervisor.is_running.return_value = True
|
||||||
|
vm._fix_permissions = MagicMock()
|
||||||
|
|
||||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="running"):
|
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="running"):
|
||||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
||||||
loop.run_until_complete(asyncio.async(vm.stop()))
|
loop.run_until_complete(asyncio.async(vm.stop()))
|
||||||
mock_query.assert_called_with("POST", "containers/e90e34656842/stop", params={"t": 5})
|
mock_query.assert_called_with("POST", "containers/e90e34656842/stop", params={"t": 5})
|
||||||
assert vm._ubridge_hypervisor.stop.called
|
assert vm._ubridge_hypervisor.stop.called
|
||||||
|
assert vm._fix_permissions.called
|
||||||
|
|
||||||
|
|
||||||
def test_stop_paused_container(loop, vm):
|
def test_stop_paused_container(loop, vm):
|
||||||
@ -532,7 +540,8 @@ def test_update(loop, vm):
|
|||||||
"Hostname": "test",
|
"Hostname": "test",
|
||||||
"Image": "ubuntu:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Env": [
|
"Env": [
|
||||||
"GNS3_MAX_ETHERNET=eth0"
|
"GNS3_MAX_ETHERNET=eth0",
|
||||||
|
"GNS3_VOLUMES=/etc/network"
|
||||||
],
|
],
|
||||||
"Entrypoint": ["/gns3/init.sh"],
|
"Entrypoint": ["/gns3/init.sh"],
|
||||||
"Cmd": ["/bin/sh"]
|
"Cmd": ["/bin/sh"]
|
||||||
@ -599,7 +608,8 @@ def test_update_running(loop, vm):
|
|||||||
"Hostname": "test",
|
"Hostname": "test",
|
||||||
"Image": "ubuntu:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Env": [
|
"Env": [
|
||||||
"GNS3_MAX_ETHERNET=eth0"
|
"GNS3_MAX_ETHERNET=eth0",
|
||||||
|
"GNS3_VOLUMES=/etc/network"
|
||||||
],
|
],
|
||||||
"Entrypoint": ["/gns3/init.sh"],
|
"Entrypoint": ["/gns3/init.sh"],
|
||||||
"Cmd": ["/bin/sh"]
|
"Cmd": ["/bin/sh"]
|
||||||
@ -869,6 +879,7 @@ def test_mount_binds(vm, tmpdir):
|
|||||||
"{}:{}".format(dst, "/test/experimental")
|
"{}:{}".format(dst, "/test/experimental")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
assert vm._volumes == ["/etc/network", "/test/experimental"]
|
||||||
assert os.path.exists(dst)
|
assert os.path.exists(dst)
|
||||||
|
|
||||||
|
|
||||||
@ -893,6 +904,7 @@ def test_start_aux(vm, loop):
|
|||||||
|
|
||||||
with asyncio_patch("asyncio.subprocess.create_subprocess_exec", return_value=MagicMock()) as mock_exec:
|
with asyncio_patch("asyncio.subprocess.create_subprocess_exec", return_value=MagicMock()) as mock_exec:
|
||||||
loop.run_until_complete(asyncio.async(vm._start_aux()))
|
loop.run_until_complete(asyncio.async(vm._start_aux()))
|
||||||
|
mock_exec.assert_called_with('docker', 'exec', '-i', 'e90e34656842', '/gns3/bin/busybox', 'script', '-qfc', '/gns3/bin/busybox sh', '/dev/null', stderr=asyncio.subprocess.STDOUT, stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def test_create_network_interfaces(vm):
|
def test_create_network_interfaces(vm):
|
||||||
@ -907,3 +919,12 @@ def test_create_network_interfaces(vm):
|
|||||||
assert "eth0" in content
|
assert "eth0" in content
|
||||||
assert "eth4" in content
|
assert "eth4" in content
|
||||||
assert "eth5" not in content
|
assert "eth5" not in content
|
||||||
|
|
||||||
|
|
||||||
|
def test_fix_permission(vm, loop):
|
||||||
|
vm._volumes = ["/etc"]
|
||||||
|
process = MagicMock()
|
||||||
|
with asyncio_patch("asyncio.subprocess.create_subprocess_exec", return_value=process) as mock_exec:
|
||||||
|
loop.run_until_complete(vm._fix_permissions())
|
||||||
|
mock_exec.assert_called_with('docker', 'exec', 'e90e34656842', '/gns3/bin/busybox', 'sh', '-c', '(/gns3/bin/busybox find "/etc" -depth -print0 | /gns3/bin/busybox xargs -0 /gns3/bin/busybox stat -c \'%a:%u:%g:%n\' > "/etc/.gns3_perms") && /gns3/bin/busybox chmod -R u+rX "/etc" && /gns3/bin/busybox chown {}:{} -R "/etc"'.format(os.getuid(), os.getgid()))
|
||||||
|
assert process.wait.called
|
||||||
|
@ -129,6 +129,9 @@ def test_commit(manager, loop):
|
|||||||
|
|
||||||
|
|
||||||
def test_commit_permission_issue(manager, loop):
|
def test_commit_permission_issue(manager, loop):
|
||||||
|
"""
|
||||||
|
GNS3 will fix the permission and continue to delete
|
||||||
|
"""
|
||||||
project = Project(project_id=str(uuid4()))
|
project = Project(project_id=str(uuid4()))
|
||||||
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
|
||||||
project.add_node(node)
|
project.add_node(node)
|
||||||
@ -137,9 +140,7 @@ def test_commit_permission_issue(manager, loop):
|
|||||||
assert len(project._nodes_to_destroy) == 1
|
assert len(project._nodes_to_destroy) == 1
|
||||||
assert os.path.exists(directory)
|
assert os.path.exists(directory)
|
||||||
os.chmod(directory, 0)
|
os.chmod(directory, 0)
|
||||||
with pytest.raises(aiohttp.web.HTTPInternalServerError):
|
loop.run_until_complete(asyncio.async(project.commit()))
|
||||||
loop.run_until_complete(asyncio.async(project.commit()))
|
|
||||||
os.chmod(directory, 700)
|
|
||||||
|
|
||||||
|
|
||||||
def test_project_delete(loop):
|
def test_project_delete(loop):
|
||||||
|
Loading…
Reference in New Issue
Block a user