diff --git a/gns3server/compute/docker/__init__.py b/gns3server/compute/docker/__init__.py index 2801d93c..9e9e72b1 100644 --- a/gns3server/compute/docker/__init__.py +++ b/gns3server/compute/docker/__init__.py @@ -59,7 +59,7 @@ class Docker(BaseManager): self._api_version = DOCKER_MINIMUM_API_VERSION @staticmethod - def install_busybox(): + async def install_busybox(): if not sys.platform.startswith("linux"): return @@ -69,10 +69,24 @@ class Docker(BaseManager): for busybox_exec in ("busybox-static", "busybox.static", "busybox"): busybox_path = shutil.which(busybox_exec) if busybox_path: - log.info(f"Installing busybox from '{busybox_path}'") try: - shutil.copy2(busybox_path, dst_busybox, follow_symlinks=True) - return + # check that busybox is statically linked + # (dynamically linked busybox will fail to run in a container) + proc = await asyncio.create_subprocess_exec( + "ldd", + busybox_path, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.DEVNULL + ) + stdout, _ = await proc.communicate() + if proc.returncode == 1: + # ldd returns 1 if the file is not a dynamic executable + log.info(f"Installing busybox from '{busybox_path}' to '{dst_busybox}'") + shutil.copy2(busybox_path, dst_busybox, follow_symlinks=True) + return + else: + log.warning(f"Busybox '{busybox_path}' is dynamically linked\n" + f"{stdout.decode('utf-8', errors='ignore').strip()}") except OSError as e: raise DockerError(f"Could not install busybox: {e}") raise DockerError("No busybox executable could be found") diff --git a/gns3server/compute/docker/docker_vm.py b/gns3server/compute/docker/docker_vm.py index 0e8cf243..bd94e86e 100644 --- a/gns3server/compute/docker/docker_vm.py +++ b/gns3server/compute/docker/docker_vm.py @@ -545,7 +545,7 @@ class DockerVM(BaseNode): """ # make sure busybox is installed - self.manager.install_busybox() + await self.manager.install_busybox() try: state = await self._get_container_state() diff --git a/gns3server/utils/asyncio/__init__.py b/gns3server/utils/asyncio/__init__.py index 46937b1b..562a3df6 100644 --- a/gns3server/utils/asyncio/__init__.py +++ b/gns3server/utils/asyncio/__init__.py @@ -77,7 +77,7 @@ async def subprocess_check_output(*args, cwd=None, env=None, stderr=False): if output is None: return "" # If we received garbage we ignore invalid characters - # it should happens only when user try to use another binary + # it should happen only when user try to use another binary # and the code of VPCS, dynamips... Will detect it's not the correct binary return output.decode("utf-8", errors="ignore")