diff --git a/.gitignore b/.gitignore index 309de57..93008cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ __pycache__ *.pyc .venv +build diff --git a/AUTHORS b/AUTHORS index 608cba3..6f0d20c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,2 @@ -Jeremy Grossmann \ No newline at end of file +Jeremy Grossmann +Julien Duponchelle diff --git a/README.rst b/README.rst index d1cdaed..f97398a 100644 --- a/README.rst +++ b/README.rst @@ -4,35 +4,20 @@ GNS3-registry This is the GNS3 devices registry. -You need python 3.4 installed - -Add an image -************ +Build website +############# .. code:: bash - bin/gns3-get --add ~/Downloads/linux-microcore-3.4.1.img + python build.py -Search an image -**************** + +Run website +############# .. code:: bash - - bin/gns3-get --search core - - Micro Core Linux: - * hda_disk_image: - * 3.4.1 linux-microcore-3.4.1.img: fa2ec4b1fffad67d8103c3391bbf9df2 - * 4.0.2 linux-microcore-4.0.2-clean.img: e13d0d1c0b3999ae2386bba70417930c - - -Install a remote image -************************** - -If the image is available from the internet you can download and install it: - -.. code:: bash - - bin/gns3-get --install e13d0d1c0b3999ae2386bba70417930c - Download http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-microcore-4.0.2-clean.img to /Users/noplay/GNS3/images/linux-microcore-4.0.2-clean.img + python server.py + + + diff --git a/bin/gns3-get b/bin/gns3-get deleted file mode 100755 index eb851fe..0000000 --- a/bin/gns3-get +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -SCRIPT_PATH="${BASH_SOURCE[0]}"; -GNS3_REPOSITORY_DIR=`dirname ${SCRIPT_PATH}`/.. - -# Detect Python 3.4 installation - -PY34_TEST="import sys; sys.exit(1) if sys.version_info[0] != 3 or sys.version_info[1] < 4 else sys.exit(0)" - -if python -c "$PY34_TEST" 2> /dev/null -then - PYTHON="python" -elif python3 -c "$PY34_TEST" 2> /dev/null -then - PYTHON="python3" -elif python3.4 -c "$PY34_TEST" 2> /dev/null -then - PYTHON="python3.4" -elif python34 -c "$PY34_TEST" 2> /dev/null -then - PYTHON="python34" -else - echo "No Python 3.4 installation" - - echo "On debian based distribution": - echo "apt-get install python3" - - echo "On MacOSX:" - echo "brew install python3" - echo "port install python34" - exit 1 -fi - -$PYTHON -m venv $GNS3_REPOSITORY_DIR/.venv -source $GNS3_REPOSITORY_DIR/.venv/bin/activate - -$PYTHON $GNS3_REPOSITORY_DIR/gns3registry/main.py --test -if [ $? -ne 0 ] -then - $PYTHON -m pip install -r $GNS3_REPOSITORY_DIR/requirements.txt -fi - -$PYTHON $GNS3_REPOSITORY_DIR/gns3registry/main.py $* - diff --git a/build.py b/build.py new file mode 100644 index 0000000..d78c76e --- /dev/null +++ b/build.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# 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 os +import sys +import json +import shutil + +from jinja2 import Environment, FileSystemLoader + +import logging +log = logging.getLogger(__name__) +log.setLevel(logging.DEBUG) + +handler = logging.StreamHandler(sys.stdout) +formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') +handler.setFormatter(formatter) +log.addHandler(handler) + +if os.path.exists('build'): + for file in os.listdir('build'): + if os.path.isdir(os.path.join('build', file)): + shutil.rmtree(os.path.join('build', file)) + else: + os.remove(os.path.join('build', file)) +else: + os.mkdir('build') +os.mkdir(os.path.join('build', 'devices')) + + +def render(template_file, out, **kwargs): + log.info('Build %s', out) + env = Environment(loader=FileSystemLoader('templates')) + env.filters['jsonify'] = json.dumps + template = env.get_template(template_file) + template.stream(**kwargs).dump(os.path.join('build', out)) + + +render('index.html', 'index.html') + + +devices = [] +for file in os.listdir('devices'): + filename = file[:-5] + with open(os.path.join('devices', file)) as f: + device = json.load(f) + device['id'] = filename + render('device.html', os.path.join('devices', filename + '.html'), device=device) + devices.append(device) + + +render('devices.html', os.path.join('devices', 'index.html'), devices=devices) diff --git a/gns3registry/__init__.py b/gns3registry/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/gns3registry/config.py b/gns3registry/config.py deleted file mode 100644 index 6a58c26..0000000 --- a/gns3registry/config.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/env python -# -*- 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 json -import sys -import os -import shlex -import subprocess -from gns3registry.image import Image - - -class ConfigException(Exception): - pass - - -class Config: - """ - GNS3 config file - """ - - def __init__(self, path=None): - """ - :params path: Path of the configuration file otherwise detect it on the system - """ - - #TODO: Manage errors - self.path = path - if self.path is None: - self.path = self._get_standard_config_file_path() - - with open(self.path) as f: - self._config = json.load(f) - - @property - def images_dir(self): - """ - :returns: Localion of the images directory on the server - """ - return self._config["LocalServer"]["images_path"] - - def _get_standard_config_file_path(self): - if sys.platform.startswith("win"): - filename = "gns3_gui.ini" - else: - filename = "gns3_gui.conf" - - appname = "GNS3" - - if sys.platform.startswith("win"): - appdata = os.path.expandvars("%APPDATA%") - return os.path.join(appdata, appname, filename) - else: - home = os.path.expanduser("~") - return os.path.join(home, ".config", appname, filename) - - def add_images(self, device_config): - """ - Add images to the user configuration - """ - new_config = { - "server": "local", - "name": device_config["name"] - } - if device_config["category"] == "guest": - new_config["category"] = 2 - elif device_config["category"] == "router": - new_config["category"] = 0 - - if "qemu" in device_config: - self._add_qemu_config(new_config, device_config) - - def _add_qemu_config(self, new_config, device_config): - - new_config["adapter_type"] = device_config["qemu"]["adapter_type"] - new_config["adapters"] = device_config["qemu"]["adapters"] - new_config["cpu_throttling"] = 0 - new_config["ram"] = device_config["qemu"]["ram"] - new_config["legacy_networking"] = False - new_config["process_priority"] = "normal" - - new_config["initrd"] = "" - new_config["kernel_command_line"] = "" - new_config["kernel_image"] = "" - - if device_config["qemu"].get("graphic", False): - options = "" - else: - options = "-nographic " - options += device_config["qemu"].get("options", "") - - new_config["options"] = options.strip() - - new_config["hda_disk_image"] = device_config["qemu"].get("hda_disk_image", "") - new_config["hdb_disk_image"] = device_config["qemu"].get("hdb_disk_image", "") - new_config["hdc_disk_image"] = device_config["qemu"].get("hdc_disk_image", "") - new_config["hdd_disk_image"] = device_config["qemu"].get("hdd_disk_image", "") - - new_config["qemu_path"] = self._get_qemu_binary(device_config) - - if device_config["category"] == "guest": - new_config["default_symbol"] = ":/symbols/qemu_guest.normal.svg" - new_config["hover_symbol"] = ":/symbols/qemu_guest.selected.svg" - elif device_config["category"] == "router": - new_config["default_symbol"] = ":/symbols/router.normal.svg" - new_config["hover_symbol"] = ":/symbols/router.selected.svg" - - disks = ["hda_disk_image", "hdb_disk_image", "hdc_disk_image", "hdd_disk_image", "cdrom"] - for disk in disks: - if disk in device_config["images"]: - if isinstance(device_config["images"][disk], list): - require_images = "" - for image in device_config["images"][disk]: - require_images += "* {}\n".format(image["filename"]) - raise ConfigException("Missing image for {} you should provide one of the following images:\n{}".format(disk, require_images)) - else: - new_config["name"] += " {}".format(device_config["images"][disk].version) - new_config[disk] = self._relative_image_path(device_config["images"][disk].path) - - - if device_config["qemu"].get("install_cdrom_to_hda", False): - new_config["hda_disk_image"] = self._create_qemu_img(device_config, new_config) - if "cdrom" in new_config: - self._install_qemu_cdrom(device_config, new_config) - del new_config["cdrom"] - - # Remove VM with the same Name - self._config["Qemu"]["vms"] = [item for item in self._config["Qemu"]["vms"] if item["name"] != new_config["name"]] - - self._config["Qemu"]["vms"].append(new_config) - - def _relative_image_path(self, path): - """ - :returns: Path relative to image directory if image is inside or full path - """ - print(os.path.dirname(path)) - print(self.images_dir) - if os.path.dirname(path) == self.images_dir: - return os.path.basename(path) - return path - - def _get_qemu_binary(self, device_config): - """ - Create a blank hda disk image - - :param device_config: The require device configuration - """ - #TODO: Manage Windows - if device_config["qemu"]["processor"] == "i386": - return "qemu-system-i386" - elif device_config["qemu"]["processor"] == "x64": - return "qemu-system-x86_64" - - def _create_qemu_img(self, device_config, new_config): - """ - Create a blank hda disk image - - :param device_config: The require device configuration - :param new_config: The GNS3 device configuration - :returns: Return new disk path - """ - #TODO: Manage error - image_path = os.path.join(self.images_dir, "QEMU", device_config["qemu"]["hda_disk_image"]) - #TODO: raise an error if size is missing - cmd = ["qemu-img", "create", "-f", "qcow2", image_path, device_config["qemu"]["hda_disk_size"]] - print(" ".join(cmd)) - subprocess.call(cmd) - return image_path - - def _install_qemu_cdrom(self, device_config, new_config): - """ - Install the cdrom to disk - - :param device_config: The require device configuration - :param new_config: The GNS3 device configuration - """ - - print("Starting cdrom installation. Please follow the instructions in the qemu Windows and close qemu when install is finish in order to finish the process.") - print("\nInstall instructions:") - print(device_config["qemu"]["install_instructions"]) - cmd = "{options} -cdrom {cdrom} -m {ram} {hda}".format( - options=device_config.get("options", ""), - cdrom=device_config["images"]["cdrom"].path, - ram=device_config["qemu"]["ram"], - hda=new_config["hda_disk_image"]) - self._qemu_run(device_config, cmd.strip()) - - def _qemu_run(self, device_config, cmd): - """ - Run the qemu command - """ - cmd = shlex.split(cmd) - cmd.insert(0, self._get_qemu_binary(device_config)) - print(" ".join(cmd)) - subprocess.call(cmd) - - def save(self): - """ - Save the configuration file - """ - with open(self.path, "w+") as f: - json.dump(self._config, f, indent=4) - diff --git a/gns3registry/image.py b/gns3registry/image.py deleted file mode 100644 index f75212a..0000000 --- a/gns3registry/image.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- 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 hashlib - - -class Image: - """ - A disk image - """ - - def __init__(self, path): - """ - :params: path of the image - """ - self.path = path - self._md5sum = None - self._version = None - - @property - def version(self): - """ - :returns: Get the file version / release - """ - return self._version - - @version.setter - def version(self, version): - """ - :returns: Set the file version / release - """ - self._version = version - - @property - def md5sum(self): - """ - Compute a md5 hash for file - - :returns: hexadecimal md5 - """ - - if self._md5sum is None: - m = hashlib.md5() - with open(self.path, "rb") as f: - while True: - buf = f.read(4096) - if not buf: - break - m.update(buf) - self._md5sum = m.hexdigest() - return self._md5sum diff --git a/gns3registry/main.py b/gns3registry/main.py deleted file mode 100644 index e3c0f6e..0000000 --- a/gns3registry/main.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python -# -*- 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 argparse -import sys -import os -import math -from distutils.util import strtobool - -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) - -from gns3registry.registry import Registry -from gns3registry.config import Config, ConfigException - - -def yes_no(message): - while True: - try: - return strtobool(input("{} (y/n) ".format(message)).lower()) - except ValueError: - pass - -def download_progress_callback(count, blockSize, totalSize): - """ - Callback called when a file is downloading - """ - - if totalSize == -1: - sys.stdout.write("Unknow size downloading...\n") - - percent = int(count * blockSize * 100/totalSize) - sys.stdout.write("\r[{}{}] {} %".format("#" * math.floor(percent / 2), " " * math.ceil(100 / 2 - percent / 2), percent)) - if count * blockSize == totalSize: - sys.stdout.write("\n") - sys.stdout.flush() - -registry = Registry(download_progress_callback=download_progress_callback) -config = Config() - - -def add_images(images): - print("WARNING WARNING WARNING") - print("It's experimental") - print("") - - confs = registry.detect_images(images) - if len(confs) > 0: - print("Found: {} devices configuration".format(len(confs))) - for conf in confs: - if yes_no("Add {}?".format(conf["name"])): - try: - config.add_images(conf) - except ConfigException as e: - print(e, file=sys.stderr) - sys.exit(1) - config.save() - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Manage GNS3 registry") - parser.add_argument("--add", dest="add_images", action="store", nargs='+', - help="Add images to GNS3") - parser.add_argument("--search", dest="search", action="store", - help="Search an image for GNS3") - parser.add_argument("--install", dest="install", action="store", - help="Download and install an image for GNS3") - parser.add_argument("--test", dest="test", action="store_true", - help="Test if installation of gns3 registry is OK") - - args = parser.parse_args() - - if args.test: - sys.exit(0) - - if args.add_images: - add_images(args.add_images) - elif args.search: - print("Available images\n") - for res in registry.search_device(args.search): - print("{}: ".format(res["name"])) - for image_type in res["images"]: - print(" * {}:".format(image_type)) - for file in res["images"][image_type]: - print(" * {} {}: {}".format(file["version"], file["filename"], file["md5sum"])) - elif args.install: - image = registry.download_image(args.install, config.images_dir) - if image: - add_images([image]) - else: - parser.print_help() - sys.exit(1) - diff --git a/gns3registry/registry.py b/gns3registry/registry.py deleted file mode 100644 index 19ebb0a..0000000 --- a/gns3registry/registry.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python -# -*- 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 hashlib -import json -import os -import re -import urllib.request - -from gns3registry.image import Image - - -class Registry: - def __init__(self, download_progress_callback=None): - """ - :param download_progress_callback: Callback called when a file is downloaded - """ - self._download_progress_callback = download_progress_callback - - def detect_images(self, images_path): - """ - :param images_path: Array of path to images - :returns: Array of configuration corresponding to the image - """ - - images = [] - - for path in images_path: - images.append(Image(path)) - - configurations = [] - - #TODO: Manage open error - for config in self._all_configs(): - - matched = False - for image in images: - if self._image_match(image, config): - matched = True - if matched: - configurations.append(config) - - return configurations - - def download_image(self, md5sum, images_dir): - for config in self._all_configs(): - for image_type in config.get("images", {}): - for file in config["images"].get(image_type, []): - if file["md5sum"] == md5sum: - path = os.path.join(images_dir, "QEMU", file["filename"]) - - if "direct_download_url" in file: - print("Download {} to {}".format(file["direct_download_url"], path)) - #TODO: Skip download if file already exist with same sha1 - urllib.request.urlretrieve(file["direct_download_url"], path, reporthook=self._download_progress_callback) - return path - else: - print("You need to manually download the image {filename} from:\n{download_url}\n\nAnd run: ./bin/gns3-get --add {filename}".format(filename=file["filename"], download_url=file["download_url"])) - return None - - def search_device(self, query): - results = [] - for config in self._all_configs(): - if re.match(r".*{}.*".format(query), config["name"], flags=re.IGNORECASE): - results.append(config) - return results - - def _all_configs(self): - """ - Iterate on all configs available on devices - """ - devices_path = self._get_devices_path() - for (dirpath, dirnames, filenames) in os.walk(devices_path): - for filename in filenames: - file = os.path.join(dirpath, filename) - if file.endswith(".json"): - with open(os.path.join(devices_path, file)) as f: - config = json.load(f) - yield config - - def _image_match(self, image, config): - """ - :returns: True if image is present in configuration - """ - matched = False - - for image_type in config.get("images", {}): - images = config["images"].get(image_type, []) - # If it's not a list it's mean we have already detect the image - if not isinstance(images, list): - continue - for file in images: - if isinstance(file, dict): - if file.get("md5sum", None) == image.md5sum: - image.version = file["version"] - config["images"][image_type] = image - matched = True - return matched - - def _get_devices_path(self): - """ - Get the path where the registry files are located - """ - path = os.path.abspath(os.path.dirname(__file__)) - return os.path.join(path, "..", "devices") diff --git a/requirements.txt b/requirements.txt index 68c1bb9..d1f1d25 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -jsonschema==2.4.0 +Jinja2==2.7.3 diff --git a/test/conftest.py b/server.py similarity index 56% rename from test/conftest.py rename to server.py index 2f5ab07..6ae30cc 100644 --- a/test/conftest.py +++ b/server.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +#!/usr/bin/env python # # Copyright (C) 2015 GNS3 Technologies Inc. # @@ -15,24 +15,15 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import pytest -import urllib.request -import tempfile import os +import http.server +import socketserver -@pytest.fixture -def linux_microcore_img(): +PORT = 8001 - path = os.path.join(tempfile.tempdir, "linux-microcore-3.4.1.img") - if not os.path.exists(path): - urllib.request.urlretrieve("http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-microcore-3.4.1.img?r=&ts=1432209459&use_mirror=heanet", path) - return path +os.chdir('build') +Handler = http.server.SimpleHTTPRequestHandler +httpd = socketserver.TCPServer(('', PORT), Handler) - -@pytest.fixture -def empty_file(tmpdir): - - path = str(tmpdir / "a") - open(path, "w+").close() - return path +print('Serving at port', PORT) +httpd.serve_forever() diff --git a/templates/device.html b/templates/device.html new file mode 100644 index 0000000..76bc502 --- /dev/null +++ b/templates/device.html @@ -0,0 +1,20 @@ +{% extends "layout/default.html" %} +{% block body %} +
+

