Merge pull request #2146 from GNS3/fix/2126

Improve image discovery process
pull/2160/head
Jeremy Grossmann 2 years ago committed by GitHub
commit 91b50eb5f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -57,6 +57,9 @@ default_symbol_theme = Affinity-square-blue
; Option to enable or disable raw images to be uploaded to the server ; Option to enable or disable raw images to be uploaded to the server
allow_raw_images = True allow_raw_images = True
; Option to automatically discover images in the images directory
auto_discover_images = True
; Option to automatically send crash reports to the GNS3 team ; Option to automatically send crash reports to the GNS3 team
report_errors = True report_errors = True

@ -21,6 +21,7 @@ from typing import Callable
from fastapi import FastAPI from fastapi import FastAPI
from gns3server.controller import Controller from gns3server.controller import Controller
from gns3server.config import Config
from gns3server.compute import MODULES from gns3server.compute import MODULES
from gns3server.compute.port_manager import PortManager from gns3server.compute.port_manager import PortManager
from gns3server.utils.http_client import HTTPClient from gns3server.utils.http_client import HTTPClient
@ -60,9 +61,10 @@ def create_startup_handler(app: FastAPI) -> Callable:
# computing with server start # computing with server start
from gns3server.compute.qemu import Qemu from gns3server.compute.qemu import Qemu
# Start the discovering new images on file system 5 seconds after the server has started if Config.instance().settings.Server.auto_discover_images is True:
# to give it a chance to process API requests # Start the discovering new images on file system 5 seconds after the server has started
loop.call_later(5, asyncio.create_task, discover_images_on_filesystem(app)) # to give it a chance to process API requests
loop.call_later(5, asyncio.create_task, discover_images_on_filesystem(app))
for module in MODULES: for module in MODULES:
log.debug(f"Loading module {module.__name__}") log.debug(f"Loading module {module.__name__}")

@ -30,7 +30,7 @@ from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from gns3server.db.repositories.computes import ComputesRepository from gns3server.db.repositories.computes import ComputesRepository
from gns3server.db.repositories.images import ImagesRepository from gns3server.db.repositories.images import ImagesRepository
from gns3server.utils.images import discover_images, check_valid_image_header, read_image_info, InvalidImageError from gns3server.utils.images import discover_images, check_valid_image_header, read_image_info, default_images_directory, InvalidImageError
from gns3server import schemas from gns3server import schemas
from .models import Base from .models import Base
@ -117,12 +117,16 @@ def image_filter(change: Change, path: str) -> bool:
async def monitor_images_on_filesystem(app: FastAPI): async def monitor_images_on_filesystem(app: FastAPI):
server_config = Config.instance().settings.Server directories_to_monitor = []
images_dir = os.path.expanduser(server_config.images_path) for image_type in ("qemu", "ios", "iou"):
image_dir = default_images_directory(image_type)
if os.path.isdir(image_dir):
log.debug(f"Monitoring for new images in '{image_dir}'")
directories_to_monitor.append(image_dir)
try: try:
async for changes in awatch( async for changes in awatch(
images_dir, *directories_to_monitor,
watch_filter=image_filter, watch_filter=image_filter,
raise_interrupt=True raise_interrupt=True
): ):

@ -137,6 +137,7 @@ class ServerSettings(BaseModel):
configs_path: str = "~/GNS3/configs" configs_path: str = "~/GNS3/configs"
default_symbol_theme: BuiltinSymbolTheme = BuiltinSymbolTheme.affinity_square_blue default_symbol_theme: BuiltinSymbolTheme = BuiltinSymbolTheme.affinity_square_blue
allow_raw_images: bool = True allow_raw_images: bool = True
auto_discover_images: bool = True
report_errors: bool = True report_errors: bool = True
additional_images_paths: List[str] = Field(default_factory=list) additional_images_paths: List[str] = Field(default_factory=list)
console_start_port_range: int = Field(5000, gt=0, le=65535) console_start_port_range: int = Field(5000, gt=0, le=65535)

@ -136,7 +136,8 @@ async def discover_images(image_type: str, skip_image_paths: list = None) -> Lis
files = set() files = set()
images = [] images = []
for directory in images_directories(image_type): for directory in images_directories(image_type, include_parent_directory=False):
log.info(f"Discovering images in '{directory}'")
for root, _, filenames in os.walk(os.path.normpath(directory)): for root, _, filenames in os.walk(os.path.normpath(directory)):
for filename in filenames: for filename in filenames:
if filename.endswith(".tmp") or filename.endswith(".md5sum") or filename.startswith("."): if filename.endswith(".tmp") or filename.endswith(".md5sum") or filename.startswith("."):
@ -189,7 +190,7 @@ def default_images_directory(image_type):
raise NotImplementedError(f"%s node type is not supported", image_type) raise NotImplementedError(f"%s node type is not supported", image_type)
def images_directories(image_type): def images_directories(image_type, include_parent_directory=True):
""" """
Return all directories where we will look for images Return all directories where we will look for images
by priority by priority
@ -199,7 +200,7 @@ def images_directories(image_type):
server_config = Config.instance().settings.Server server_config = Config.instance().settings.Server
paths = [] paths = []
img_dir = os.path.expanduser(server_config.images_path)
type_img_directory = default_images_directory(image_type) type_img_directory = default_images_directory(image_type)
try: try:
os.makedirs(type_img_directory, exist_ok=True) os.makedirs(type_img_directory, exist_ok=True)
@ -208,8 +209,10 @@ def images_directories(image_type):
pass pass
for directory in server_config.additional_images_paths: for directory in server_config.additional_images_paths:
paths.append(directory) paths.append(directory)
# Compatibility with old topologies we look in parent directory if include_parent_directory:
paths.append(img_dir) # Compatibility with old topologies we look in parent directory
img_dir = os.path.expanduser(server_config.images_path)
paths.append(img_dir)
# Return only the existing paths # Return only the existing paths
return [force_unix_path(p) for p in paths if os.path.exists(p)] return [force_unix_path(p) for p in paths if os.path.exists(p)]

Loading…
Cancel
Save