From 1e38b11f3494c68aa9fd80bfcd8b2abbd8f298d4 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Wed, 13 May 2015 10:16:24 +0200 Subject: [PATCH 1/9] Catch crash error in IOU in case of permission denied Fix #186 --- gns3server/modules/iou/iou_vm.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gns3server/modules/iou/iou_vm.py b/gns3server/modules/iou/iou_vm.py index b7214bd4..d666fc95 100644 --- a/gns3server/modules/iou/iou_vm.py +++ b/gns3server/modules/iou/iou_vm.py @@ -433,7 +433,10 @@ class IOUVM(BaseVM): yield from self._library_check() - self._rename_nvram_file() + try: + self._rename_nvram_file() + except OSError as e: + raise IOUError("Could not rename nvram files: {}".format(e)) iourc_path = self.iourc_path if iourc_path is None: From 3704911c2dd236c40ab05c7a06190ba614fd371b Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Wed, 13 May 2015 10:19:50 +0200 Subject: [PATCH 2/9] Fix tests --- tests/modules/qemu/test_qemu_vm.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/modules/qemu/test_qemu_vm.py b/tests/modules/qemu/test_qemu_vm.py index 5d00e1c5..ac939473 100644 --- a/tests/modules/qemu/test_qemu_vm.py +++ b/tests/modules/qemu/test_qemu_vm.py @@ -272,12 +272,13 @@ def test_build_command(vm, loop, fake_qemu_binary, port_manager): os.path.join(vm.working_dir, "flash.qcow2"), "-serial", "telnet:127.0.0.1:{},server,nowait".format(vm.console), + "-net", + "none", "-device", - "e1000,mac=00:00:ab:0e:0f:00,netdev=gns3-0", - "-netdev", - "user,id=gns3-0" + "e1000,mac=00:00:ab:0e:0f:00" ] + @pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows") def test_build_command_without_display(vm, loop, fake_qemu_binary): @@ -313,6 +314,7 @@ def test_hdb_disk_image(vm, tmpdir): vm.hdb_disk_image = "test" assert vm.hdb_disk_image == str(tmpdir / "QEMU" / "test") + def test_hdc_disk_image(vm, tmpdir): with patch("gns3server.config.Config.get_section_config", return_value={"images_path": str(tmpdir)}): @@ -321,6 +323,7 @@ def test_hdc_disk_image(vm, tmpdir): vm.hdc_disk_image = "test" assert vm.hdc_disk_image == str(tmpdir / "QEMU" / "test") + def test_hdd_disk_image(vm, tmpdir): with patch("gns3server.config.Config.get_section_config", return_value={"images_path": str(tmpdir)}): From 157bc18ebd1df53d5d2d44d5e7c9541a231ccf49 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Wed, 13 May 2015 14:29:03 +0200 Subject: [PATCH 3/9] Use a temporary directory as egg cache We have use with broken permission on their system. We try to workaround the issue. Fix #182 --- gns3server/main.py | 10 ++++++++ gns3server/utils/get_resource.py | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 gns3server/utils/get_resource.py diff --git a/gns3server/main.py b/gns3server/main.py index 30360876..e0bf9af2 100644 --- a/gns3server/main.py +++ b/gns3server/main.py @@ -16,6 +16,16 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . + +# WARNING +# Due to buggy user machines we choose to put this as the first loading modules +# otherwise the egg cache is initialized in his standard location and +# if is not writetable the application crash. It's the user fault +# because one day the user as used sudo to run an egg and break his +# filesystem permissions, but it's a common mistake. +import gns3server.utils.get_resource + + import os import datetime import sys diff --git a/gns3server/utils/get_resource.py b/gns3server/utils/get_resource.py new file mode 100644 index 00000000..f28152ab --- /dev/null +++ b/gns3server/utils/get_resource.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2015 GNS3 Technologies Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import tempfile +import pkg_resources +import atexit +import logging + +log = logging.getLogger(__name__) + +try: + egg_cache_dir = tempfile.mkdtemp() + pkg_resources.set_extraction_path(dir) +except ValueError: + # If the path is already set the module throw an error + pass + + +@atexit.register +def clean_egg_cache(): + try: + import shutil + log.debug("Clean egg cache %s", egg_cache_dir) + shutil.rmtree(egg_cache_dir) + except Exception: + # We don't care if we can not cleanup + pass From a3c0f0754efb61834edd2b044bc881a2214e8c45 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Wed, 13 May 2015 23:27:51 +0200 Subject: [PATCH 4/9] Fix crash --- gns3server/utils/get_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gns3server/utils/get_resource.py b/gns3server/utils/get_resource.py index f28152ab..dae285fc 100644 --- a/gns3server/utils/get_resource.py +++ b/gns3server/utils/get_resource.py @@ -24,7 +24,7 @@ log = logging.getLogger(__name__) try: egg_cache_dir = tempfile.mkdtemp() - pkg_resources.set_extraction_path(dir) + pkg_resources.set_extraction_path(egg_cache_dir) except ValueError: # If the path is already set the module throw an error pass From dd9f62158fbd2a8deca149380d12b5268e39a4fa Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 13 May 2015 15:53:58 -0600 Subject: [PATCH 5/9] Fixes bugs with IOS router configs. Fixes #354. --- .../handlers/api/dynamips_vm_handler.py | 38 ++++++++++--------- gns3server/modules/dynamips/__init__.py | 10 +++-- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/gns3server/handlers/api/dynamips_vm_handler.py b/gns3server/handlers/api/dynamips_vm_handler.py index 5b501815..cfb919ba 100644 --- a/gns3server/handlers/api/dynamips_vm_handler.py +++ b/gns3server/handlers/api/dynamips_vm_handler.py @@ -367,15 +367,16 @@ class DynamipsVMHandler: else: # nvram doesn't contain anything if the router has not been started at least once # in this case just use the startup-config file - startup_config_path = os.path.join(module_workdir, vm.startup_config) - if os.path.exists(startup_config_path): - try: - with open(startup_config_path, "rb") as f: - content = f.read().decode("utf-8", errors='replace') - if content: - result["startup_config_content"] = content - except OSError as e: - raise DynamipsError("Could not read the startup-config {}: {}".format(startup_config_path, e)) + if vm.startup_config: + startup_config_path = os.path.join(module_workdir, vm.startup_config) + if os.path.isfile(startup_config_path): + try: + with open(startup_config_path, "rb") as f: + content = f.read().decode("utf-8", errors='replace') + if content: + result["startup_config_content"] = content + except OSError as e: + raise DynamipsError("Could not read the startup-config {}: {}".format(startup_config_path, e)) if private_config_base64: private_config_content = base64.b64decode(private_config_base64).decode("utf-8", errors='replace') @@ -383,15 +384,16 @@ class DynamipsVMHandler: else: # nvram doesn't contain anything if the router has not been started at least once # in this case just use the private-config file - private_config_path = os.path.join(module_workdir, vm.private_config) - if os.path.exists(private_config_path): - try: - with open(private_config_path, "rb") as f: - content = f.read().decode("utf-8", errors='replace') - if content: - result["private_config_content"] = content - except OSError as e: - raise DynamipsError("Could not read the private-config {}: {}".format(private_config_path, e)) + if vm.private_config: + private_config_path = os.path.join(module_workdir, vm.private_config) + if os.path.isfile(private_config_path): + try: + with open(private_config_path, "rb") as f: + content = f.read().decode("utf-8", errors='replace') + if content: + result["private_config_content"] = content + except OSError as e: + raise DynamipsError("Could not read the private-config {}: {}".format(private_config_path, e)) response.set_status(200) response.json(result) diff --git a/gns3server/modules/dynamips/__init__.py b/gns3server/modules/dynamips/__init__.py index 38aeac83..a8bb51e2 100644 --- a/gns3server/modules/dynamips/__init__.py +++ b/gns3server/modules/dynamips/__init__.py @@ -535,17 +535,19 @@ class Dynamips(BaseManager): default_private_config_path = os.path.join(module_workdir, "configs", "i{}_private-config.cfg".format(vm.dynamips_id)) startup_config_path = settings.get("startup_config") + startup_config_content = settings.get("startup_config_content") if startup_config_path: yield from vm.set_configs(startup_config_path) - else: - startup_config_path = self._create_config(vm, default_startup_config_path, settings.get("startup_config_content")) + elif startup_config_content: + startup_config_path = self._create_config(vm, default_startup_config_path, startup_config_content) yield from vm.set_configs(startup_config_path) private_config_path = settings.get("private_config") + private_config_content = settings.get("private_config_content") if private_config_path: yield from vm.set_configs(vm.startup_config, private_config_path) - else: - private_config_path = self._create_config(vm, default_private_config_path, settings.get("private_config_content")) + elif private_config_content: + private_config_path = self._create_config(vm, default_private_config_path, private_config_content) yield from vm.set_configs(vm.startup_config, private_config_path) def _create_config(self, vm, path, content=None): From b2457e0b3b6d43e156d14d202ae8fdc7d129eff8 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 13 May 2015 16:05:54 -0600 Subject: [PATCH 6/9] Check for empty iourc path. --- gns3server/modules/iou/iou_vm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gns3server/modules/iou/iou_vm.py b/gns3server/modules/iou/iou_vm.py index d666fc95..d826a2ab 100644 --- a/gns3server/modules/iou/iou_vm.py +++ b/gns3server/modules/iou/iou_vm.py @@ -439,8 +439,8 @@ class IOUVM(BaseVM): raise IOUError("Could not rename nvram files: {}".format(e)) iourc_path = self.iourc_path - if iourc_path is None: - raise IOUError("Could not find a iourc file (IOU license)") + if not iourc_path: + raise IOUError("Could not find an iourc file (IOU license)") if not os.path.isfile(iourc_path): raise IOUError("The iourc path '{}' is not a regular file".format(iourc_path)) From 078b72cafdb987552f25ab6d6482c5ff4b5352e3 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Thu, 14 May 2015 18:57:30 +0200 Subject: [PATCH 7/9] Version 1.3.3 --- CHANGELOG | 7 +++++++ gns3server/version.py | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 91835c49..abf6dca2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,12 @@ # Change Log +## 1.3.3 14/05/15 + +* Check for empty iourc path. +* Fixes bugs with IOS router configs. Fixes #354. +* Use a temporary directory as egg cache +* Catch crash error in IOU in case of permission denied + ## 1.3.3rc1 07/05/2015 * Return an error if an adapter slot doesn't exist on an IOS router. diff --git a/gns3server/version.py b/gns3server/version.py index aa2d4e2a..01b6d7f1 100644 --- a/gns3server/version.py +++ b/gns3server/version.py @@ -23,5 +23,5 @@ # or negative for a release candidate or beta (after the base version # number has been incremented) -__version__ = "1.3.3.dev3" -__version_info__ = (1, 3, 3, -99) +__version__ = "1.3.3" +__version_info__ = (1, 3, 3, 0) From 76be91d544081df1871d629467fa3dbffa42482b Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Thu, 14 May 2015 19:23:21 +0200 Subject: [PATCH 8/9] 1.3.4dev1 --- gns3server/version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gns3server/version.py b/gns3server/version.py index 01b6d7f1..b6e4f133 100644 --- a/gns3server/version.py +++ b/gns3server/version.py @@ -23,5 +23,5 @@ # or negative for a release candidate or beta (after the base version # number has been incremented) -__version__ = "1.3.3" -__version_info__ = (1, 3, 3, 0) +__version__ = "1.3.4.dev1" +__version_info__ = (1, 3, 4, -99) From 5bb870dc0f0b5065e7fbf4aa380205076af3a9af Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Thu, 14 May 2015 19:28:26 +0200 Subject: [PATCH 9/9] New crash report key --- gns3server/crash_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gns3server/crash_report.py b/gns3server/crash_report.py index 89800189..23ee7bc0 100644 --- a/gns3server/crash_report.py +++ b/gns3server/crash_report.py @@ -40,7 +40,7 @@ class CrashReport: Report crash to a third party service """ - DSN = "sync+https://45147533567b4d529ca09c093758681f:12d8b456cdb34d23aba771325aa64ee6@app.getsentry.com/38482" + DSN = "sync+https://9e6f04df72c74b6894a6dcd2928d069e:2035d1beb1654136b170f1e91f05ee51@app.getsentry.com/38482" if hasattr(sys, "frozen"): cacert = os.path.join(os.getcwd(), "cacert.pem") if os.path.isfile(cacert):