diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index 4b8a5001..9f947673 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -29,6 +29,8 @@ except ImportError: from importlib import resources as importlib_resources from ..config import Config +from ..utils import parse_version + from .project import Project from .template import Template from .appliance import Appliance @@ -69,7 +71,7 @@ class Controller: async def start(self): log.info("Controller is starting") - self._load_base_files() + self._install_base_configs() server_config = Config.instance().get_section_config("Server") Config.instance().listen_for_config_changes(self._update_config) host = server_config.get("host", "localhost") @@ -246,7 +248,9 @@ class Controller: if "iou_license" in controller_settings: self._iou_license_settings = controller_settings["iou_license"] - self._appliance_manager.install_builtin_appliances() + if parse_version(__version__) > parse_version(controller_settings.get("version", "")): + self._appliance_manager.install_builtin_appliances() + self._appliance_manager.appliances_etag = controller_settings.get("appliances_etag") self._appliance_manager.load_appliances() self._template_manager.load_templates(controller_settings.get("templates")) @@ -274,13 +278,14 @@ class Controller: except OSError as e: log.error(str(e)) - def _load_base_files(self): + def _install_base_configs(self): """ At startup we copy base file to the user location to allow them to customize it """ dst_path = self.configs_path() + log.info(f"Installing base configs in '{dst_path}'") try: if hasattr(sys, "frozen") and sys.platform.startswith("win"): resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), "configs")) diff --git a/gns3server/controller/appliance_manager.py b/gns3server/controller/appliance_manager.py index ea2b294a..15c4da70 100644 --- a/gns3server/controller/appliance_manager.py +++ b/gns3server/controller/appliance_manager.py @@ -81,13 +81,15 @@ class ApplianceManager: os.makedirs(appliances_path, exist_ok=True) return appliances_path - def _builtin_appliances_path(self): + def _builtin_appliances_path(self, delete_first=False): """ Get the built-in appliance storage directory """ config = Config.instance() appliances_dir = os.path.join(config.config_dir, "appliances") + if delete_first: + shutil.rmtree(appliances_dir, ignore_errors=True) os.makedirs(appliances_dir, exist_ok=True) return appliances_dir @@ -96,17 +98,17 @@ class ApplianceManager: At startup we copy the built-in appliances files. """ - dst_path = self._builtin_appliances_path() + dst_path = self._builtin_appliances_path(delete_first=True) + log.info(f"Installing built-in appliances in '{dst_path}'") try: if hasattr(sys, "frozen") and sys.platform.startswith("win"): resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), "appliances")) for filename in os.listdir(resource_path): - if not os.path.exists(os.path.join(dst_path, filename)): - shutil.copy(os.path.join(resource_path, filename), os.path.join(dst_path, filename)) + shutil.copy(os.path.join(resource_path, filename), os.path.join(dst_path, filename)) else: for entry in importlib_resources.files('gns3server.appliances').iterdir(): full_path = os.path.join(dst_path, entry.name) - if entry.is_file() and not os.path.exists(full_path): + if entry.is_file(): log.debug(f"Installing built-in appliance file {entry.name} to {full_path}") shutil.copy(str(entry), os.path.join(dst_path, entry.name)) except OSError as e: diff --git a/tests/controller/test_controller.py b/tests/controller/test_controller.py index 48ba98af..198556a1 100644 --- a/tests/controller/test_controller.py +++ b/tests/controller/test_controller.py @@ -381,13 +381,13 @@ async def test_get_free_project_name(controller): assert controller.get_free_project_name("Hello") == "Hello" -async def test_load_base_files(controller, config, tmpdir): +async def test_install_base_configs(controller, config, tmpdir): config.set_section_config("Server", {"configs_path": str(tmpdir)}) with open(str(tmpdir / 'iou_l2_base_startup-config.txt'), 'w+') as f: f.write('test') - controller._load_base_files() + controller._install_base_configs() assert os.path.exists(str(tmpdir / 'iou_l3_base_startup-config.txt')) # Check is the file has not been overwritten @@ -410,6 +410,7 @@ def test_appliances(controller, tmpdir): with open(str(tmpdir / "my_appliance2.gns3a"), 'w+') as f: json.dump(my_appliance, f) + controller.appliance_manager.install_builtin_appliances() with patch("gns3server.config.Config.get_section_config", return_value={"appliances_path": str(tmpdir)}): controller.appliance_manager.load_appliances() assert len(controller.appliance_manager.appliances) > 0