{{ device["name"] }}

+ Vendor: {{ device["vendor_name"] }} +
+ Documentation: {{ device["documentation_url"] }} +
+ {% for image_type in device["images"] %} +

Images for {{image_type}}

+
    + {% for image in device["images"][image_type] %} +

    {{image["filename"]}}

    + Version: {{image["version"]}}
    + Checksum: {{image["md5sum"]}}
    + + {% endfor %} +
+ {% endfor %} +{% endblock %} diff --git a/templates/devices.html b/templates/devices.html new file mode 100644 index 0000000..76c8932 --- /dev/null +++ b/templates/devices.html @@ -0,0 +1,8 @@ +{% extends "layout/default.html" %} +{% block body %} + +{% endblock %} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..2ea801d --- /dev/null +++ b/templates/index.html @@ -0,0 +1,7 @@ +{% extends "layout/default.html" %} +{% block body %} +
+

Hello Networker!

+

Show devices

+
+{% endblock %} diff --git a/templates/layout/default.html b/templates/layout/default.html new file mode 100644 index 0000000..1fe02a0 --- /dev/null +++ b/templates/layout/default.html @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + +
+ {% block body %}{% endblock %} +
+ + diff --git a/test/test_config.py b/test/test_config.py deleted file mode 100644 index 897d049..0000000 --- a/test/test_config.py +++ /dev/null @@ -1,253 +0,0 @@ -#!/usr/bin/env python -# -*- 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 pytest -import json -import os -from unittest.mock import MagicMock, patch - -from gns3registry.config import Config, ConfigException -from gns3registry.image import Image - - -@pytest.fixture(scope="function") -def empty_config(tmpdir): - config = { - "LocalServer": { - "allow_console_from_anywhere": False, - "auto_start": False, - "console_end_port_range": 5000, - "console_start_port_range": 2001, - "host": "127.0.0.1", - "images_path": str(tmpdir), - "path": "", - "port": 8000, - "projects_path": str(tmpdir), - "report_errors": False, - "udp_end_port_range": 20000, - "udp_start_port_range": 10000 - }, - "Dynamips": { - "allocate_aux_console_ports": False, - "dynamips_path": "/Applications/GNS3.app/Contents/Resources/dynamips", - "ghost_ios_support": True, - "mmap_support": True, - "routers": [ - { - } - ], - "sparse_memory_support": True, - "use_local_server": True - }, - "IOU": { - "devices": [ - { - } - ], - "iourc_path": "/Users/noplay/code/gns3/gns3-vagrant/images/iou/iourc.txt", - "iouyap_path": "", - "license_check": True, - "use_local_server": False - }, - "Qemu": { - "use_local_server": True, - "vms": [ - ] - } - } - path = str(tmpdir / "config") - with open(path, "w+") as f: - json.dump(config, f) - return Config(path) - - -def test_add_images_guest(empty_config, linux_microcore_img): - with open("devices/microcore-linux.json") as f: - config = json.load(f) - image = Image(linux_microcore_img) - image.version = "3.4.1" - config["images"]["hda_disk_image"] = image - empty_config.add_images(config) - assert empty_config._config["Qemu"]["vms"][0] == { - "adapter_type": "e1000", - "adapters": 1, - "category": 2, - "cpu_throttling": 0, - "default_symbol": ":/symbols/qemu_guest.normal.svg", - "hda_disk_image": image.path, - "hdb_disk_image": "", - "hdc_disk_image": "", - "hdd_disk_image": "", - "hover_symbol": ":/symbols/qemu_guest.selected.svg", - "initrd": "", - "kernel_command_line": "", - "kernel_image": "", - "legacy_networking": False, - "name": "Micro Core Linux 3.4.1", - "options": "-nographic", - "process_priority": "normal", - "qemu_path": "qemu-system-i386", - "ram": 32, - "server": "local" - } - - -def test_add_images_cdrom(empty_config, linux_microcore_img): - with open("devices/hp-vsr1001.json") as f: - config = json.load(f) - - hda = os.path.join(empty_config.images_dir, "QEMU", "vsr1000-hp.img") - - image = Image(linux_microcore_img) - image.version = "7.10.R0204P01" - config["images"]["cdrom"] = image - - with patch("subprocess.call") as mock_qemu_img: - with patch("gns3registry.config.Config._qemu_run") as mock_qemu: - mock_qemu.return_value = hda - empty_config.add_images(config) - assert mock_qemu_img.called - args, kwargs = mock_qemu_img.call_args - assert args[0] == ["qemu-img", "create", "-f", "qcow2", hda, "8G"] - - assert mock_qemu.called - args, kwargs = mock_qemu.call_args - assert args[1] == "-cdrom {} -m 1024 {}".format(image.path, hda) - - assert empty_config._config["Qemu"]["vms"][0] == { - "adapter_type": "e1000", - "adapters": 16, - "category": 0, - "cpu_throttling": 0, - "default_symbol": ":/symbols/router.normal.svg", - "hda_disk_image": hda, - "hdb_disk_image": "", - "hdc_disk_image": "", - "hdd_disk_image": "", - "hover_symbol": ":/symbols/router.selected.svg", - "initrd": "", - "kernel_command_line": "", - "kernel_image": "", - "legacy_networking": False, - "name": "HP VSR1001 7.10.R0204P01", - "options": "", - "process_priority": "normal", - "qemu_path": "qemu-system-x86_64", - "ram": 1024, - "server": "local" - } - - -def test_add_images_router_two_disk(empty_config): - with open("devices/arista-veos.json") as f: - config = json.load(f) - - image = MagicMock() - image.version = "2.1.0" - image.md5sum = "ea9dc1989764fc6db1d388b061340743016214a7" - image.path = "/a" - config["images"]["hda_disk_image"] = image - - image = MagicMock() - image.version = "4.13.8M" - image.md5sum = "ff50656fe817c420e9f7fbb0c0ee41f1ca52fee2" - image.path = "/b" - config["images"]["hdb_disk_image"] = image - - empty_config.add_images(config) - assert empty_config._config["Qemu"]["vms"][0]["name"] == "Arista vEOS 2.1.0 4.13.8M" - - assert empty_config._config["Qemu"]["vms"][0] == { - "adapter_type": "e1000", - "adapters": 8, - "category": 0, - "cpu_throttling": 0, - "default_symbol": ":/symbols/router.normal.svg", - "hda_disk_image": "/a", - "hdb_disk_image": "/b", - "hdc_disk_image": "", - "hdd_disk_image": "", - "hover_symbol": ":/symbols/router.selected.svg", - "initrd": "", - "kernel_command_line": "", - "kernel_image": "", - "legacy_networking": False, - "name": "Arista vEOS 2.1.0 4.13.8M", - "options": "-nographic", - "process_priority": "normal", - "qemu_path": "qemu-system-x86_64", - "ram": 2048, - "server": "local" - } - - -def test_add_images_uniq(empty_config, linux_microcore_img): - with open("devices/microcore-linux.json") as f: - config = json.load(f) - - image = Image(linux_microcore_img) - image.version = "3.4.1" - config["images"]["hda_disk_image"] = image - - empty_config.add_images(config) - config["qemu"]["adapters"] = 2 - empty_config.add_images(config) - assert len(empty_config._config["Qemu"]["vms"]) == 1 - assert empty_config._config["Qemu"]["vms"][0]["adapters"] == 2 - - -def test_add_images_two_disk_one_missing(empty_config): - with open("devices/arista-veos.json") as f: - config = json.load(f) - - image = MagicMock() - image.version = "2.1.0" - image.md5sum = "ea9dc1989764fc6db1d388b061340743016214a7" - config["images"]["hda_disk_image"] = image - - with pytest.raises(ConfigException): - empty_config.add_images(config) - assert len(empty_config._config["Qemu"]["vms"]) == 0 - - -def test_add_image_path_relative_to_images_dir(empty_config, tmpdir, linux_microcore_img): - with open("devices/microcore-linux.json") as f: - config = json.load(f) - image = Image(linux_microcore_img) - image.version = "3.4.1" - image.path = str(tmpdir / "linux-microcore-3.4.1.img") - - config["images"]["hda_disk_image"] = image - empty_config.add_images(config) - assert empty_config._config["Qemu"]["vms"][0]["hda_disk_image"] == "linux-microcore-3.4.1.img" - - -def test_save(empty_config, linux_microcore_img): - - with open("devices/microcore-linux.json") as f: - config = json.load(f) - - image = Image(linux_microcore_img) - image.version = "3.4.1" - config["images"]["hda_disk_image"] = image - - empty_config.add_images(config) - empty_config.save() - with open(empty_config.path) as f: - assert "Micro Core" in f.read() diff --git a/test/test_registry.py b/test/test_registry.py deleted file mode 100644 index 2714e53..0000000 --- a/test/test_registry.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# -*- 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 pytest -import json - -from gns3registry.registry import Registry - - -def test_detect_image(linux_microcore_img): - - with open("devices/microcore-linux.json") as f: - config = json.load(f) - - registry = Registry() - detected = registry.detect_images([linux_microcore_img]) - assert detected[0]["name"] == "Micro Core Linux" - assert detected[0]["images"]["hda_disk_image"].version == "3.4.1" - - -def test_detect_two_image(linux_microcore_img): - - with open("devices/microcore-linux.json") as f: - config = json.load(f) - - registry = Registry() - detected = registry.detect_images([linux_microcore_img]) - assert detected[0]["name"] == "Micro Core Linux" - assert detected[0]["images"]["hda_disk_image"].version == "3.4.1" - - -def test_detect_unknow_image(empty_file): - registry = Registry() - assert registry.detect_images([empty_file]) == [] - - -def test_search_device(): - registry = Registry() - results = registry.search_device("Micro Core Linux") - assert len(results) == 1