|
|
|
@ -84,6 +84,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
|
|
|
|
@ -143,6 +145,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
|
|
|
|
@ -174,9 +177,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:
|
|
|
|
@ -191,11 +195,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):
|
|
|
|
@ -219,6 +225,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] == b"\x01":
|
|
|
|
|
# 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 = {
|
|
|
|
@ -385,8 +413,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
|
|
|
|
@ -513,7 +543,7 @@ class IOUVM(BaseNode):
|
|
|
|
|
Starts the IOU process.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
self._check_requirements()
|
|
|
|
|
await self._check_requirements()
|
|
|
|
|
if not self.is_running():
|
|
|
|
|
|
|
|
|
|
await self._library_check()
|
|
|
|
@ -560,10 +590,13 @@ class IOUVM(BaseNode):
|
|
|
|
|
|
|
|
|
|
command = await self._build_command()
|
|
|
|
|
try:
|
|
|
|
|
log.info(f"Starting IOU: {command}")
|
|
|
|
|
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,
|
|
|
|
@ -1125,7 +1158,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"])
|
|
|
|
|