Fix permissions and ownership when stopping container

Fix #550
This commit is contained in:
Julien Duponchelle committed 2016-05-31 21:08:41 +02:00
1 parent 6f7b06e66f
commit d3436756b2
6 files changed
+52 -7

No files matched your search

+4 -1
View File
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import stat
import logging
import aiohttp
import shutil
@@ -224,11 +225,13 @@ class BaseVM:
"""
Delete the VM (including all its files).
"""
def set_rw(operation, name, exc):
os.chmod(name, stat.S_IWRITE)
directory = self.project.vm_working_directory(self)
if os.path.exists(directory):
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:
raise aiohttp.web.HTTPInternalServerError(text="Could not delete the VM working directory: {}".format(e))
+25
View File
@@ -80,6 +80,7 @@ class DockerVM(BaseVM):
self._console_http_path = console_http_path
self._console_http_port = console_http_port
self._console_websocket = None
self._volumes = []
if adapters is None:
self.adapters = 1
@@ -203,6 +204,8 @@ class DockerVM(BaseVM):
network_config = self._create_network_config()
binds.append("{}:/etc/network:rw".format(network_config))
self._volumes = ["/etc/network"]
volumes = image_infos.get("ContainerConfig", {}).get("Volumes")
if volumes is None:
return binds
@@ -210,6 +213,7 @@ class DockerVM(BaseVM):
source = os.path.join(self.working_dir, os.path.relpath(volume, "/"))
os.makedirs(source, exist_ok=True)
binds.append("{}:{}".format(source, volume))
self._volumes.append(volume)
return binds
@@ -380,6 +384,25 @@ class DockerVM(BaseVM):
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)
@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",
"chmod -R u+rX {path} && chown {uid}:{gid} -R {path}".format(uid=os.getuid(), gid=os.getgid(), path=volume))
yield from process.wait()
@asyncio.coroutine
def _start_vnc(self):
"""
@@ -504,6 +527,8 @@ class DockerVM(BaseVM):
if state == "paused":
yield from self.unpause()
yield from self._fix_permissions()
# t=5 number of seconds to wait before killing the container
try:
yield from self.manager.query("POST", "containers/{}/stop".format(self._cid), params={"t": 5})
@@ -60,3 +60,4 @@ ifup -a -f
# continue normal docker startup
PATH="$OLD_PATH"
exec "$@"
+4 -2
View File
@@ -16,24 +16,26 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import functools
import asyncio
import sys
import os
@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
for the result.
:param func: Run this function in a different thread
:param args: Parameters of the function
:param kwargs: Keyword parameters of the function
:returns: Return the result of the function
"""
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])
return future.result()