mirror of
https://github.com/GNS3/gns3-server.git
synced 2024-11-17 17:24:51 +02:00
Merge pull request #2086 from GNS3/iou-user-loader-libraries
Support user defined loader/libraries to run IOU
This commit is contained in:
commit
d08a052f94
@ -88,6 +88,8 @@ class IOUVM(BaseNode):
|
||||
self._started = False
|
||||
self._nvram_watcher = None
|
||||
self._path = self.manager.get_abs_image_path(path, project.path)
|
||||
self._lib_base = self.manager.get_images_directory()
|
||||
self._loader = None
|
||||
self._license_check = True
|
||||
|
||||
# IOU settings
|
||||
@ -147,6 +149,7 @@ class IOUVM(BaseNode):
|
||||
"""
|
||||
|
||||
self._path = self.manager.get_abs_image_path(path, self.project.path)
|
||||
self._loader = None
|
||||
log.info(f'IOU "{self._name}" [{self._id}]: IOU image updated to "{self._path}"')
|
||||
|
||||
@property
|
||||
@ -178,9 +181,10 @@ class IOUVM(BaseNode):
|
||||
Finds the default RAM and NVRAM values for the IOU image.
|
||||
"""
|
||||
|
||||
await self._check_requirements()
|
||||
try:
|
||||
output = await gns3server.utils.asyncio.subprocess_check_output(
|
||||
self._path, "-h", cwd=self.working_dir, stderr=True
|
||||
*self._loader, self._path, "-h", cwd=self.working_dir, stderr=True
|
||||
)
|
||||
match = re.search(r"-n <n>\s+Size of nvram in Kb \(default ([0-9]+)KB\)", output)
|
||||
if match:
|
||||
@ -195,11 +199,13 @@ class IOUVM(BaseNode):
|
||||
|
||||
await self.update_default_iou_values()
|
||||
|
||||
def _check_requirements(self):
|
||||
async def _check_requirements(self):
|
||||
"""
|
||||
Checks the IOU image.
|
||||
"""
|
||||
|
||||
if self._loader is not None:
|
||||
return # image already checked
|
||||
if not self._path:
|
||||
raise IOUError("IOU image is not configured")
|
||||
if not os.path.isfile(self._path) or not os.path.exists(self._path):
|
||||
@ -223,6 +229,28 @@ class IOUVM(BaseNode):
|
||||
if not os.access(self._path, os.X_OK):
|
||||
raise IOUError(f"IOU image '{self._path}' is not executable")
|
||||
|
||||
# set loader command
|
||||
if elf_header_start[4] == 1:
|
||||
# 32-bit loader
|
||||
loader = os.path.join(self._lib_base, "lib", "ld-linux.so.2")
|
||||
lib_path = (os.path.join(self._lib_base, "lib"),
|
||||
os.path.join(self._lib_base, "lib", "i386-linux-gnu"))
|
||||
else:
|
||||
# 64-bit loader
|
||||
loader = os.path.join(self._lib_base, "lib64", "ld-linux-x86-64.so.2")
|
||||
lib_path = (os.path.join(self._lib_base, "lib64"),
|
||||
os.path.join(self._lib_base, "lib", "x86_64-linux-gnu"))
|
||||
self._loader = []
|
||||
if os.path.isfile(loader):
|
||||
try:
|
||||
proc = await asyncio.create_subprocess_exec(loader, "--verify", self._path)
|
||||
if await proc.wait() == 0:
|
||||
self._loader = [loader, "--library-path", ":".join(lib_path)]
|
||||
else:
|
||||
log.warning(f"Loader {loader} incompatible with '{self._path}'")
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
log.warning(f"Could not use loader {loader}: {e}")
|
||||
|
||||
def asdict(self):
|
||||
|
||||
iou_vm_info = {
|
||||
@ -391,8 +419,10 @@ class IOUVM(BaseNode):
|
||||
Checks for missing shared library dependencies in the IOU image.
|
||||
"""
|
||||
|
||||
env = os.environ.copy()
|
||||
env["LD_TRACE_LOADED_OBJECTS"] = "1"
|
||||
try:
|
||||
output = await gns3server.utils.asyncio.subprocess_check_output("ldd", self._path)
|
||||
output = await gns3server.utils.asyncio.subprocess_check_output(*self._loader, self._path, env=env)
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
log.warning(f"Could not determine the shared library dependencies for {self._path}: {e}")
|
||||
return
|
||||
@ -519,7 +549,7 @@ class IOUVM(BaseNode):
|
||||
Starts the IOU process.
|
||||
"""
|
||||
|
||||
self._check_requirements()
|
||||
await self._check_requirements()
|
||||
if not self.is_running():
|
||||
|
||||
await self._library_check()
|
||||
@ -566,10 +596,13 @@ class IOUVM(BaseNode):
|
||||
|
||||
command = await self._build_command()
|
||||
try:
|
||||
if self._loader:
|
||||
log.info(f"Starting IOU: {command} with loader {self._loader}")
|
||||
else:
|
||||
log.info(f"Starting IOU: {command}")
|
||||
self.command_line = " ".join(command)
|
||||
self._iou_process = await asyncio.create_subprocess_exec(
|
||||
*command,
|
||||
*self._loader, *command,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
@ -1131,7 +1164,7 @@ class IOUVM(BaseNode):
|
||||
env["IOURC"] = self.iourc_path
|
||||
try:
|
||||
output = await gns3server.utils.asyncio.subprocess_check_output(
|
||||
self._path, "-h", cwd=self.working_dir, env=env, stderr=True
|
||||
*self._loader, self._path, "-h", cwd=self.working_dir, env=env, stderr=True
|
||||
)
|
||||
if re.search(r"-l\s+Enable Layer 1 keepalive messages", output):
|
||||
command.extend(["-l"])
|
||||
|
@ -91,7 +91,8 @@ async def get_computes(app: FastAPI) -> List[dict]:
|
||||
def image_filter(change: Change, path: str) -> bool:
|
||||
|
||||
if change == Change.added and os.path.isfile(path):
|
||||
if path.endswith(".tmp") or path.endswith(".md5sum") or path.startswith("."):
|
||||
if path.endswith(".tmp") or path.endswith(".md5sum") or path.startswith(".") or \
|
||||
"/lib/" in path or "/lib64/" in path:
|
||||
return False
|
||||
header_magic_len = 7
|
||||
with open(path, "rb") as f:
|
||||
|
@ -48,6 +48,7 @@ async def vm(compute_project, manager, config, tmpdir, fake_iou_bin, iourc_file)
|
||||
vm = IOUVM("test", str(uuid.uuid4()), compute_project, manager, application_id=1)
|
||||
config.settings.IOU.iourc_path = iourc_file
|
||||
vm.path = "iou.bin"
|
||||
vm._loader = []
|
||||
return vm
|
||||
|
||||
|
||||
@ -228,7 +229,8 @@ def test_path_relative(vm, fake_iou_bin):
|
||||
assert vm.path == fake_iou_bin
|
||||
|
||||
|
||||
def test_path_invalid_bin(vm, tmpdir, config):
|
||||
@pytest.mark.asyncio
|
||||
async def test_path_invalid_bin(vm, tmpdir, config):
|
||||
|
||||
config.settings.Server.images_path = str(tmpdir)
|
||||
path = str(tmpdir / "test.bin")
|
||||
@ -238,7 +240,7 @@ def test_path_invalid_bin(vm, tmpdir, config):
|
||||
|
||||
with pytest.raises(IOUError):
|
||||
vm.path = path
|
||||
vm._check_requirements()
|
||||
await vm._check_requirements()
|
||||
|
||||
|
||||
def test_create_netmap_config(vm):
|
||||
|
Loading…
Reference in New Issue
Block a user