diff --git a/.gitignore b/.gitignore index e4ff9349..ed797b2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.py[cod] __pycache__ +.pytest_cache #py.test .cache @@ -39,6 +40,7 @@ nosetests.xml .project .pydevproject .settings +.vscode # Pycharm .idea diff --git a/.travis.yml b/.travis.yml index e4f308b5..eb9ef803 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,6 @@ deploy: env: matrix: - - PYTHON_VERSION=3.4 - PYTHON_VERSION=3.5 - PYTHON_VERSION=3.6 + - PYTHON_VERSION=3.7 diff --git a/CHANGELOG b/CHANGELOG index f7e7cc88..d465edda 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,349 @@ # Change Log +## 2.2.0b1 21/05/2019 + +* Upgrade GNS3 Web UI to v2019.2.0-alpha.3 +* Change behavior when an IOU license is verified. Fixes https://github.com/GNS3/gns3-server/issues/1555 +* Fix Qemu VM state support after closing a project and check for JSON data returned by qemu-img. Fixes #1591 +* Ensure Qemu monitor commands are executed. Ref #1582. +* Set console type to "none" by default for Ethernet switches and add a warning if trying to use "telnet". Fixes https://github.com/GNS3/gns3-gui/issues/2776 +* Add %console-port% variable for additional Qemu options. Fixes https://github.com/GNS3/gns3-gui/issues/2786 +* Fix invalid reStructuredText for long description in setup.py +* Support for additional persistent docker volumes + +## 2.2.0a5 15/04/2019 + +* Back to the major.minor version for config files. Ref https://github.com/GNS3/gns3-gui/issues/2756 +* Fix templates missing after server restart. Fixes https://github.com/GNS3/gns3-gui/issues/2769 +* Fix bug when GNS3 VM were not saved. Fix tests. +* Some adjustments with compute WebSocket handling. Ref https://github.com/GNS3/gns3-server/issues/1564 +* Fix broken embedded console for Ethernet switch. Fixes #1574 +* Prevent locked nodes to be deleted. Fixes https://github.com/GNS3/gns3-gui/issues/2764 +* Remove old unused argument option. Fixes #1569 + +## 2.1.17 17/05/2019 + +* Force aiohttp version to 2.3.10 and aiohttp-cors version to 0.5.3 This is to fix build issue for Ubuntu 19.04 package on Launchpad. Ref #1583 https://github.com/GNS3/gns3-gui/issues/2774 + +## 2.1.16 15/04/2019 + +* Fix broken embedded console for Ethernet switch. Fixes #1574 +* Remove old unused argument option. Fixes #1569 + +## 2.2.0a4 05/04/2019 + +* Use the full version number for path to config files. Ref https://github.com/GNS3/gns3-gui/issues/2756 +* Support for docker images that set the USER directive. Changes the docker user to root for the init script to configure the network, then drops to the configured user (or root if one is not defined) for continuing booting the image. +* Fix packet filter not working for Ethernet switch and Ethernet hub. Fixes https://github.com/GNS3/gns3-gui/issues/2754 +* Fix remote packet capture for Dynamips. +* Fix remote packet capture and make sure packet capture is stopped when deleting an NIO. Fixes https://github.com/GNS3/gns3-gui/issues/2753 +* Store config files in version specific location +* Update pytest from 4.3.1 to 4.4.0 +* Fix opening previously saved 2.1 project grid overlapping. Fixes #2734 +* Fix empty theme name in symbol selection dialog. Fixes https://github.com/GNS3/gns3-gui/issues/2751 +* Bundle v2019.1.0-alpha.3 web-ui + +## 2.2.0a3 25/03/2019 + +* Fix traceback when starting packet capture on builtin nodes. Fixes https://github.com/GNS3/gns3-gui/issues/2743 +* Load v2019.1.0-alpha.2 of WebUI +* Fetch tags for update-bundled-web-ui.sh +* Fix mimetype for javascript, #1559 +* Serve WebUI via get_resource for freezed app +* Deactivate the embedded shell for Ethernet switch. Ref #1424 #1556 +* Fix VBoxManage fails if VM has specific special characters in name. Fixes #2739 +* Fix IOU symlink issue on remote servers. +* Fix vcpus configuration for GNS3 VM on VMware. Ref #2738. +* Fix issue when images are not uploaded from appliance wizard. Ref https://github.com/GNS3/gns3-gui/issues/2738 +* Save the GNS3 VM settings even if the GNS3 VM cannot be stopped. +* Fix exception when emitting event from controller. Ref https://github.com/GNS3/gns3-gui/issues/2737 + +## 2.1.15 21/03/2019 + +* Fix IOU symlink issue on remote servers. +* Fix vcpus configuration for GNS3 VM on VMware. Ref #2738. + +## 2.2.0a2 14/03/2019 + +* Web-UI v2019.1.0-alpha.1 +* Update docs for update-bundled-web-ui.sh +* Fix issue when loading and quickly closing a project and opening it again. Fixes #1501. +* Disable unreliable nested virtualization check. +* Fix issue not checking build number on Windows. +* Change Hyper-V requirement checks. +* Early support for symbol themes. +* Re-order handlers in order to prevent CORS +* Download custom appliance symbols from GitHub Fix symbol cache issue. Ref https://github.com/GNS3/gns3-gui/issues/2671 Fix temporary directory for symbols was not deleted Fix temporary appliance file was not deleted +* Option to export snapshots. +* Support tags versioned WebUI when bundling +* Support selecting a compression type when exporting a project. +* Change how VPCS executable is searched. +* Use aiofiles where relevant. +* Update paths for binaries moved to the MacOS directory in GNS3.app +* Locked state should not be used when duplicating a node. +* Handle locking/unlocking items independently from the layer position. +* Use aiozipstream for snapshots. Fix tests. +* Project duplication support. + +## 2.2.0a1 29/01/2019 + +* Restore reload support for nodes. +* Tune how to get the size of SVG images. Ref https://github.com/GNS3/gns3-gui/issues/2674. * Default for missing height/width is "100%" as defined in the SVG specification * Better error message, if viewBox attribute is missing * Removal of "%" in percent more fault tolerant by using rstrip("%") +* Fix DeprecationWarning: invalid escape sequence. Fixes https://github.com/GNS3/gns3-gui/issues/2670 +* Fix issue with coroutine not awaited. Fixes #1499 +* Remove "deprecated" node for VirtualBox based GNS3 VM support. Ref #1377 +* Fix wrong controller method call. +* Move appliance and template management code in their own classes. +* Try to delete saved VM state only if a snapshot has been saved. +* Set socket options SO_KEEPALIVE and TCP_NODELAY for embedded Telnet server. Ref #1335 +* Fix issue with notification queue that prevented to properly close projects. Fix #1493 +* Fix issue with "usage" variable for Dynamips VMs. Fixes #1495 +* New node information dialog to display general, usage and command line information. Ref https://github.com/GNS3/gns3-gui/issues/2662 https://github.com/GNS3/gns3-gui/issues/2656 +* Support "usage" field for Dynamips, IOU, VirtualBox and VMware. Fixes https://github.com/GNS3/gns3-gui/issues/2657 +* Automatically create a symbolic link to the IOU image in the IOU working directory. Fixes #1484 +* Merge remote-tracking branch 'origin/2.1' into 2.1 +* Fix link pause/filters only work for the first interface of Docker containers. Fixes #1482 +* Fix ConnectionResetError issues and switch to aiohttp version 3.4.4. Fixes #1474. +* Fix server authentication. +* Fix issue when there is no gns3_controller.conf. Fixes https://github.com/GNS3/gns3-gui/issues/2644 +* Fix non responsive console for Docker VMs. Fixes https://github.com/GNS3/gns3-gui/issues/2645 +* Back to classic symbol theme. Ref https://github.com/GNS3/gns3-gui/issues/2644 +* docker_vm: fix x11vnc not starting +* Use "template" to name what we use to create new nodes. +* Use project instead of topology where appropriate. +* Make sure nothing is named "compute server". +* Allow usage property in Docker appliance. +* Use "node" instead of "appliance" for grid support. +* Telnet console resize support for Docker VM. +* Allow appliances to be loaded from file without the appliance id. +* Update schema to allow for drawing grid size to be part of project. +* Avoid _fix_permissions() to be called twice when stopping Docker VM. Ref #1428 +* Fix _fix_permissions() garbles permissions in Docker VM. Ref #1428 +* Fix "None is not of type 'integer'" when opening project containing a Qemu VM. Fixes #2610. +* Remove useless warning. +* Normalize symbol ID on Windows. +* Use POSIX path for symbol ID. +* Early support for symbol themes. +* Fix broken examples in API documentation. +* Add more information about appliances to the API documentation. +* Use Python3.6 to build the API documentation. +* Add missing files for API documentation. +* Restore previously removed test. +* Update API documentation for appliance endpoints. Ref https://github.com/GNS3/gns3-gui/issues/2630 +* Require privileged access for uBridge when using VMware VMs and Docker containers. Fixes #1461. +* Only require privileged access for uBridge when connecting a cloud to an Ethernet/TAP interface. Fixes #1461. +* Allow virtual machines to use files in project directory as disk images. +* Support to duplicate an appliance. +* Fix mac address schema validation for Qemu VM appliance. Fixes https://github.com/GNS3/gns3-gui/issues/2629 +* Support "L1 keepalives" in IOU appliance schema. +* Remove problematic test when run on Travis. +* Change test that randomly fails on Travis. +* Fix small bugs when using the new appliance management API. +* Fix bug with custom adapters and categories for Docker VM. Fixes https://github.com/GNS3/gns3-gui/issues/2613 +* Handle custom adapters in schemas. +* Reorganize how appliance creation is validated against JSON schemas. This allows for clearer error messages when validation fails. +* Use schema to set appliance default values and better schema validation error messages. +* Schema validation for appliance API. Ref #1427. +* Remove generic controller settings API endpoint. +* Working dedicated appliance management API. Ref https://github.com/GNS3/gns3-server/issues/1427 +* Support Xtigervnc restart. +* Only require Xtigervnc or Xvfb+x11vnc for Docker with vnc console. Ref #1438 +* Support tigervnc in Docker VM. Ref #1438 +* Base for dedicated appliance management API. Ref https://github.com/GNS3/gns3-server/issues/1427 +* Reorder routes in order to get working CORS +* Fix CORS response on node deletion, Fixes: #1446 +* Disable CORS cache, Fixes: #1445 +* Refactor how clients access PCAP capture files. Fixes https://github.com/GNS3/gns3-gui/issues/2438. +* Remove static dir configuration +* FIX PUT CORS for nodes, Fixes: #1434 +* Fix installation with Python 3.7. Fixes #1414. Fix deprecated use of aiohttp.Timeout. Fixes #1296. Use "async with" with aiohttp.ClientSession(). Make sure websocket connections are properly closed, see https://docs.aiohttp.org/en/stable/web_advanced.html#graceful-shutdown Finish to drop Python 3.4. +* Drop Python 3.4 and switch to async / await syntax for asyncio. Fixes #1425 +* Added "/sbin" to init script PATH variable so that its possible to use more sophosticated dhcp clients (compared to the udhcpc that is provided by busybox) by installing them into the docker image in the normal way. +* Notify users if x11vnc process has crashed. Fix #1401. +* Return compute port information via API. Ref #1420. +* Fix platform.linux_distribution() is deprecated. Fixes https://github.com/GNS3/gns3-gui/issues/2578 +* Update minimum VIX version requirements for VMware. Ref #1415. +* Disable static directory. Ref https://github.com/GNS3/gns3-gui/issues/2558. +* Include HTTP error code when reporting an error while download appliance templates from GitHub repository. +* Optimize appliance templates update from GitHub repository by only downloading when the repository has been updated. Ref https://github.com/GNS3/gns3-gui/issues/2490 +* Fix appliance template tests. +* Update appliance templates from online registry. Ref #2490. +* Add missing doc pages. +* Update docs for controller_notifications and project_notifications. +* The server has now 2 notification streams * A new one for controller related events (compute, appliance templates etc.) * The existing one for project related events (links, nodes etc.) +* Allow custom symbols to be sub-directories. +* Add affinity symbols. Ref https://github.com/GNS3/gns3-gui/issues/2488 +* ACPI shutdown for GNS3 VM running on Hyper-V. Ref https://github.com/GNS3/gns3-gui/issues/763 +* Hyper-V support for GNS3 VM. Fixes https://github.com/GNS3/gns3-gui/issues/763 +* Get IP address from guest Hyper-V VM. Ref https://github.com/GNS3/gns3-gui/issues/763 +* Early Hyper-V support to run the GNS3 VM. Ref https://github.com/GNS3/gns3-gui/issues/763. +* Add appliance UUID added to the node data. Fixes #1334. +* Clean GNS3 close if one remote server is down. Fixes #1357. +* Mark VirtualBox support for running the GNS3 VM as deprecated. Ref #1377. +* Change default z value for nodes to 1 +* Re-enable static directory +* Disable static/ dir, Ref: #2532 +* Fix tests on Windows +* Use mocked dir for web-ui redirection test +* Use mocked dir of web-ui for tests +* Gitkeep for web-ui directory +* Serve WebUI handlers and update-bundled-web-ui script, Ref: #1362 +* Support /static/ files serving, Ref: #1362 +* Console support for clouds (to connect to external devices or services). +* Fix switching console type from telnet to VNC throws error. Fixes #2489. +* Fix saved VM state was not deleted correctly. +* Fix problem with VM saved stated. +* Returns the ports' adapter types and mac addresses when available. +* Support for console auto start. +* Possibility to customize port names and adapter types for Qemu, VirtualBox, VMware and Docker. Fixes #2361. MAC addresses can customized for Qemu as well. +* Allow to have projects with the same name in different locations. +* Save state feature for VirtualBox and VMware. New "On close" setting to select the action to execute when closing/stopping a Qemu/VirtualBox/VMware VM. +* Support for suspend to disk / resume (Qemu). +* Fix bug with 'none' console type for Ethernet switch. Fix some tests related to traceng. +* Allow to resize a Qemu VM disk (extend only). +* Allow to select the default NAT interface in preferences for local server. +* Spice with agent support for Qemu VMs. +* Check if the HAXM service is running when starting a Qemu VM with hardware acceleration. Ref #1242. +* Support for console type "none". +* Support for none console type (Qemu & Docker only) +* Fix bug and add optimizations when connecting and sending commands to QEMU monitor after starting a VM. Fixes #2336. +* Check if HAXM support is installed on macOS. Ref #1242. +* Fix some issues with hardware acceleration support for Qemu. +* Support Qemu with HAXM acceleration. Ref #1242. +* Fix packet filters for Dynamips. +* Fix link filters/suspend tests. +* Improve suspend a link for Qemu and VirtualBox VMs. A suspended link will be unplugged allowing the VMs to be notified of the change. +* Qemu VM support to detect when a link is plugged/unplugged. +* Allow to configure the interface to be used by the NAT node. Fixes #1175. +* Restrict the list of available Ethernet/TAP adapters. Fixes #352. +* Basic project stats. +* Filter snapshots directory during the snapshot, Fixes: #1297 +* Calculate MD5 on thread and before json response, Ref. gui#2239 +* Cancellable md5sum calculation on thread, Ref. gui#2239 +* Compute md5sum on thread and don't block main server, Ref. gui#2239 +* Replace asyncio.async with ensure_future because of deprecation, Fixes: #1269 +* Implement #1153 into 2.2 branch. +* Pin prompt-toolkit to latest version 1.0.15 + +## 2.1.14 27/02/2019 + +* Fix issue when setting cpuid.corespersocket for the GNS3 VM. Fixes https://github.com/GNS3/gns3-gui/issues/2723 +* Bump ACPI Shutdown Timeout to 120 seconds. Ref #1536 + +## 2.1.13 26/02/2019 + +* Force jsonschema dependency to 2.6.0 +* Less aggressive connections to uBridge. Ref #1289 +* Fix topology images (Pictures) disappearing from projects. Fixes #1514. +* Reset MAC addresses when duplicating a project. Fixes #1522 +* Fix API call to create a node from an appliance doesn't return the new node data. Fixes #1527 +* Detect invalid environment variable and send a warning when creating a Docker node. Ref #2683 +* Do not export/import symlinks for projects. Fixes #2699 +* Fix symlink not being created for duplicated IOU devices. Fixes https://github.com/GNS3/gns3-gui/issues/2699 +* Configure coresPerSocket value in VMX file for the GNS3 VM. Fixes https://github.com/GNS3/gns3-gui/issues/2688 +* Count logical CPUs to detect if the number of vCPUs is too high when configuring the GNS3 VM. Fixes #2688. +* Add explicit error when trying to pull a Docker image from Docker Hub without Internet access. Fixes #1506. +* Fixes double display output in GRUB in QEMU v3.1. Fixes #1516. + +## 2.1.12 23/01/2019 + +* Tune how to get the size of SVG images. Ref https://github.com/GNS3/gns3-gui/issues/2674. +* Automatically create a symbolic link to the IOU image in the IOU working directory. Fixes #1484 +* Fix link pause/filters only work for the first interface of Docker containers. Fixes #1482 +* Telnet console resize support for Docker VM. +* Fix _fix_permissions() garbles permissions in Docker VM. Ref #1428 +* Fix "None is not of type 'integer'" when opening project containing a Qemu VM. Fixes #2610. +* Only require Xtigervnc or Xvfb+x11vnc for Docker with vnc console. Ref #1438 +* Support tigervnc in Docker VM. Ref #1438 +* Update minimum VIX version requirements for VMware. Ref #1415. + +## 2.1.11 28/09/2018 + +* Catch some exceptions. + +## 2.1.10 15/09/2018 + +* Include locale information and GNS3 VM version in crash reports. +* Fix small errors like unhandled exceptions etc. +* Import encodings.idna to avoid LookupError when standard library is in a zip file. +* Catch exceptions in various locations to fix small issues reported by Sentry. +* Check if serial pipe can be opened for VMware and VirtualBox VMs. +* Improve the invalid port format detection. Fixes https://github.com/GNS3/gns3-gui/issues/2580 +* Update aiohttp verion requirement in order to support Python 3.7. Fixes https://github.com/GNS3/gns3-gui/issues/2566 +* Update setup.py and fix minor issues. +* Catch asyncio.CancelledError when shutting down the server. +* Report GNS3 VM errors to the GUI server summary. Ref #1359. +* Replace vboxnet0 (if it does not exist) by the first available vboxnet interface on Windows. Fixes https://github.com/GNS3/gns3-vm/issues/102 +* Check if the VirtualBox host-only network exists when starting a GNS3 VM running on VirtualBox. Ref https://github.com/GNS3/gns3-vm/issues/102 +* Change file timestamps if necessary because ZIP does not support timestamps before 1980. Fixes #1360. +* Add missing coroutine decorator Ref https://github.com/GNS3/gns3-gui/issues/2566 +* Refactor asyncio locking system for Python 3.7 support. Ref https://github.com/GNS3/gns3-gui/issues/2566 Ref https://github.com/GNS3/gns3-gui/issues/2568 +* Use asyncio.ensure_future() instead of asyncio.async() with conservative approach to support Python < 3.4.4. Fixes https://github.com/GNS3/gns3-gui/issues/2566 +* Forbid controller and computes to be different versions. Report last compute error to clients and display in the server summary. +* Fix exception with short names for Dynamips interfaces. Fixes #1386. +* Add missing Qemu boot priority values. Fixes https://github.com/GNS3/gns3-server/issues/1385 + +## 2.1.9 13/08/2018 + +* Fix some more problems with interface short names. Fixes https://github.com/GNS3/gns3-gui/issues/2562 +* Fix incorrect short port names in topology summary. Fixes https://github.com/GNS3/gns3-gui/issues/2562 +* Set lower process priority when computing idle-pc value on Windows. Ref #2522. +* Catch exception: ZIP does not support timestamps before 1980. Ref #1360. +* Sync appliances + +## 2.1.8 14/06/2018 + +* 'caplog.text()' syntax is deprecated, use 'caplog.text' property instead. +* Remove problematic pytest-capturelog dev dependency. +* Fix API status code for start/stop/suspend/reload a node. Fixes #1353. Fix issues with test. Update documentation. +* Don't send variables to computes where are empty, Ref: #1340 + +## 2.1.7 12/06/2018 + +* Don't release NIO UDP ports when updating docker container. +* Timeout for stream file. +* Fix switching console type from telnet to VNC throws error. +* Fix timeout error with "save as" for large projects. +* Update API documentation +* Add API endpoint to return all links attached to a node. +* Fix issue with some SVG symbols that could not be used in GNS3. This was due to the height and width values being percentages. +* Show correct free disk space value. +* Force prompt-toolkit to version 1.0.15 +* Remove unwanted trailing characters and other white spaces when reading .md5sum files. +* Change order to find vnetlib on Windows (PATH -> Registry -> Default directories). + +## 2.1.6 22/05/2018 + +* Locks down async-timeout<3.0.0 for P3.4 support; Fixes: #1331 +* Create/update project on compute when variables changes +* Support for nested global variables +* Don't clean logo images when applied to the project +* Support of supplier and variables in topology +* Project global variables +* Add command information when uBridge has an error. Ref #1289 +* Handle asyncio timeouts. Ref #1307. +* Fix bug with export project. Ref #1187 #1307. +* Offload slow file operations to threads for snapshots and project "save as". Ref #1187 #1307. +* support based on init.sh, Ref: #2482 +* Fix exception from send_signal() on Windows. +* Add support of ExtraHosts for Docker, Ref. gns3-gui#2482 + +## 2.1.5 18/04/2018 + +* Set the first byte to 0C when generating a random MAC address for a Qemu VM. Ref #1267. +* Update appliance files. +* Do not use VMnet0 when allocating VMnet adapters. +* Use SO_REUSEADDR before calling bind() where missing. Fixes #1289. +* Do not fail a Dynamips project conversion if a file being used. +* Catch exceptions when using AsyncioTelnetServer. Fixes #1321. +* Grid size support for projects. +* Remove 'include INSTALL' from MANIFEST. +* Fix issue with start all. +* Check for valid IP address and prevent to run on non-Windows platforms. +* Enable UDP tunnel option and use ICMP probing by default. +* Use the configured IP address to trace. +* Have TraceNG start without needing cmd.exe + ## 2.1.4 12/03/2018 * Add Juniper JunOS space appliance. @@ -466,7 +810,7 @@ * Trust user for host binding of link adress * Code cleanup for docker interface creation * Fix a rare crash when writing a file on a remote server -* Fix delete project on remote compute server +* Fix delete project on remote compute * Fix trouble with builtin devices when we free ports * When a dynamips command failed display the full command to the user * Raise error when we can't found VboxManage at GNS3 VM startup @@ -594,7 +938,7 @@ * Fix naming of IOU serial interfaces * Improve timeout management * When exporting debug information export GNS3 VM vmx content -* /debug for exporting debug informations +* /debug for exporting debug information * Raise error if using a non linked clone VM twice * Fix a possible deadlock at exit * Fix import of some old dynamips topologies diff --git a/Dockerfile b/Dockerfile index 96f84c4b..4b176018 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # Dockerfile for GNS3 server development -FROM ubuntu:16.04 +FROM ubuntu:18.04 ENV DEBIAN_FRONTEND noninteractive diff --git a/MANIFEST.in b/MANIFEST.in index 61bdd940..38cadc48 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,5 @@ include README.rst include AUTHORS -include INSTALL include LICENSE include MANIFEST.in include tox.ini diff --git a/README.rst b/README.rst index 4e29ee32..1aba56f7 100644 --- a/README.rst +++ b/README.rst @@ -23,7 +23,7 @@ master is the next stable release, you can test it in your day to day activities Bug fixes or small improvements pull requests go here. 2.x (2.1 for example) -******** +********************* Next major release *Never* use this branch for production. Pull requests for major new features go here. @@ -100,7 +100,7 @@ All init scripts require the creation of a GNS3 user. You can change it to anoth sudo adduser gns3 upstart -~~~~~~~ +------- For ubuntu < 15.04 @@ -113,7 +113,8 @@ You need to copy init/gns3.conf.upstart to /etc/init/gns3.conf systemd -~~~~~~~~ +------- + You need to copy init/gns3.service.systemd to /lib/systemd/system/gns3.service .. code:: bash @@ -163,14 +164,14 @@ Mac OS X Please use our DMG package for a simple installation. -If you want to test the current git version or contribute to the project, +If you want to test the current git version or contribute to the project, you can follow these instructions with virtualenwrapper: http://virtualenvwrapper.readthedocs.org/ and homebrew: http://brew.sh/. .. code:: bash brew install python3 - mkvirtualenv gns3-server --python=/usr/local/bin/python3.4 + mkvirtualenv gns3-server --python=/usr/local/bin/python3.5 python3 setup.py install gns3server @@ -218,5 +219,5 @@ If you want test coverage: Security issues ---------------- -Please contact us using contact information available here: +Please contact us using contact form available here: http://docs.gns3.com/1ON9JBXSeR7Nt2-Qum2o3ZX0GU86BZwlmNSUgvmqNWGY/index.html diff --git a/conf/gns3_server.conf b/conf/gns3_server.conf index e8e98431..ffab4ec8 100644 --- a/conf/gns3_server.conf +++ b/conf/gns3_server.conf @@ -39,6 +39,14 @@ user = gns3 ; Password for HTTP authentication. password = gns3 +; Only allow these interfaces to be used by GNS3, for the Cloud node for example (Linux/OSX only) +; Do not forget to allow virbr0 in order for the NAT node to work +allowed_interfaces = eth0,eth1,virbr0 + +; Specify the NAT interface to be used by the NAT node +; Default is virbr0 on Linux (requires libvirt) and vmnet8 for other platforms (requires VMware) +default_nat_interface = vmnet10 + [VPCS] ; VPCS executable location, default: search in PATH ;vpcs_path = vpcs @@ -53,15 +61,17 @@ sparse_memory_support = True ghost_ios_support = True [IOU] -; iouyap executable path, default: search in PATH -;iouyap_path = iouyap ; Path of your .iourc file. If not provided, the file is searched in $HOME/.iourc iourc_path = /home/gns3/.iourc ; Validate if the iourc license file is correct. If you turn this off and your licence is invalid IOU will not start and no errors will be shown. license_check = True [Qemu] -; !! Remember to add the gns3 user to the KVM group, otherwise you will not have read / write permssions to /dev/kvm !! +; !! Remember to add the gns3 user to the KVM group, otherwise you will not have read / write permissions to /dev/kvm !! (Linux only, has priority over enable_hardware_acceleration) enable_kvm = True -; Require KVM to be installed in order to start VMs -require_kvm = True \ No newline at end of file +; Require KVM to be installed in order to start VMs (Linux only, has priority over require_hardware_acceleration) +require_kvm = True +; Enable hardware acceleration (all platforms) +enable_hardware_acceleration = True +; Require hardware acceleration in order to start VMs (all platforms) +require_hardware_acceleration = True diff --git a/dev-requirements.txt b/dev-requirements.txt index 51e2d6b5..ced89dbc 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,7 +1,6 @@ -rrequirements.txt -sphinx==1.6.2 -pytest==3.1.1 -pep8==1.7.0 -pytest-catchlog==1.2.2 -pytest-timeout==1.2.0 +sphinx==1.8.3 +pytest==4.4.1 +pep8==1.7.1 +pytest-timeout==1.3.3 diff --git a/docs/api/examples/compute_delete_projectsprojectid.txt b/docs/api/examples/compute_delete_projectsprojectid.txt index dc50a67c..c65723c6 100644 --- a/docs/api/examples/compute_delete_projectsprojectid.txt +++ b/docs/api/examples/compute_delete_projectsprojectid.txt @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:55 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:58 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id} diff --git a/docs/api/examples/compute_delete_projectsprojectidcloudnodesnodeid.txt b/docs/api/examples/compute_delete_projectsprojectidcloudnodesnodeid.txt index 5d5f84c4..4fedf755 100644 --- a/docs/api/examples/compute_delete_projectsprojectidcloudnodesnodeid.txt +++ b/docs/api/examples/compute_delete_projectsprojectidcloudnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/b5a23628-0043-4eeb-86b7-d55b6909b9b7' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/8e21e0ec-028e-4aaf-a6dc-d4cf5e449c0c' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/b5a23628-0043-4eeb-86b7-d55b6909b9b7 HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/8e21e0ec-028e-4aaf-a6dc-d4cf5e449c0c HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:44 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:38 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/cloud/nodes/{node_id} diff --git a/docs/api/examples/compute_delete_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_delete_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index db010a2d..2754c967 100644 --- a/docs/api/examples/compute_delete_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_delete_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/a979dd8e-8c34-4a5a-98de-f50cf4fcce8c/adapters/0/ports/0/nio' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/d0b540bc-1fcf-4e5f-9a9c-d04a2b1001c1/adapters/0/ports/0/nio' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/a979dd8e-8c34-4a5a-98de-f50cf4fcce8c/adapters/0/ports/0/nio HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/d0b540bc-1fcf-4e5f-9a9c-d04a2b1001c1/adapters/0/ports/0/nio HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:43 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:36 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio diff --git a/docs/api/examples/compute_delete_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_delete_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 5c69c596..c4afa97d 100644 --- a/docs/api/examples/compute_delete_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_delete_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/8c0aeb7d-1f06-425c-9e03-f16182fae5b8/adapters/0/ports/0/nio' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/8dc16f7a-d0a1-443a-888f-e7a105315f25/adapters/0/ports/0/nio' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/8c0aeb7d-1f06-425c-9e03-f16182fae5b8/adapters/0/ports/0/nio HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/8dc16f7a-d0a1-443a-888f-e7a105315f25/adapters/0/ports/0/nio HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:46 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:39 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio diff --git a/docs/api/examples/compute_delete_projectsprojectidiounodesnodeid.txt b/docs/api/examples/compute_delete_projectsprojectidiounodesnodeid.txt index f7b9ec41..7f6be093 100644 --- a/docs/api/examples/compute_delete_projectsprojectidiounodesnodeid.txt +++ b/docs/api/examples/compute_delete_projectsprojectidiounodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/33edb045-964b-4089-857b-cfc31fff99b7' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/cfab21a8-053e-41a9-b1e6-4fa7d7d03ec7' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/33edb045-964b-4089-857b-cfc31fff99b7 HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/cfab21a8-053e-41a9-b1e6-4fa7d7d03ec7 HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:48 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id} diff --git a/docs/api/examples/compute_delete_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_delete_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt index c789627f..9c4288bb 100644 --- a/docs/api/examples/compute_delete_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_delete_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/642df0c1-b531-4c9b-8643-25282fcdbda6/adapters/1/ports/0/nio' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/5ea1f88b-fed0-4366-958e-bdce27a00aca/adapters/1/ports/0/nio' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/642df0c1-b531-4c9b-8643-25282fcdbda6/adapters/1/ports/0/nio HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/5ea1f88b-fed0-4366-958e-bdce27a00aca/adapters/1/ports/0/nio HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:48 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:54 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio diff --git a/docs/api/examples/compute_delete_projectsprojectidnatnodesnodeid.txt b/docs/api/examples/compute_delete_projectsprojectidnatnodesnodeid.txt index 4a4eedcd..55cd9c9e 100644 --- a/docs/api/examples/compute_delete_projectsprojectidnatnodesnodeid.txt +++ b/docs/api/examples/compute_delete_projectsprojectidnatnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/924bd83c-8b35-4e7d-b3fd-8903deaf3eec' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/6fd4180e-4c48-4faa-8b92-2f61b38e456f' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/924bd83c-8b35-4e7d-b3fd-8903deaf3eec HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/6fd4180e-4c48-4faa-8b92-2f61b38e456f HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:52 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:57 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/nat/nodes/{node_id} diff --git a/docs/api/examples/compute_delete_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_delete_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 5d532ad0..164fce43 100644 --- a/docs/api/examples/compute_delete_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_delete_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/8cbe8570-b6f2-489a-b7fc-69aafaf24bf0/adapters/0/ports/0/nio' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/ff81b716-de5b-4700-81a9-19b85ed2484c/adapters/0/ports/0/nio' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/8cbe8570-b6f2-489a-b7fc-69aafaf24bf0/adapters/0/ports/0/nio HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/ff81b716-de5b-4700-81a9-19b85ed2484c/adapters/0/ports/0/nio HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:49 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:57 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio diff --git a/docs/api/examples/compute_delete_projectsprojectidqemunodesnodeid.txt b/docs/api/examples/compute_delete_projectsprojectidqemunodesnodeid.txt index 1708461a..3546f1cd 100644 --- a/docs/api/examples/compute_delete_projectsprojectidqemunodesnodeid.txt +++ b/docs/api/examples/compute_delete_projectsprojectidqemunodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/153aafd0-e32b-456a-8502-cd07b2ecc94b' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/e4c7296b-444a-4851-9169-b7286d19f32f' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/153aafd0-e32b-456a-8502-cd07b2ecc94b HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/e4c7296b-444a-4851-9169-b7286d19f32f HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:36 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id} diff --git a/docs/api/examples/compute_delete_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_delete_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt index b1a1ab26..bc57a079 100644 --- a/docs/api/examples/compute_delete_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_delete_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/7d6b86b2-510e-4f1c-99ae-dd945b3479d1/adapters/1/ports/0/nio' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/0e323568-5bfe-43e1-a6c1-88c42dc6e27e/adapters/1/ports/0/nio' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/7d6b86b2-510e-4f1c-99ae-dd945b3479d1/adapters/1/ports/0/nio HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/0e323568-5bfe-43e1-a6c1-88c42dc6e27e/adapters/1/ports/0/nio HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:41 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio diff --git a/docs/api/examples/compute_delete_projectsprojectidtracengnodesnodeid.txt b/docs/api/examples/compute_delete_projectsprojectidtracengnodesnodeid.txt new file mode 100644 index 00000000..ffd6cc7d --- /dev/null +++ b/docs/api/examples/compute_delete_projectsprojectidtracengnodesnodeid.txt @@ -0,0 +1,14 @@ +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/4fae9b05-92d7-4926-b025-e2fa82d36104' + +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/4fae9b05-92d7-4926-b025-e2fa82d36104 HTTP/1.1 + + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:48:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id} + diff --git a/docs/api/examples/compute_delete_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_delete_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt new file mode 100644 index 00000000..4df89d98 --- /dev/null +++ b/docs/api/examples/compute_delete_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -0,0 +1,14 @@ +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/1d7faff2-881a-4db7-95ab-1eb0fb43b1f0/adapters/0/ports/0/nio' + +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/1d7faff2-881a-4db7-95ab-1eb0fb43b1f0/adapters/0/ports/0/nio HTTP/1.1 + + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:48:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio + diff --git a/docs/api/examples/compute_delete_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_delete_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 81893234..22e6c384 100644 --- a/docs/api/examples/compute_delete_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_delete_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/88bb1118-bdf4-43af-aa30-8883e0ab6a4b/adapters/0/ports/0/nio' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/4e22a267-67ab-4cc9-aac7-b5d155caa7f2/adapters/0/ports/0/nio' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/88bb1118-bdf4-43af-aa30-8883e0ab6a4b/adapters/0/ports/0/nio HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/4e22a267-67ab-4cc9-aac7-b5d155caa7f2/adapters/0/ports/0/nio HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:58 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio diff --git a/docs/api/examples/compute_delete_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_delete_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 7f652342..d7a03a34 100644 --- a/docs/api/examples/compute_delete_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_delete_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/18cb778e-37a5-485d-8ee5-42e42d78ed3e/adapters/0/ports/0/nio' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/08e3c716-8162-413f-adf0-af630d05a9f5/adapters/0/ports/0/nio' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/18cb778e-37a5-485d-8ee5-42e42d78ed3e/adapters/0/ports/0/nio HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/08e3c716-8162-413f-adf0-af630d05a9f5/adapters/0/ports/0/nio HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:08 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:05 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio diff --git a/docs/api/examples/compute_delete_projectsprojectidvpcsnodesnodeid.txt b/docs/api/examples/compute_delete_projectsprojectidvpcsnodesnodeid.txt index fecbd515..4adea335 100644 --- a/docs/api/examples/compute_delete_projectsprojectidvpcsnodesnodeid.txt +++ b/docs/api/examples/compute_delete_projectsprojectidvpcsnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/8b556295-efa1-46ae-ad46-8f9e38ed879e' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/98e08164-d04b-4785-9805-70862e92d0b6' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/8b556295-efa1-46ae-ad46-8f9e38ed879e HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/98e08164-d04b-4785-9805-70862e92d0b6 HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:44 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id} diff --git a/docs/api/examples/compute_delete_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_delete_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index b052edd5..57ce6f92 100644 --- a/docs/api/examples/compute_delete_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_delete_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/881b9fcf-316f-4a25-9807-a23363c0ed63/adapters/0/ports/0/nio' +curl -i -X DELETE 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/21890613-9dc9-4990-bec5-8fd968e3a6e7/adapters/0/ports/0/nio' -DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/881b9fcf-316f-4a25-9807-a23363c0ed63/adapters/0/ports/0/nio HTTP/1.1 +DELETE /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/21890613-9dc9-4990-bec5-8fd968e3a6e7/adapters/0/ports/0/nio HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:44 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio diff --git a/docs/api/examples/compute_get_capabilities.txt b/docs/api/examples/compute_get_capabilities.txt index 73c85e35..574972db 100644 --- a/docs/api/examples/compute_get_capabilities.txt +++ b/docs/api/examples/compute_get_capabilities.txt @@ -6,10 +6,10 @@ GET /v2/compute/capabilities HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 347 +Content-Length: 366 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:42 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:36 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/capabilities { @@ -25,9 +25,10 @@ X-Route: /v2/compute/capabilities "atm_switch", "qemu", "vmware", + "traceng", "docker", "iou" ], "platform": "linuxdebian", - "version": "2.1.2dev1" + "version": "2.2.0dev8" } diff --git a/docs/api/examples/compute_get_iouimages.txt b/docs/api/examples/compute_get_iouimages.txt index b0fb48f6..fbb771f4 100644 --- a/docs/api/examples/compute_get_iouimages.txt +++ b/docs/api/examples/compute_get_iouimages.txt @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 149 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:48 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:55 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/iou/images [ diff --git a/docs/api/examples/compute_get_networkinterfaces.txt b/docs/api/examples/compute_get_networkinterfaces.txt index 36098af1..33f0a206 100644 --- a/docs/api/examples/compute_get_networkinterfaces.txt +++ b/docs/api/examples/compute_get_networkinterfaces.txt @@ -6,74 +6,128 @@ GET /v2/compute/network/interfaces HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 1461 +Content-Length: 2933 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:54 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:58 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/network/interfaces [ { - "id": "bridge0", - "ip_address": "", - "mac_address": "ca:2a:14:12:34:00", - "name": "bridge0", - "netmask": "", + "id": "docker0", + "ip_address": "172.17.0.1", + "mac_address": "02:42:c5:7b:84:0b", + "name": "docker0", + "netmask": "255.255.0.0", "special": true, "type": "ethernet" }, { - "id": "en0", - "ip_address": "", - "mac_address": "c8:2a:14:21:cf:c8", - "name": "en0", - "netmask": "", - "special": false, - "type": "ethernet" - }, - { - "id": "en1", - "ip_address": "192.168.1.10", - "mac_address": "10:9a:dd:a4:f1:6a", - "name": "en1", - "netmask": "255.255.255.0", - "special": false, - "type": "ethernet" - }, - { - "id": "en2", - "ip_address": "", - "mac_address": "d2:00:18:cc:6a:60", - "name": "en2", - "netmask": "", - "special": false, - "type": "ethernet" - }, - { - "id": "fw0", - "ip_address": "", - "mac_address": "c8:2a:14:ff:fe:8c:c6:a6", - "name": "fw0", - "netmask": "", - "special": true, - "type": "ethernet" - }, - { - "id": "lo0", + "id": "lo", "ip_address": "127.0.0.1", - "mac_address": "", - "name": "lo0", + "mac_address": "00:00:00:00:00:00", + "name": "lo", "netmask": "255.0.0.0", "special": true, "type": "ethernet" }, { - "id": "p2p0", + "id": "vboxnet0", "ip_address": "", - "mac_address": "02:9a:dd:a4:f1:6a", - "name": "p2p0", + "mac_address": "0a:00:27:00:00:00", + "name": "vboxnet0", "netmask": "", "special": true, "type": "ethernet" + }, + { + "id": "vboxnet1", + "ip_address": "", + "mac_address": "0a:00:27:00:00:01", + "name": "vboxnet1", + "netmask": "", + "special": true, + "type": "ethernet" + }, + { + "id": "vboxnet2", + "ip_address": "", + "mac_address": "0a:00:27:00:00:02", + "name": "vboxnet2", + "netmask": "", + "special": true, + "type": "ethernet" + }, + { + "id": "virbr0", + "ip_address": "192.168.122.1", + "mac_address": "00:00:00:00:00:00", + "name": "virbr0", + "netmask": "255.255.255.0", + "special": true, + "type": "ethernet" + }, + { + "id": "virbr0-nic", + "ip_address": "", + "mac_address": "52:54:00:cb:6a:77", + "name": "virbr0-nic", + "netmask": "", + "special": true, + "type": "ethernet" + }, + { + "id": "vmnet1", + "ip_address": "172.16.1.1", + "mac_address": "00:50:56:c0:00:01", + "name": "vmnet1", + "netmask": "255.255.255.0", + "special": true, + "type": "ethernet" + }, + { + "id": "vmnet2", + "ip_address": "172.16.2.1", + "mac_address": "00:50:56:c0:00:02", + "name": "vmnet2", + "netmask": "255.255.255.0", + "special": true, + "type": "ethernet" + }, + { + "id": "vmnet3", + "ip_address": "172.16.3.1", + "mac_address": "00:50:56:c0:00:03", + "name": "vmnet3", + "netmask": "255.255.255.0", + "special": true, + "type": "ethernet" + }, + { + "id": "vmnet4", + "ip_address": "172.16.10.1", + "mac_address": "00:50:56:c0:00:04", + "name": "vmnet4", + "netmask": "255.255.255.0", + "special": true, + "type": "ethernet" + }, + { + "id": "vmnet8", + "ip_address": "192.168.195.1", + "mac_address": "00:50:56:c0:00:08", + "name": "vmnet8", + "netmask": "255.255.255.0", + "special": true, + "type": "ethernet" + }, + { + "id": "wlp58s0", + "ip_address": "192.168.1.149", + "mac_address": "9c:b6:d0:dc:20:29", + "name": "wlp58s0", + "netmask": "255.255.255.0", + "special": false, + "type": "ethernet" } ] diff --git a/docs/api/examples/compute_get_projects.txt b/docs/api/examples/compute_get_projects.txt index e851566e..10dc31c1 100644 --- a/docs/api/examples/compute_get_projects.txt +++ b/docs/api/examples/compute_get_projects.txt @@ -6,19 +6,21 @@ GET /v2/compute/projects HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 198 +Content-Length: 252 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:55 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:58 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects [ { "name": "test", - "project_id": "51010203-0405-0607-0809-0a0b0c0d0e0f" + "project_id": "51010203-0405-0607-0809-0a0b0c0d0e0f", + "variables": null }, { "name": "test", - "project_id": "52010203-0405-0607-0809-0a0b0c0d0e0b" + "project_id": "52010203-0405-0607-0809-0a0b0c0d0e0b", + "variables": null } ] diff --git a/docs/api/examples/compute_get_projectsprojectid.txt b/docs/api/examples/compute_get_projectsprojectid.txt index a1e8cf1b..5aa15c5a 100644 --- a/docs/api/examples/compute_get_projectsprojectid.txt +++ b/docs/api/examples/compute_get_projectsprojectid.txt @@ -6,13 +6,14 @@ GET /v2/compute/projects/40010203-0405-0607-0809-0a0b0c0d0e02 HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 80 +Content-Length: 103 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:55 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:58 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id} { "name": "test", - "project_id": "40010203-0405-0607-0809-0a0b0c0d0e02" + "project_id": "40010203-0405-0607-0809-0a0b0c0d0e02", + "variables": null } diff --git a/docs/api/examples/compute_get_projectsprojectidcloudnodesnodeid.txt b/docs/api/examples/compute_get_projectsprojectidcloudnodesnodeid.txt index 48e6b7e6..c4e12eff 100644 --- a/docs/api/examples/compute_get_projectsprojectidcloudnodesnodeid.txt +++ b/docs/api/examples/compute_get_projectsprojectidcloudnodesnodeid.txt @@ -1,78 +1,100 @@ -curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/870c464a-d236-4a5e-8a1d-87893c493f4c' +curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/62a9389c-9bfd-4fd7-986d-ba32879fbe91' -GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/870c464a-d236-4a5e-8a1d-87893c493f4c HTTP/1.1 +GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/62a9389c-9bfd-4fd7-986d-ba32879fbe91 HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 1584 +Content-Length: 2080 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:42 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:36 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/cloud/nodes/{node_id} { "interfaces": [ { - "name": "bridge0", + "name": "docker0", "special": true, "type": "ethernet" }, { - "name": "en0", + "name": "lo", + "special": true, + "type": "ethernet" + }, + { + "name": "vboxnet0", + "special": true, + "type": "ethernet" + }, + { + "name": "vboxnet1", + "special": true, + "type": "ethernet" + }, + { + "name": "vboxnet2", + "special": true, + "type": "ethernet" + }, + { + "name": "virbr0", + "special": true, + "type": "ethernet" + }, + { + "name": "virbr0-nic", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet1", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet2", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet3", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet4", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet8", + "special": true, + "type": "ethernet" + }, + { + "name": "wlp58s0", "special": false, "type": "ethernet" - }, - { - "name": "en1", - "special": false, - "type": "ethernet" - }, - { - "name": "en2", - "special": false, - "type": "ethernet" - }, - { - "name": "fw0", - "special": true, - "type": "ethernet" - }, - { - "name": "lo0", - "special": true, - "type": "ethernet" - }, - { - "name": "p2p0", - "special": true, - "type": "ethernet" } ], "name": "Cloud 1", - "node_directory": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/project-files/builtin/870c464a-d236-4a5e-8a1d-87893c493f4c", - "node_id": "870c464a-d236-4a5e-8a1d-87893c493f4c", + "node_directory": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/builtin/62a9389c-9bfd-4fd7-986d-ba32879fbe91", + "node_id": "62a9389c-9bfd-4fd7-986d-ba32879fbe91", "ports_mapping": [ { - "interface": "en0", - "name": "en0", + "interface": "wlp58s0", + "name": "wlp58s0", "port_number": 0, "type": "ethernet" - }, - { - "interface": "en1", - "name": "en1", - "port_number": 1, - "type": "ethernet" - }, - { - "interface": "en2", - "name": "en2", - "port_number": 2, - "type": "ethernet" } ], "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", + "remote_console_host": "", + "remote_console_http_path": "/", + "remote_console_port": 23, + "remote_console_type": "none", "status": "started" } diff --git a/docs/api/examples/compute_get_projectsprojectidiounodesnodeid.txt b/docs/api/examples/compute_get_projectsprojectidiounodesnodeid.txt index 6d6f3973..315ca484 100644 --- a/docs/api/examples/compute_get_projectsprojectidiounodesnodeid.txt +++ b/docs/api/examples/compute_get_projectsprojectidiounodesnodeid.txt @@ -1,15 +1,15 @@ -curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/f1e67396-246b-4edb-bfeb-cfd6bd028ae1' +curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/011a97fd-82ba-4a6f-8f96-684637afd015' -GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/f1e67396-246b-4edb-bfeb-cfd6bd028ae1 HTTP/1.1 +GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/011a97fd-82ba-4a6f-8f96-684637afd015 HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 665 +Content-Length: 630 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:47 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id} { @@ -21,13 +21,14 @@ X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id} "l1_keepalives": false, "md5sum": "e573e8f5c93c6c00783f20c7a170aa6c", "name": "PC TEST 1", - "node_directory": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/project-files/iou/f1e67396-246b-4edb-bfeb-cfd6bd028ae1", - "node_id": "f1e67396-246b-4edb-bfeb-cfd6bd028ae1", + "node_directory": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/iou/011a97fd-82ba-4a6f-8f96-684637afd015", + "node_id": "011a97fd-82ba-4a6f-8f96-684637afd015", "nvram": 128, "path": "iou.bin", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "ram": 256, "serial_adapters": 2, "status": "stopped", + "usage": "", "use_default_iou_values": true } diff --git a/docs/api/examples/compute_get_projectsprojectidnatnodesnodeid.txt b/docs/api/examples/compute_get_projectsprojectidnatnodesnodeid.txt index bc6e43cf..2d14985d 100644 --- a/docs/api/examples/compute_get_projectsprojectidnatnodesnodeid.txt +++ b/docs/api/examples/compute_get_projectsprojectidnatnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/2d520206-fba0-4b14-9fac-c065701eab55' +curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/620cae24-6a49-4608-8c21-8367f1e57cfc' -GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/2d520206-fba0-4b14-9fac-c065701eab55 HTTP/1.1 +GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/620cae24-6a49-4608-8c21-8367f1e57cfc HTTP/1.1 @@ -8,13 +8,13 @@ HTTP/1.1 200 Connection: close Content-Length: 335 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:49 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:56 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/nat/nodes/{node_id} { "name": "Nat 1", - "node_id": "2d520206-fba0-4b14-9fac-c065701eab55", + "node_id": "620cae24-6a49-4608-8c21-8367f1e57cfc", "ports_mapping": [ { "interface": "virbr0", diff --git a/docs/api/examples/compute_get_projectsprojectidqemunodesnodeid.txt b/docs/api/examples/compute_get_projectsprojectidqemunodesnodeid.txt index ece08136..041740ef 100644 --- a/docs/api/examples/compute_get_projectsprojectidqemunodesnodeid.txt +++ b/docs/api/examples/compute_get_projectsprojectidqemunodesnodeid.txt @@ -1,19 +1,18 @@ -curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/24403711-3db5-4cae-abae-956bfbf08519' +curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/94667ffb-fb8f-4fac-8003-242b720591c3' -GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/24403711-3db5-4cae-abae-956bfbf08519 HTTP/1.1 +GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/94667ffb-fb8f-4fac-8003-242b720591c3 HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 1468 +Content-Length: 1381 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:55 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:19 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id} { - "acpi_shutdown": false, "adapter_type": "e1000", "adapters": 1, "bios_image": "", @@ -44,15 +43,16 @@ X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id} "kernel_image": "", "kernel_image_md5sum": null, "legacy_networking": false, - "mac_address": "00:dd:80:85:19:00", + "mac_address": "0c:dd:80:91:c3:00", "name": "PC TEST 1", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/qemu/24403711-3db5-4cae-abae-956bfbf08519", - "node_id": "24403711-3db5-4cae-abae-956bfbf08519", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/qemu/94667ffb-fb8f-4fac-8003-242b720591c3", + "node_id": "94667ffb-fb8f-4fac-8003-242b720591c3", + "on_close": "power_off", "options": "", "platform": "x86_64", "process_priority": "low", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", - "qemu_path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp26lo7e4o/qemu-system-x86_64", + "qemu_path": "/tmp/tmpjg3j58ga/qemu-system-x86_64", "ram": 256, "status": "stopped", "usage": "" diff --git a/docs/api/examples/compute_get_projectsprojectidtracengnodesnodeid.txt b/docs/api/examples/compute_get_projectsprojectidtracengnodesnodeid.txt new file mode 100644 index 00000000..0885f615 --- /dev/null +++ b/docs/api/examples/compute_get_projectsprojectidtracengnodesnodeid.txt @@ -0,0 +1,26 @@ +curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/f1e6bf7a-d927-43ee-9c32-d012602ef405' + +GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/f1e6bf7a-d927-43ee-9c32-d012602ef405 HTTP/1.1 + + + +HTTP/1.1 200 +Connection: close +Content-Length: 443 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:50 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id} + +{ + "command_line": "", + "console": null, + "console_type": "none", + "default_destination": "", + "ip_address": "", + "name": "TraceNG TEST 1", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/traceng/f1e6bf7a-d927-43ee-9c32-d012602ef405", + "node_id": "f1e6bf7a-d927-43ee-9c32-d012602ef405", + "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", + "status": "stopped" +} diff --git a/docs/api/examples/compute_get_projectsprojectidvirtualboxnodesnodeid.txt b/docs/api/examples/compute_get_projectsprojectidvirtualboxnodesnodeid.txt index b1e56213..58027054 100644 --- a/docs/api/examples/compute_get_projectsprojectidvirtualboxnodesnodeid.txt +++ b/docs/api/examples/compute_get_projectsprojectidvirtualboxnodesnodeid.txt @@ -1,19 +1,18 @@ -curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/0e9631fd-c8b4-4a21-bba1-2fe71d2387e0' +curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/ee5edbb1-c7cc-4db2-b16f-2389b75d3f7b' -GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/0e9631fd-c8b4-4a21-bba1-2fe71d2387e0 HTTP/1.1 +GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/ee5edbb1-c7cc-4db2-b16f-2389b75d3f7b HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 465 +Content-Length: 483 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:57 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id} { - "acpi_shutdown": false, "adapter_type": "Intel PRO/1000 MT Desktop (82540EM)", "adapters": 0, "console": 5004, @@ -22,10 +21,12 @@ X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id} "linked_clone": false, "name": "VMTEST", "node_directory": null, - "node_id": "0e9631fd-c8b4-4a21-bba1-2fe71d2387e0", + "node_id": "ee5edbb1-c7cc-4db2-b16f-2389b75d3f7b", + "on_close": "power_off", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "ram": 0, "status": "stopped", + "usage": "", "use_any_adapter": false, "vmname": "VMTEST" } diff --git a/docs/api/examples/compute_get_projectsprojectidvmwarenodesnodeid.txt b/docs/api/examples/compute_get_projectsprojectidvmwarenodesnodeid.txt index 2bb99c63..f87d0cd7 100644 --- a/docs/api/examples/compute_get_projectsprojectidvmwarenodesnodeid.txt +++ b/docs/api/examples/compute_get_projectsprojectidvmwarenodesnodeid.txt @@ -1,19 +1,18 @@ -curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/1cb7bfee-78f2-442d-8c62-da5fba43c91a' +curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/adcea44c-6419-4253-a4e9-d851abc1ddb4' -GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/1cb7bfee-78f2-442d-8c62-da5fba43c91a HTTP/1.1 +GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/adcea44c-6419-4253-a4e9-d851abc1ddb4 HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 688 +Content-Length: 610 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:59 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:55 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id} { - "acpi_shutdown": false, "adapter_type": "e1000", "adapters": 0, "console": 5004, @@ -21,10 +20,12 @@ X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id} "headless": false, "linked_clone": false, "name": "VMTEST", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vmware/1cb7bfee-78f2-442d-8c62-da5fba43c91a", - "node_id": "1cb7bfee-78f2-442d-8c62-da5fba43c91a", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vmware/adcea44c-6419-4253-a4e9-d851abc1ddb4", + "node_id": "adcea44c-6419-4253-a4e9-d851abc1ddb4", + "on_close": "power_off", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "status": "stopped", + "usage": "", "use_any_adapter": false, - "vmx_path": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_vmware_get0/test.vmx" + "vmx_path": "/tmp/pytest-of-grossmj/pytest-0/test_vmware_get0/test.vmx" } diff --git a/docs/api/examples/compute_get_projectsprojectidvpcsnodesnodeid.txt b/docs/api/examples/compute_get_projectsprojectidvpcsnodesnodeid.txt index 84d97efe..887ae763 100644 --- a/docs/api/examples/compute_get_projectsprojectidvpcsnodesnodeid.txt +++ b/docs/api/examples/compute_get_projectsprojectidvpcsnodesnodeid.txt @@ -1,15 +1,15 @@ -curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/ba38f0b3-b87d-4f60-a2b8-47fef0cf9ab7' +curl -i -X GET 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/b9391d74-c99f-4efc-a120-a3f781cbf80f' -GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/ba38f0b3-b87d-4f60-a2b8-47fef0cf9ab7 HTTP/1.1 +GET /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/b9391d74-c99f-4efc-a120-a3f781cbf80f HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 428 +Content-Length: 384 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:44 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id} { @@ -17,8 +17,8 @@ X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id} "console": 5004, "console_type": "telnet", "name": "PC TEST 1", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vpcs/ba38f0b3-b87d-4f60-a2b8-47fef0cf9ab7", - "node_id": "ba38f0b3-b87d-4f60-a2b8-47fef0cf9ab7", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vpcs/b9391d74-c99f-4efc-a120-a3f781cbf80f", + "node_id": "b9391d74-c99f-4efc-a120-a3f781cbf80f", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "status": "stopped" } diff --git a/docs/api/examples/compute_get_qemubinaries.txt b/docs/api/examples/compute_get_qemubinaries.txt index fd0fb43a..1b00bbb6 100644 --- a/docs/api/examples/compute_get_qemubinaries.txt +++ b/docs/api/examples/compute_get_qemubinaries.txt @@ -12,8 +12,8 @@ HTTP/1.1 200 Connection: close Content-Length: 212 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:57 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:41 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/qemu/binaries [ diff --git a/docs/api/examples/compute_get_qemucapabilities.txt b/docs/api/examples/compute_get_qemucapabilities.txt index 55bd4a8d..7e914527 100644 --- a/docs/api/examples/compute_get_qemucapabilities.txt +++ b/docs/api/examples/compute_get_qemucapabilities.txt @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 39 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:57 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:47 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/qemu/capabilities { diff --git a/docs/api/examples/compute_get_version.txt b/docs/api/examples/compute_get_version.txt index 1aca034a..11ae3197 100644 --- a/docs/api/examples/compute_get_version.txt +++ b/docs/api/examples/compute_get_version.txt @@ -8,11 +8,11 @@ HTTP/1.1 200 Connection: close Content-Length: 49 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:57 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:50 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/version { "local": true, - "version": "2.1.2dev1" + "version": "2.2.0dev8" } diff --git a/docs/api/examples/compute_post_projects.txt b/docs/api/examples/compute_post_projects.txt index c3c7022d..623a40c2 100644 --- a/docs/api/examples/compute_post_projects.txt +++ b/docs/api/examples/compute_post_projects.txt @@ -9,13 +9,14 @@ POST /v2/compute/projects HTTP/1.1 HTTP/1.1 201 Connection: close -Content-Length: 80 +Content-Length: 103 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:54 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:58 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects { "name": "test", - "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f" + "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f", + "variables": null } diff --git a/docs/api/examples/compute_post_projectsprojectidclose.txt b/docs/api/examples/compute_post_projectsprojectidclose.txt index 6554fc1f..935706a9 100644 --- a/docs/api/examples/compute_post_projectsprojectidclose.txt +++ b/docs/api/examples/compute_post_projectsprojectidclose.txt @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:55 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:59 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/close diff --git a/docs/api/examples/compute_post_projectsprojectidcloudnodes.txt b/docs/api/examples/compute_post_projectsprojectidcloudnodes.txt index dc5c9802..22c67f96 100644 --- a/docs/api/examples/compute_post_projectsprojectidcloudnodes.txt +++ b/docs/api/examples/compute_post_projectsprojectidcloudnodes.txt @@ -8,73 +8,95 @@ POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes HTTP/ HTTP/1.1 201 Connection: close -Content-Length: 1584 +Content-Length: 2080 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:42 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:36 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/cloud/nodes { "interfaces": [ { - "name": "bridge0", + "name": "docker0", "special": true, "type": "ethernet" }, { - "name": "en0", + "name": "lo", + "special": true, + "type": "ethernet" + }, + { + "name": "vboxnet0", + "special": true, + "type": "ethernet" + }, + { + "name": "vboxnet1", + "special": true, + "type": "ethernet" + }, + { + "name": "vboxnet2", + "special": true, + "type": "ethernet" + }, + { + "name": "virbr0", + "special": true, + "type": "ethernet" + }, + { + "name": "virbr0-nic", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet1", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet2", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet3", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet4", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet8", + "special": true, + "type": "ethernet" + }, + { + "name": "wlp58s0", "special": false, "type": "ethernet" - }, - { - "name": "en1", - "special": false, - "type": "ethernet" - }, - { - "name": "en2", - "special": false, - "type": "ethernet" - }, - { - "name": "fw0", - "special": true, - "type": "ethernet" - }, - { - "name": "lo0", - "special": true, - "type": "ethernet" - }, - { - "name": "p2p0", - "special": true, - "type": "ethernet" } ], "name": "Cloud 1", - "node_directory": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/project-files/builtin/f5c51574-0032-419f-af7e-87edd8cab649", - "node_id": "f5c51574-0032-419f-af7e-87edd8cab649", + "node_directory": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/builtin/52c21d2b-9348-4945-b541-107aabe9fe79", + "node_id": "52c21d2b-9348-4945-b541-107aabe9fe79", "ports_mapping": [ { - "interface": "en0", - "name": "en0", + "interface": "wlp58s0", + "name": "wlp58s0", "port_number": 0, "type": "ethernet" - }, - { - "interface": "en1", - "name": "en1", - "port_number": 1, - "type": "ethernet" - }, - { - "interface": "en2", - "name": "en2", - "port_number": 2, - "type": "ethernet" } ], "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", + "remote_console_host": "", + "remote_console_http_path": "/", + "remote_console_port": 23, + "remote_console_type": "none", "status": "started" } diff --git a/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index d68bc365..67dd161c 100644 --- a/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/dbff6f53-7446-4c8f-bebb-38b568b1edc6/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/872594c6-31ff-401d-a93a-8ffc545219fc/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/dbff6f53-7446-4c8f-bebb-38b568b1edc6/adapters/0/ports/0/nio HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/872594c6-31ff-401d-a93a-8ffc545219fc/adapters/0/ports/0/nio HTTP/1.1 { "lport": 4242, "rhost": "127.0.0.1", @@ -13,8 +13,8 @@ HTTP/1.1 201 Connection: close Content-Length: 89 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:43 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:36 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt b/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt new file mode 100644 index 00000000..50c11199 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt @@ -0,0 +1,20 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/3bb37e84-4a74-454c-8203-3a186d08edf2/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/3bb37e84-4a74-454c-8203-3a186d08edf2/adapters/0/ports/0/start_capture HTTP/1.1 +{ + "capture_file_name": "test.pcap", + "data_link_type": "DLT_EN10MB" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 103 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:47:38 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture + +{ + "pcap_file_path": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/captures/test.pcap" +} diff --git a/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt b/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt new file mode 100644 index 00000000..65d69e59 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt @@ -0,0 +1,14 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/1492f546-a85e-4cb6-91e7-97890c84cf5c/adapters/0/ports/0/stop_capture' -d '{}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/1492f546-a85e-4cb6-91e7-97890c84cf5c/adapters/0/ports/0/stop_capture HTTP/1.1 +{} + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:47:38 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture + diff --git a/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt index f033d818..e321ae13 100644 --- a/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/22a7d45d-7024-4303-bfd6-bedd6bab4037/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/8e4d6773-6943-44a0-b607-ceed7b0caf51/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/22a7d45d-7024-4303-bfd6-bedd6bab4037/adapters/0/ports/0/nio HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/8e4d6773-6943-44a0-b607-ceed7b0caf51/adapters/0/ports/0/nio HTTP/1.1 { "lport": 4242, "rhost": "127.0.0.1", @@ -13,8 +13,8 @@ HTTP/1.1 201 Connection: close Content-Length: 89 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:46 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:39 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt b/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt index 4fa39c43..b560d78e 100644 --- a/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt +++ b/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/283cc38e-c13f-41e9-951e-42c9723fb3bc/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/b1aa7be8-9b00-415d-8a55-5c7896aaa9b3/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/283cc38e-c13f-41e9-951e-42c9723fb3bc/adapters/0/ports/0/start_capture HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/b1aa7be8-9b00-415d-8a55-5c7896aaa9b3/adapters/0/ports/0/start_capture HTTP/1.1 { "capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB" @@ -9,12 +9,12 @@ POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/283c HTTP/1.1 200 Connection: close -Content-Length: 145 +Content-Length: 103 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:46 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:39 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture { - "pcap_file_path": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/tmp/captures/test.pcap" + "pcap_file_path": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/captures/test.pcap" } diff --git a/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt b/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt index 75805247..2bfaedd6 100644 --- a/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt +++ b/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/b25504e3-b9a3-42c4-8280-bc590448deb4/adapters/0/ports/0/stop_capture' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/dceae966-3bef-4ba6-b194-7cc20441b629/adapters/0/ports/0/stop_capture' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/b25504e3-b9a3-42c4-8280-bc590448deb4/adapters/0/ports/0/stop_capture HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/dceae966-3bef-4ba6-b194-7cc20441b629/adapters/0/ports/0/stop_capture HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:47 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:39 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture diff --git a/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidduplicate.txt b/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidduplicate.txt index 952cc8b2..121b8169 100644 --- a/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidduplicate.txt +++ b/docs/api/examples/compute_post_projectsprojectiddockernodesnodeidduplicate.txt @@ -1,8 +1,8 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/3abf5f1e-3d86-41f1-8fe7-9b6e2b89f236/duplicate' -d '{"destination_node_id": "933fb9ff-759b-4781-8da7-ff28bd3c4a8d"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/2a4f5dd4-ad8e-4452-94dc-48d152a179d6/duplicate' -d '{"destination_node_id": "621aef4c-7561-4741-9c17-6abbec80622e"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/3abf5f1e-3d86-41f1-8fe7-9b6e2b89f236/duplicate HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/2a4f5dd4-ad8e-4452-94dc-48d152a179d6/duplicate HTTP/1.1 { - "destination_node_id": "933fb9ff-759b-4781-8da7-ff28bd3c4a8d" + "destination_node_id": "621aef4c-7561-4741-9c17-6abbec80622e" } @@ -10,8 +10,8 @@ HTTP/1.1 201 Connection: close Content-Length: 4 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:47 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:40 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/docker/nodes/{node_id}/duplicate true diff --git a/docs/api/examples/compute_post_projectsprojectidiounodes.txt b/docs/api/examples/compute_post_projectsprojectidiounodes.txt index 81cc286e..7c0a051b 100644 --- a/docs/api/examples/compute_post_projectsprojectidiounodes.txt +++ b/docs/api/examples/compute_post_projectsprojectidiounodes.txt @@ -1,9 +1,9 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes' -d '{"name": "PC TEST 1", "node_id": "2a40df31-c258-409e-8aa3-466baab4bb1a", "path": "iou.bin", "startup_config_content": "hostname test"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes' -d '{"name": "PC TEST 1", "node_id": "3a4a4104-8ef4-4726-aa00-8b38672f82ce", "path": "iou.bin", "startup_config_content": "hostname test"}' POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes HTTP/1.1 { "name": "PC TEST 1", - "node_id": "2a40df31-c258-409e-8aa3-466baab4bb1a", + "node_id": "3a4a4104-8ef4-4726-aa00-8b38672f82ce", "path": "iou.bin", "startup_config_content": "hostname test" } @@ -11,10 +11,10 @@ POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes HTTP/1. HTTP/1.1 201 Connection: close -Content-Length: 665 +Content-Length: 630 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:47 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes { @@ -26,13 +26,14 @@ X-Route: /v2/compute/projects/{project_id}/iou/nodes "l1_keepalives": false, "md5sum": "e573e8f5c93c6c00783f20c7a170aa6c", "name": "PC TEST 1", - "node_directory": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/project-files/iou/2a40df31-c258-409e-8aa3-466baab4bb1a", - "node_id": "2a40df31-c258-409e-8aa3-466baab4bb1a", + "node_directory": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/iou/3a4a4104-8ef4-4726-aa00-8b38672f82ce", + "node_id": "3a4a4104-8ef4-4726-aa00-8b38672f82ce", "nvram": 128, "path": "iou.bin", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "ram": 256, "serial_adapters": 2, "status": "stopped", + "usage": "", "use_default_iou_values": true } diff --git a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 0884bf6c..0fba3c73 100644 --- a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,8 +1,8 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/bde9180a-13f9-484b-93b7-7cd79dd12e59/adapters/1/ports/0/nio' -d '{"ethernet_device": "bridge0", "type": "nio_ethernet"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/f2f7e520-ee5d-4583-8dcb-0a23f575ca0b/adapters/1/ports/0/nio' -d '{"ethernet_device": "docker0", "type": "nio_ethernet"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/bde9180a-13f9-484b-93b7-7cd79dd12e59/adapters/1/ports/0/nio HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/f2f7e520-ee5d-4583-8dcb-0a23f575ca0b/adapters/1/ports/0/nio HTTP/1.1 { - "ethernet_device": "bridge0", + "ethernet_device": "docker0", "type": "nio_ethernet" } @@ -11,11 +11,11 @@ HTTP/1.1 201 Connection: close Content-Length: 64 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:48 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { - "ethernet_device": "bridge0", + "ethernet_device": "docker0", "type": "nio_ethernet" } diff --git a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt index 0c63abaf..920e35ae 100644 --- a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt +++ b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/2c1dfb5a-629f-4f71-a28b-32b5afdda38c/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/2ac89cba-1663-460d-8f75-22d2f9127e8c/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/2c1dfb5a-629f-4f71-a28b-32b5afdda38c/adapters/0/ports/0/start_capture HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/2ac89cba-1663-460d-8f75-22d2f9127e8c/adapters/0/ports/0/start_capture HTTP/1.1 { "capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB" @@ -9,12 +9,12 @@ POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/2c1dfb5 HTTP/1.1 200 Connection: close -Content-Length: 145 +Content-Length: 103 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:48 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:54 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture { - "pcap_file_path": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/tmp/captures/test.pcap" + "pcap_file_path": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/captures/test.pcap" } diff --git a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt index ca7c6451..be5fea67 100644 --- a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt +++ b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/1fe06fbf-df85-4a1e-8719-9bcee87e95c3/adapters/0/ports/0/stop_capture' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/c3e2df2b-b6c6-4bb7-b8bc-649a01e30cda/adapters/0/ports/0/stop_capture' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/1fe06fbf-df85-4a1e-8719-9bcee87e95c3/adapters/0/ports/0/stop_capture HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/c3e2df2b-b6c6-4bb7-b8bc-649a01e30cda/adapters/0/ports/0/stop_capture HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:48 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:55 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture diff --git a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidduplicate.txt b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidduplicate.txt index 6a5bdf33..fed57392 100644 --- a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidduplicate.txt +++ b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidduplicate.txt @@ -1,8 +1,8 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/5004383e-1288-434b-bb06-86d2831b3197/duplicate' -d '{"destination_node_id": "10e25f8a-476d-46d0-a152-ffce1c0a1e6d"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/868f9f30-4a19-44a5-89e6-01f3eb539e6f/duplicate' -d '{"destination_node_id": "f1236c95-e376-494d-8c36-b7c097f5a74e"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/5004383e-1288-434b-bb06-86d2831b3197/duplicate HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/868f9f30-4a19-44a5-89e6-01f3eb539e6f/duplicate HTTP/1.1 { - "destination_node_id": "10e25f8a-476d-46d0-a152-ffce1c0a1e6d" + "destination_node_id": "f1236c95-e376-494d-8c36-b7c097f5a74e" } @@ -10,8 +10,8 @@ HTTP/1.1 201 Connection: close Content-Length: 4 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:49 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:56 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/duplicate true diff --git a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidreload.txt b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidreload.txt index 9f35b297..e6a043e9 100644 --- a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidreload.txt +++ b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidreload.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/920627e2-ac0a-4ff5-b7f0-92146d119cfa/reload' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/0eb2fd65-d114-4609-ae8f-4a499e1ae21e/reload' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/920627e2-ac0a-4ff5-b7f0-92146d119cfa/reload HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/0eb2fd65-d114-4609-ae8f-4a499e1ae21e/reload HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:47 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/reload diff --git a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidstart.txt b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidstart.txt index 1aded760..5a3abd59 100644 --- a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidstart.txt +++ b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidstart.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/7aaf8730-a591-434b-832c-545c3fdace21/start' -d '{"iourc_content": "test"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/b8bf9529-f866-42f0-96b7-9f4ff0da73c2/start' -d '{"iourc_content": "test"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/7aaf8730-a591-434b-832c-545c3fdace21/start HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/b8bf9529-f866-42f0-96b7-9f4ff0da73c2/start HTTP/1.1 { "iourc_content": "test" } @@ -8,10 +8,10 @@ POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/7aaf873 HTTP/1.1 200 Connection: close -Content-Length: 665 +Content-Length: 630 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:47 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/start { @@ -23,13 +23,14 @@ X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/start "l1_keepalives": false, "md5sum": "e573e8f5c93c6c00783f20c7a170aa6c", "name": "PC TEST 1", - "node_directory": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/project-files/iou/7aaf8730-a591-434b-832c-545c3fdace21", - "node_id": "7aaf8730-a591-434b-832c-545c3fdace21", + "node_directory": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/iou/b8bf9529-f866-42f0-96b7-9f4ff0da73c2", + "node_id": "b8bf9529-f866-42f0-96b7-9f4ff0da73c2", "nvram": 128, "path": "iou.bin", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "ram": 256, "serial_adapters": 2, "status": "stopped", + "usage": "", "use_default_iou_values": true } diff --git a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidstop.txt b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidstop.txt index 448a837b..b26ff9d2 100644 --- a/docs/api/examples/compute_post_projectsprojectidiounodesnodeidstop.txt +++ b/docs/api/examples/compute_post_projectsprojectidiounodesnodeidstop.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/815fcdf5-75d2-48a4-99b1-f4651460c031/stop' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/418fee34-c56a-437c-8a60-b9fb5adf85e4/stop' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/815fcdf5-75d2-48a4-99b1-f4651460c031/stop HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/418fee34-c56a-437c-8a60-b9fb5adf85e4/stop HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:47 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/stop diff --git a/docs/api/examples/compute_post_projectsprojectidnatnodes.txt b/docs/api/examples/compute_post_projectsprojectidnatnodes.txt index e53c3018..643276d7 100644 --- a/docs/api/examples/compute_post_projectsprojectidnatnodes.txt +++ b/docs/api/examples/compute_post_projectsprojectidnatnodes.txt @@ -10,13 +10,13 @@ HTTP/1.1 201 Connection: close Content-Length: 335 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:49 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:56 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/nat/nodes { "name": "Nat 1", - "node_id": "bb9f6090-ce62-461c-8457-babcbabe1417", + "node_id": "aef6720f-e0cb-43cb-bd32-6cd83bfee5dd", "ports_mapping": [ { "interface": "virbr0", diff --git a/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 6a1c7fb3..6eb7c4fb 100644 --- a/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/7ac53432-e8aa-41ab-b3fe-a0278f0dd73b/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/6d7317fd-73f0-4311-ba21-f974925b17bf/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/7ac53432-e8aa-41ab-b3fe-a0278f0dd73b/adapters/0/ports/0/nio HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/6d7317fd-73f0-4311-ba21-f974925b17bf/adapters/0/ports/0/nio HTTP/1.1 { "lport": 4242, "rhost": "127.0.0.1", @@ -13,8 +13,8 @@ HTTP/1.1 201 Connection: close Content-Length: 89 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:49 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:56 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt b/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt new file mode 100644 index 00000000..5421c03a --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt @@ -0,0 +1,20 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/85c32b82-3012-4917-9c1f-bc4c6cc7e35b/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/85c32b82-3012-4917-9c1f-bc4c6cc7e35b/adapters/0/ports/0/start_capture HTTP/1.1 +{ + "capture_file_name": "test.pcap", + "data_link_type": "DLT_EN10MB" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 103 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:47:57 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture + +{ + "pcap_file_path": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/captures/test.pcap" +} diff --git a/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt b/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt new file mode 100644 index 00000000..574c3046 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt @@ -0,0 +1,14 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/400c5707-217f-4270-852a-e9f3c5b9cca2/adapters/0/ports/0/stop_capture' -d '{}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/400c5707-217f-4270-852a-e9f3c5b9cca2/adapters/0/ports/0/stop_capture HTTP/1.1 +{} + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:47:57 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture + diff --git a/docs/api/examples/compute_post_projectsprojectidportsudp.txt b/docs/api/examples/compute_post_projectsprojectidportsudp.txt index c0eab42b..4308ce88 100644 --- a/docs/api/examples/compute_post_projectsprojectidportsudp.txt +++ b/docs/api/examples/compute_post_projectsprojectidportsudp.txt @@ -8,8 +8,8 @@ HTTP/1.1 201 Connection: close Content-Length: 25 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:54 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:58 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/ports/udp { diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodes.txt b/docs/api/examples/compute_post_projectsprojectidqemunodes.txt index 399b0eb4..8645047a 100644 --- a/docs/api/examples/compute_post_projectsprojectidqemunodes.txt +++ b/docs/api/examples/compute_post_projectsprojectidqemunodes.txt @@ -1,24 +1,22 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes' -d '{"hda_disk_image": "linux\u8f7d.img", "name": "PC TEST 1", "qemu_path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp26lo7e4o/qemu-system-x86_64", "ram": 1024}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes' -d '{"hda_disk_image": "hello.img", "name": "PC TEST 1", "qemu_path": "/tmp/tmpjg3j58ga/qemu-system-x86_64"}' POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes HTTP/1.1 { - "hda_disk_image": "linux\u8f7d.img", + "hda_disk_image": "hello.img", "name": "PC TEST 1", - "qemu_path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp26lo7e4o/qemu-system-x86_64", - "ram": 1024 + "qemu_path": "/tmp/tmpjg3j58ga/qemu-system-x86_64" } HTTP/1.1 201 Connection: close -Content-Length: 1514 +Content-Length: 1420 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:55 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:17 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes { - "acpi_shutdown": false, "adapter_type": "e1000", "adapters": 1, "bios_image": "", @@ -31,8 +29,8 @@ X-Route: /v2/compute/projects/{project_id}/qemu/nodes "console_type": "telnet", "cpu_throttling": 0, "cpus": 1, - "hda_disk_image": "linux\u8f7d.img", - "hda_disk_image_md5sum": "c4ca4238a0b923820dcc509a6f75849b", + "hda_disk_image": "hello.img", + "hda_disk_image_md5sum": "7d793037a0760186574b0282f2f435e7", "hda_disk_interface": "ide", "hdb_disk_image": "", "hdb_disk_image_md5sum": null, @@ -49,16 +47,17 @@ X-Route: /v2/compute/projects/{project_id}/qemu/nodes "kernel_image": "", "kernel_image_md5sum": null, "legacy_networking": false, - "mac_address": "00:dd:80:61:ca:00", + "mac_address": "0c:dd:80:c7:ca:00", "name": "PC TEST 1", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/qemu/c5506ba4-66a1-4b97-b632-0b73291161ca", - "node_id": "c5506ba4-66a1-4b97-b632-0b73291161ca", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/qemu/5cb24b0b-7252-4b97-85aa-31efaf6dc7ca", + "node_id": "5cb24b0b-7252-4b97-85aa-31efaf6dc7ca", + "on_close": "power_off", "options": "", "platform": "x86_64", "process_priority": "low", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", - "qemu_path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp26lo7e4o/qemu-system-x86_64", - "ram": 1024, + "qemu_path": "/tmp/tmpjg3j58ga/qemu-system-x86_64", + "ram": 256, "status": "stopped", "usage": "" } diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt index bcac1dec..2b5b1d34 100644 --- a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/61a9f99e-3542-49a5-b082-fd154577b1da/adapters/1/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/0afa5ce7-44ef-48df-906e-fb9b53b65924/adapters/1/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/61a9f99e-3542-49a5-b082-fd154577b1da/adapters/1/ports/0/nio HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/0afa5ce7-44ef-48df-906e-fb9b53b65924/adapters/1/ports/0/nio HTTP/1.1 { "lport": 4242, "rhost": "127.0.0.1", @@ -13,8 +13,8 @@ HTTP/1.1 201 Connection: close Content-Length: 89 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:40 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt new file mode 100644 index 00000000..7a839f9d --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt @@ -0,0 +1,20 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/c963f115-ea5a-44d8-b96f-06612cb2fcc4/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/c963f115-ea5a-44d8-b96f-06612cb2fcc4/adapters/0/ports/0/start_capture HTTP/1.1 +{ + "capture_file_name": "test.pcap", + "data_link_type": "DLT_EN10MB" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 123 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture + +{ + "pcap_file_path": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/captures/test.pcap" +} diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt new file mode 100644 index 00000000..11abcaf1 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt @@ -0,0 +1,14 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/195d0083-2c8b-48cc-abe3-5965308d135b/adapters/0/ports/0/stop_capture' -d '{}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/195d0083-2c8b-48cc-abe3-5965308d135b/adapters/0/ports/0/stop_capture HTTP/1.1 +{} + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:48:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture + diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidduplicate.txt b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidduplicate.txt index 0702c4b1..60dbaa08 100644 --- a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidduplicate.txt +++ b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidduplicate.txt @@ -1,8 +1,8 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/991224a4-0c6a-46f5-a9cf-7a7b03dd2f7f/duplicate' -d '{"destination_node_id": "ddc56104-6d5b-44b8-8883-560df43c12d4"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/a6d2e376-d9b9-4d2f-b955-74939a34a278/duplicate' -d '{"destination_node_id": "0a133429-a8ea-44f3-8a35-d52ec14bf92c"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/991224a4-0c6a-46f5-a9cf-7a7b03dd2f7f/duplicate HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/a6d2e376-d9b9-4d2f-b955-74939a34a278/duplicate HTTP/1.1 { - "destination_node_id": "ddc56104-6d5b-44b8-8883-560df43c12d4" + "destination_node_id": "0a133429-a8ea-44f3-8a35-d52ec14bf92c" } @@ -10,8 +10,8 @@ HTTP/1.1 201 Connection: close Content-Length: 4 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:57 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/duplicate true diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidreload.txt b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidreload.txt index 1ef73170..76c39319 100644 --- a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidreload.txt +++ b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidreload.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/a5001f88-4ea1-4c30-b150-0b64d6468114/reload' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/318670f6-d34a-49c8-9086-96a55fbdfe5d/reload' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/a5001f88-4ea1-4c30-b150-0b64d6468114/reload HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/318670f6-d34a-49c8-9086-96a55fbdfe5d/reload HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:25 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/reload diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidresume.txt b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidresume.txt index 86644775..51ccb90f 100644 --- a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidresume.txt +++ b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidresume.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/47c84302-343c-49ec-88aa-d6df5c12ca76/resume' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/d782eac8-1a49-4390-bddd-9e5abfb91a7e/resume' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/47c84302-343c-49ec-88aa-d6df5c12ca76/resume HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/d782eac8-1a49-4390-bddd-9e5abfb91a7e/resume HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:34 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/resume diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidstart.txt b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidstart.txt index eff36977..e7aeea1f 100644 --- a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidstart.txt +++ b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidstart.txt @@ -1,19 +1,18 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/549b4a45-e05f-46f7-9162-9c8917cfdbd2/start' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/27170ede-eb4a-4587-9f34-5feef70b64f5/start' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/549b4a45-e05f-46f7-9162-9c8917cfdbd2/start HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/27170ede-eb4a-4587-9f34-5feef70b64f5/start HTTP/1.1 {} HTTP/1.1 200 Connection: close -Content-Length: 1468 +Content-Length: 1381 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:20 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/start { - "acpi_shutdown": false, "adapter_type": "e1000", "adapters": 1, "bios_image": "", @@ -44,15 +43,16 @@ X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/start "kernel_image": "", "kernel_image_md5sum": null, "legacy_networking": false, - "mac_address": "00:dd:80:db:d2:00", + "mac_address": "0c:dd:80:64:f5:00", "name": "PC TEST 1", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/qemu/549b4a45-e05f-46f7-9162-9c8917cfdbd2", - "node_id": "549b4a45-e05f-46f7-9162-9c8917cfdbd2", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/qemu/27170ede-eb4a-4587-9f34-5feef70b64f5", + "node_id": "27170ede-eb4a-4587-9f34-5feef70b64f5", + "on_close": "power_off", "options": "", "platform": "x86_64", "process_priority": "low", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", - "qemu_path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp26lo7e4o/qemu-system-x86_64", + "qemu_path": "/tmp/tmpjg3j58ga/qemu-system-x86_64", "ram": 256, "status": "stopped", "usage": "" diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidstop.txt b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidstop.txt index 8ad14370..d7aab927 100644 --- a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidstop.txt +++ b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidstop.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/76838b21-f233-49fc-8b9e-efb44e924770/stop' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/02827bc3-3459-4217-b2dc-1711f6331c99/stop' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/76838b21-f233-49fc-8b9e-efb44e924770/stop HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/02827bc3-3459-4217-b2dc-1711f6331c99/stop HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:23 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/stop diff --git a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidsuspend.txt b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidsuspend.txt index 605a1990..0906204f 100644 --- a/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidsuspend.txt +++ b/docs/api/examples/compute_post_projectsprojectidqemunodesnodeidsuspend.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/0e83b0b6-4a6a-4c59-9f1d-cd38eef8d8c3/suspend' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/0960fea6-6ee6-4f5b-82dc-090cbea3c67d/suspend' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/0e83b0b6-4a6a-4c59-9f1d-cd38eef8d8c3/suspend HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/0960fea6-6ee6-4f5b-82dc-090cbea3c67d/suspend HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:28 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/suspend diff --git a/docs/api/examples/compute_post_projectsprojectidtracengnodes.txt b/docs/api/examples/compute_post_projectsprojectidtracengnodes.txt new file mode 100644 index 00000000..703a464e --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidtracengnodes.txt @@ -0,0 +1,28 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes' -d '{"name": "TraceNG TEST 1"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes HTTP/1.1 +{ + "name": "TraceNG TEST 1" +} + + +HTTP/1.1 201 +Connection: close +Content-Length: 443 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:50 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes + +{ + "command_line": "", + "console": null, + "console_type": "none", + "default_destination": "", + "ip_address": "", + "name": "TraceNG TEST 1", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/traceng/d210c8c7-3943-49c5-81ef-9a465b13a4ea", + "node_id": "d210c8c7-3943-49c5-81ef-9a465b13a4ea", + "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", + "status": "stopped" +} diff --git a/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt new file mode 100644 index 00000000..fcb08c73 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -0,0 +1,25 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/e152b6ae-e44e-479e-9934-2298cc93cdb9/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/e152b6ae-e44e-479e-9934-2298cc93cdb9/adapters/0/ports/0/nio HTTP/1.1 +{ + "lport": 4242, + "rhost": "127.0.0.1", + "rport": 4343, + "type": "nio_udp" +} + + +HTTP/1.1 201 +Connection: close +Content-Length: 89 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:50 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio + +{ + "lport": 4242, + "rhost": "127.0.0.1", + "rport": 4343, + "type": "nio_udp" +} diff --git a/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt new file mode 100644 index 00000000..04718758 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt @@ -0,0 +1,20 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/9307ddf4-2ec7-4051-bf2e-1af1736cccfe/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/9307ddf4-2ec7-4051-bf2e-1af1736cccfe/adapters/0/ports/0/start_capture HTTP/1.1 +{ + "capture_file_name": "test.pcap", + "data_link_type": "DLT_EN10MB" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 123 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture + +{ + "pcap_file_path": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/captures/test.pcap" +} diff --git a/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt new file mode 100644 index 00000000..a8719c58 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt @@ -0,0 +1,14 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/f7778b34-efd8-4abc-b8d2-4c72b63db100/adapters/0/ports/0/stop_capture' -d '{}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/f7778b34-efd8-4abc-b8d2-4c72b63db100/adapters/0/ports/0/stop_capture HTTP/1.1 +{} + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:48:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture + diff --git a/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidduplicate.txt b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidduplicate.txt new file mode 100644 index 00000000..de7d06ff --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidduplicate.txt @@ -0,0 +1,17 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/870e9937-77a9-467b-a854-32e23449ec8a/duplicate' -d '{"destination_node_id": "f5f44123-29c4-4462-a705-f6265bfbe5eb"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/870e9937-77a9-467b-a854-32e23449ec8a/duplicate HTTP/1.1 +{ + "destination_node_id": "f5f44123-29c4-4462-a705-f6265bfbe5eb" +} + + +HTTP/1.1 201 +Connection: close +Content-Length: 4 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id}/duplicate + +true diff --git a/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidreload.txt b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidreload.txt new file mode 100644 index 00000000..fbfa0c5a --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidreload.txt @@ -0,0 +1,14 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/43adaa30-d077-4fcb-9219-450d5f96521b/reload' -d '{}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/43adaa30-d077-4fcb-9219-450d5f96521b/reload HTTP/1.1 +{} + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:48:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id}/reload + diff --git a/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidstart.txt b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidstart.txt new file mode 100644 index 00000000..f9794609 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidstart.txt @@ -0,0 +1,28 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/d6de7db3-8114-4f10-b738-9f07f9f5e076/start' -d '{"destination": "192.168.1.2"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/d6de7db3-8114-4f10-b738-9f07f9f5e076/start HTTP/1.1 +{ + "destination": "192.168.1.2" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 443 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id}/start + +{ + "command_line": "", + "console": null, + "console_type": "none", + "default_destination": "", + "ip_address": "", + "name": "TraceNG TEST 1", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/traceng/d6de7db3-8114-4f10-b738-9f07f9f5e076", + "node_id": "d6de7db3-8114-4f10-b738-9f07f9f5e076", + "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", + "status": "stopped" +} diff --git a/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidstop.txt b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidstop.txt new file mode 100644 index 00000000..e7471c0a --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidtracengnodesnodeidstop.txt @@ -0,0 +1,14 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/4952fc41-261a-43cc-8d6b-1f56af3e1593/stop' -d '{}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/4952fc41-261a-43cc-8d6b-1f56af3e1593/stop HTTP/1.1 +{} + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:48:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id}/stop + diff --git a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodes.txt b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodes.txt index db20360a..a126d2c6 100644 --- a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodes.txt +++ b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodes.txt @@ -10,14 +10,13 @@ POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes HTTP/1.1 201 Connection: close -Content-Length: 459 +Content-Length: 477 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:57 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes { - "acpi_shutdown": false, "adapter_type": "Intel PRO/1000 MT Desktop (82540EM)", "adapters": 0, "console": 5004, @@ -26,10 +25,12 @@ X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes "linked_clone": false, "name": "VM1", "node_directory": null, - "node_id": "dbbae445-fdee-4985-ab03-9fd20c4dd5c1", + "node_id": "8f1ecb93-c1c4-4b0b-a7ff-b81bf074b2ac", + "on_close": "power_off", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "ram": 0, "status": "stopped", + "usage": "", "use_any_adapter": false, "vmname": "VM1" } diff --git a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index e7270773..ea4b5c5c 100644 --- a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/acf82559-f05c-4623-8607-f4725c99dd19/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/19e8ab3c-6c40-4837-bfc4-062a6bb7b33e/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/acf82559-f05c-4623-8607-f4725c99dd19/adapters/0/ports/0/nio HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/19e8ab3c-6c40-4837-bfc4-062a6bb7b33e/adapters/0/ports/0/nio HTTP/1.1 { "lport": 4242, "rhost": "127.0.0.1", @@ -13,8 +13,8 @@ HTTP/1.1 201 Connection: close Content-Length: 89 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:58 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt new file mode 100644 index 00000000..5ef56262 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt @@ -0,0 +1,20 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/f3c03f37-91ef-4f52-bd7f-6cdf141ab5d1/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/f3c03f37-91ef-4f52-bd7f-6cdf141ab5d1/adapters/0/ports/0/start_capture HTTP/1.1 +{ + "capture_file_name": "test.pcap", + "data_link_type": "DLT_EN10MB" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 123 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture + +{ + "pcap_file_path": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/captures/test.pcap" +} diff --git a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt new file mode 100644 index 00000000..a5394b43 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt @@ -0,0 +1,14 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/e44348ff-8a7b-434d-bc2f-9356e08e7dda/adapters/0/ports/0/stop_capture' -d '{}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/e44348ff-8a7b-434d-bc2f-9356e08e7dda/adapters/0/ports/0/stop_capture HTTP/1.1 +{} + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:48:54 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture + diff --git a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidreload.txt b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidreload.txt index 9e91965d..389759e6 100644 --- a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidreload.txt +++ b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidreload.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/dec54572-148b-4d8a-b8e6-fed0f2f0e27a/reload' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/1db15c46-4b2e-4b2f-ae36-e3bbbb412234/reload' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/dec54572-148b-4d8a-b8e6-fed0f2f0e27a/reload HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/1db15c46-4b2e-4b2f-ae36-e3bbbb412234/reload HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:58 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/reload diff --git a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidresume.txt b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidresume.txt index c495f6bc..187bc450 100644 --- a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidresume.txt +++ b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidresume.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/890d1ef3-de36-4215-a3d2-2e7735238784/resume' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/04c5e242-3011-40df-aeb5-c75ac13f37e5/resume' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/890d1ef3-de36-4215-a3d2-2e7735238784/resume HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/04c5e242-3011-40df-aeb5-c75ac13f37e5/resume HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:58 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/resume diff --git a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidstart.txt b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidstart.txt index c924f306..476576bf 100644 --- a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidstart.txt +++ b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidstart.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/14876fc1-ed1f-45c6-9fe5-03c5c1de21be/start' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/4e67d9c1-a02f-4d91-88c9-69b58366b509/start' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/14876fc1-ed1f-45c6-9fe5-03c5c1de21be/start HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/4e67d9c1-a02f-4d91-88c9-69b58366b509/start HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:57 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/start diff --git a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidstop.txt b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidstop.txt index afeb5c18..993b359d 100644 --- a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidstop.txt +++ b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidstop.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/030a16df-bb45-476b-8b4a-ad82e6a03859/stop' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/58b02985-720b-4096-a5d6-a96529662849/stop' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/030a16df-bb45-476b-8b4a-ad82e6a03859/stop HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/58b02985-720b-4096-a5d6-a96529662849/stop HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:58 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/stop diff --git a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidsuspend.txt b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidsuspend.txt index a0bbe4de..9346cb88 100644 --- a/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidsuspend.txt +++ b/docs/api/examples/compute_post_projectsprojectidvirtualboxnodesnodeidsuspend.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/c3f25ab6-15b2-472f-b9c8-a3e9d2db521e/suspend' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/6a28f677-fd86-4a6e-8001-aadbf07130df/suspend' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/c3f25ab6-15b2-472f-b9c8-a3e9d2db521e/suspend HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/6a28f677-fd86-4a6e-8001-aadbf07130df/suspend HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:58 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/suspend diff --git a/docs/api/examples/compute_post_projectsprojectidvmwarenodes.txt b/docs/api/examples/compute_post_projectsprojectidvmwarenodes.txt index c6c3d72c..98bb5b07 100644 --- a/docs/api/examples/compute_post_projectsprojectidvmwarenodes.txt +++ b/docs/api/examples/compute_post_projectsprojectidvmwarenodes.txt @@ -1,23 +1,22 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes' -d '{"linked_clone": false, "name": "VM1", "vmx_path": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_vmware_create0/test.vmx"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes' -d '{"linked_clone": false, "name": "VM1", "vmx_path": "/tmp/pytest-of-grossmj/pytest-0/test_vmware_create0/test.vmx"}' POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes HTTP/1.1 { "linked_clone": false, "name": "VM1", - "vmx_path": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_vmware_create0/test.vmx" + "vmx_path": "/tmp/pytest-of-grossmj/pytest-0/test_vmware_create0/test.vmx" } HTTP/1.1 201 Connection: close -Content-Length: 688 +Content-Length: 610 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:58 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:54 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes { - "acpi_shutdown": false, "adapter_type": "e1000", "adapters": 0, "console": 5004, @@ -25,10 +24,12 @@ X-Route: /v2/compute/projects/{project_id}/vmware/nodes "headless": false, "linked_clone": false, "name": "VM1", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vmware/363338c7-451e-4f3d-a74a-5d7400b2325b", - "node_id": "363338c7-451e-4f3d-a74a-5d7400b2325b", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vmware/b8bfe749-bacf-4f45-8e05-6f9f3063f80b", + "node_id": "b8bfe749-bacf-4f45-8e05-6f9f3063f80b", + "on_close": "power_off", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "status": "stopped", + "usage": "", "use_any_adapter": false, - "vmx_path": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_vmware_create0/test.vmx" + "vmx_path": "/tmp/pytest-of-grossmj/pytest-0/test_vmware_create0/test.vmx" } diff --git a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt index a3e6933d..07e0d7b4 100644 --- a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/8bd601b4-b70c-455d-86a8-656a844523bf/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/17eb18bb-d3ee-441a-8c9f-6c8019cf6815/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/8bd601b4-b70c-455d-86a8-656a844523bf/adapters/0/ports/0/nio HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/17eb18bb-d3ee-441a-8c9f-6c8019cf6815/adapters/0/ports/0/nio HTTP/1.1 { "lport": 4242, "rhost": "127.0.0.1", @@ -13,8 +13,8 @@ HTTP/1.1 201 Connection: close Content-Length: 89 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:06 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:02 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt new file mode 100644 index 00000000..e98d22fe --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt @@ -0,0 +1,20 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/ccd87893-9cfd-41a3-a000-2a56a57505ba/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/ccd87893-9cfd-41a3-a000-2a56a57505ba/adapters/0/ports/0/start_capture HTTP/1.1 +{ + "capture_file_name": "test.pcap", + "data_link_type": "DLT_EN10MB" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 123 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:49:40 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture + +{ + "pcap_file_path": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/captures/test.pcap" +} diff --git a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt new file mode 100644 index 00000000..5f08d49c --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt @@ -0,0 +1,14 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/f8122b27-c179-46fe-8f1a-1c278ee6ea6d/adapters/0/ports/0/stop_capture' -d '{}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/f8122b27-c179-46fe-8f1a-1c278ee6ea6d/adapters/0/ports/0/stop_capture HTTP/1.1 +{} + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:49:41 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture + diff --git a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidreload.txt b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidreload.txt index 06974d43..6f065364 100644 --- a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidreload.txt +++ b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidreload.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/f29ee895-6312-4c95-813a-2194257925f3/reload' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/69c8b98c-6b82-4a11-86ef-b2da845bb444/reload' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/f29ee895-6312-4c95-813a-2194257925f3/reload HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/69c8b98c-6b82-4a11-86ef-b2da845bb444/reload HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:05 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:01 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/reload diff --git a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidresume.txt b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidresume.txt index 58e242fd..d0927468 100644 --- a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidresume.txt +++ b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidresume.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/5b5cf295-69cf-4c7f-8dbe-cd34d8a50b96/resume' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/3f23c59b-3cef-45ea-8a99-a09d39159bb7/resume' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/5b5cf295-69cf-4c7f-8dbe-cd34d8a50b96/resume HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/3f23c59b-3cef-45ea-8a99-a09d39159bb7/resume HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:04 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:59 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/resume diff --git a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidstart.txt b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidstart.txt index e901133f..c0906462 100644 --- a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidstart.txt +++ b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidstart.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/3284972b-259f-4c32-804c-f95253a2b272/start' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/7290cb18-a955-4955-90fe-28fcb69b592c/start' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/3284972b-259f-4c32-804c-f95253a2b272/start HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/7290cb18-a955-4955-90fe-28fcb69b592c/start HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:00 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:56 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/start diff --git a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidstop.txt b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidstop.txt index d9e0419f..fb724b52 100644 --- a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidstop.txt +++ b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidstop.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/5d67e87b-35c7-484b-924c-44934ade59b9/stop' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/a67c3019-b019-4234-9ee0-f87f42dd1ada/stop' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/5d67e87b-35c7-484b-924c-44934ade59b9/stop HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/a67c3019-b019-4234-9ee0-f87f42dd1ada/stop HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:01 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:57 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/stop diff --git a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidsuspend.txt b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidsuspend.txt index 3b954e10..5c04a21f 100644 --- a/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidsuspend.txt +++ b/docs/api/examples/compute_post_projectsprojectidvmwarenodesnodeidsuspend.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/020c5143-2385-4b7e-84ab-2fa6235d7d44/suspend' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/eef44d66-ddc4-4855-9469-bd7f2b63cce5/suspend' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/020c5143-2385-4b7e-84ab-2fa6235d7d44/suspend HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/eef44d66-ddc4-4855-9469-bd7f2b63cce5/suspend HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:02 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:58 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/suspend diff --git a/docs/api/examples/compute_post_projectsprojectidvpcsnodes.txt b/docs/api/examples/compute_post_projectsprojectidvpcsnodes.txt index 058daa67..f6872c7b 100644 --- a/docs/api/examples/compute_post_projectsprojectidvpcsnodes.txt +++ b/docs/api/examples/compute_post_projectsprojectidvpcsnodes.txt @@ -8,10 +8,10 @@ POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes HTTP/1 HTTP/1.1 201 Connection: close -Content-Length: 428 +Content-Length: 384 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:44 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes { @@ -19,8 +19,8 @@ X-Route: /v2/compute/projects/{project_id}/vpcs/nodes "console": 5004, "console_type": "telnet", "name": "PC TEST 1", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vpcs/de5b89af-2907-411f-bc88-d7aacc015763", - "node_id": "de5b89af-2907-411f-bc88-d7aacc015763", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vpcs/58c82c16-db5c-4fbe-bde8-a8747078b908", + "node_id": "58c82c16-db5c-4fbe-bde8-a8747078b908", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "status": "stopped" } diff --git a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 4584bfc2..a9db5ab4 100644 --- a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/eb360fb6-4941-4f14-9145-e7d64369bc3c/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/102684d6-d8b7-4903-8612-5f86674fda11/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/eb360fb6-4941-4f14-9145-e7d64369bc3c/adapters/0/ports/0/nio HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/102684d6-d8b7-4903-8612-5f86674fda11/adapters/0/ports/0/nio HTTP/1.1 { "lport": 4242, "rhost": "127.0.0.1", @@ -13,8 +13,8 @@ HTTP/1.1 201 Connection: close Content-Length: 89 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:44 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt new file mode 100644 index 00000000..b17e1c49 --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt @@ -0,0 +1,20 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/dac41de2-77f5-4c64-9be0-d2817459425e/adapters/0/ports/0/start_capture' -d '{"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/dac41de2-77f5-4c64-9be0-d2817459425e/adapters/0/ports/0/start_capture HTTP/1.1 +{ + "capture_file_name": "test.pcap", + "data_link_type": "DLT_EN10MB" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 123 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:49:45 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture + +{ + "pcap_file_path": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/captures/test.pcap" +} diff --git a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt new file mode 100644 index 00000000..8ba3f1ec --- /dev/null +++ b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt @@ -0,0 +1,14 @@ +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/ddbd27e0-604e-42a5-9f2d-9f553f2c1286/adapters/0/ports/0/stop_capture' -d '{}' + +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/ddbd27e0-604e-42a5-9f2d-9f553f2c1286/adapters/0/ports/0/stop_capture HTTP/1.1 +{} + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:49:45 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture + diff --git a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidduplicate.txt b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidduplicate.txt index a4342f3c..bb478a8c 100644 --- a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidduplicate.txt +++ b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidduplicate.txt @@ -1,8 +1,8 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/3cd0a1d7-b074-4bf6-8c33-626f97ad8559/duplicate' -d '{"destination_node_id": "79886fa2-4320-419e-9044-e445694394d6"}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/1fa028fc-c993-4880-a8dc-dc60e30b22a0/duplicate' -d '{"destination_node_id": "a96800d2-eb29-4ac2-8844-a7d85b937708"}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/3cd0a1d7-b074-4bf6-8c33-626f97ad8559/duplicate HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/1fa028fc-c993-4880-a8dc-dc60e30b22a0/duplicate HTTP/1.1 { - "destination_node_id": "79886fa2-4320-419e-9044-e445694394d6" + "destination_node_id": "a96800d2-eb29-4ac2-8844-a7d85b937708" } @@ -10,8 +10,8 @@ HTTP/1.1 201 Connection: close Content-Length: 4 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:45 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/duplicate true diff --git a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidreload.txt b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidreload.txt index 4b9f57d4..8fecfb58 100644 --- a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidreload.txt +++ b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidreload.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/aaa4c50f-2c60-40ca-971d-d86a4433de82/reload' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/80030155-05ee-40fd-bb9a-5242ce70a308/reload' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/aaa4c50f-2c60-40ca-971d-d86a4433de82/reload HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/80030155-05ee-40fd-bb9a-5242ce70a308/reload HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:44 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/reload diff --git a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidstart.txt b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidstart.txt index 60ae628f..113294a5 100644 --- a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidstart.txt +++ b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidstart.txt @@ -1,15 +1,15 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/9c0b927b-a48b-41c7-ad94-4006669f49f5/start' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/d7b70ff5-1ce4-47f4-9316-e82ff821bee2/start' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/9c0b927b-a48b-41c7-ad94-4006669f49f5/start HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/d7b70ff5-1ce4-47f4-9316-e82ff821bee2/start HTTP/1.1 {} HTTP/1.1 200 Connection: close -Content-Length: 428 +Content-Length: 384 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:44 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/start { @@ -17,8 +17,8 @@ X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/start "console": 5004, "console_type": "telnet", "name": "PC TEST 1", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vpcs/9c0b927b-a48b-41c7-ad94-4006669f49f5", - "node_id": "9c0b927b-a48b-41c7-ad94-4006669f49f5", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vpcs/d7b70ff5-1ce4-47f4-9316-e82ff821bee2", + "node_id": "d7b70ff5-1ce4-47f4-9316-e82ff821bee2", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "status": "stopped" } diff --git a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidstop.txt b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidstop.txt index 2c6e2e70..c931bb98 100644 --- a/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidstop.txt +++ b/docs/api/examples/compute_post_projectsprojectidvpcsnodesnodeidstop.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/92b13851-ebaf-4966-a013-e0e4514848b2/stop' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/f63cb8d6-176a-4b2f-baee-52da1132651e/stop' -d '{}' -POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/92b13851-ebaf-4966-a013-e0e4514848b2/stop HTTP/1.1 +POST /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/f63cb8d6-176a-4b2f-baee-52da1132651e/stop HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:44 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/stop diff --git a/docs/api/examples/compute_post_qemuimg.txt b/docs/api/examples/compute_post_qemuimg.txt index aabe42f9..2e548fd1 100644 --- a/docs/api/examples/compute_post_qemuimg.txt +++ b/docs/api/examples/compute_post_qemuimg.txt @@ -17,7 +17,7 @@ HTTP/1.1 201 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:15:57 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:47 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/qemu/img diff --git a/docs/api/examples/compute_put_projectsprojectid.txt b/docs/api/examples/compute_put_projectsprojectid.txt new file mode 100644 index 00000000..febfaca8 --- /dev/null +++ b/docs/api/examples/compute_put_projectsprojectid.txt @@ -0,0 +1,31 @@ +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/51010203-0405-0607-0809-0a0b0c0d0e0f' -d '{"variables": [{"name": "TEST1", "value": "VAL1"}]}' + +PUT /v2/compute/projects/51010203-0405-0607-0809-0a0b0c0d0e0f HTTP/1.1 +{ + "variables": [ + { + "name": "TEST1", + "value": "VAL1" + } + ] +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 183 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:47:59 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id} + +{ + "name": "test", + "project_id": "51010203-0405-0607-0809-0a0b0c0d0e0f", + "variables": [ + { + "name": "TEST1", + "value": "VAL1" + } + ] +} diff --git a/docs/api/examples/compute_put_projectsprojectidcloudnodesnodeid.txt b/docs/api/examples/compute_put_projectsprojectidcloudnodesnodeid.txt index adbee567..2315af5e 100644 --- a/docs/api/examples/compute_put_projectsprojectidcloudnodesnodeid.txt +++ b/docs/api/examples/compute_put_projectsprojectidcloudnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/f5393b54-aad6-4233-acfa-ab20d9cb0e43' -d '{"name": "test"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/56c14edf-c5d0-4855-a422-399bc310769f' -d '{"name": "test"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/f5393b54-aad6-4233-acfa-ab20d9cb0e43 HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/56c14edf-c5d0-4855-a422-399bc310769f HTTP/1.1 { "name": "test" } @@ -8,73 +8,95 @@ PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/f5393b HTTP/1.1 200 Connection: close -Content-Length: 1581 +Content-Length: 2077 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:46 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:38 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/cloud/nodes/{node_id} { "interfaces": [ { - "name": "bridge0", + "name": "docker0", "special": true, "type": "ethernet" }, { - "name": "en0", + "name": "lo", + "special": true, + "type": "ethernet" + }, + { + "name": "vboxnet0", + "special": true, + "type": "ethernet" + }, + { + "name": "vboxnet1", + "special": true, + "type": "ethernet" + }, + { + "name": "vboxnet2", + "special": true, + "type": "ethernet" + }, + { + "name": "virbr0", + "special": true, + "type": "ethernet" + }, + { + "name": "virbr0-nic", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet1", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet2", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet3", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet4", + "special": true, + "type": "ethernet" + }, + { + "name": "vmnet8", + "special": true, + "type": "ethernet" + }, + { + "name": "wlp58s0", "special": false, "type": "ethernet" - }, - { - "name": "en1", - "special": false, - "type": "ethernet" - }, - { - "name": "en2", - "special": false, - "type": "ethernet" - }, - { - "name": "fw0", - "special": true, - "type": "ethernet" - }, - { - "name": "lo0", - "special": true, - "type": "ethernet" - }, - { - "name": "p2p0", - "special": true, - "type": "ethernet" } ], "name": "test", - "node_directory": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/project-files/builtin/f5393b54-aad6-4233-acfa-ab20d9cb0e43", - "node_id": "f5393b54-aad6-4233-acfa-ab20d9cb0e43", + "node_directory": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/builtin/56c14edf-c5d0-4855-a422-399bc310769f", + "node_id": "56c14edf-c5d0-4855-a422-399bc310769f", "ports_mapping": [ { - "interface": "en0", - "name": "en0", + "interface": "wlp58s0", + "name": "wlp58s0", "port_number": 0, "type": "ethernet" - }, - { - "interface": "en1", - "name": "en1", - "port_number": 1, - "type": "ethernet" - }, - { - "interface": "en2", - "name": "en2", - "port_number": 2, - "type": "ethernet" } ], "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", + "remote_console_host": "", + "remote_console_http_path": "/", + "remote_console_port": 23, + "remote_console_type": "none", "status": "started" } diff --git a/docs/api/examples/compute_put_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_put_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 49cdcbc8..72fcd71b 100644 --- a/docs/api/examples/compute_put_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_put_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/02dbb665-8582-4d4f-ab65-59d371b6dd26/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/2392e233-53cb-461e-a497-00537f37c3cb/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/02dbb665-8582-4d4f-ab65-59d371b6dd26/adapters/0/ports/0/nio HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/cloud/nodes/2392e233-53cb-461e-a497-00537f37c3cb/adapters/0/ports/0/nio HTTP/1.1 { "filters": {}, "lport": 4242, @@ -14,8 +14,8 @@ HTTP/1.1 201 Connection: close Content-Length: 108 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:43 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:36 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_put_projectsprojectiddockernodesnodeid.txt b/docs/api/examples/compute_put_projectsprojectiddockernodesnodeid.txt index c811bdf0..f95d289c 100644 --- a/docs/api/examples/compute_put_projectsprojectiddockernodesnodeid.txt +++ b/docs/api/examples/compute_put_projectsprojectiddockernodesnodeid.txt @@ -1,9 +1,10 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/22396e9c-c6a0-4d55-82f0-fff20006a4a3' -d '{"console": 5006, "environment": "GNS3=1\nGNS4=0", "name": "test", "start_command": "yes"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/cbb090e6-5b5a-427c-b74e-25eff0d78b26' -d '{"console": 5006, "environment": "GNS3=1\nGNS4=0", "extra_hosts": "test:127.0.0.1", "name": "test", "start_command": "yes"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/22396e9c-c6a0-4d55-82f0-fff20006a4a3 HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/cbb090e6-5b5a-427c-b74e-25eff0d78b26 HTTP/1.1 { "console": 5006, "environment": "GNS3=1\nGNS4=0", + "extra_hosts": "test:127.0.0.1", "name": "test", "start_command": "yes" } @@ -11,10 +12,10 @@ PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/22396 HTTP/1.1 200 Connection: close -Content-Length: 653 +Content-Length: 655 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:46 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:39 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/docker/nodes/{node_id} { @@ -27,11 +28,13 @@ X-Route: /v2/compute/projects/{project_id}/docker/nodes/{node_id} "console_type": "telnet", "container_id": "8bd8153ea8f5", "environment": "GNS3=1\nGNS4=0", + "extra_hosts": "test:127.0.0.1", "image": "nginx:latest", "name": "test", - "node_directory": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/project-files/docker/22396e9c-c6a0-4d55-82f0-fff20006a4a3", - "node_id": "22396e9c-c6a0-4d55-82f0-fff20006a4a3", + "node_directory": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/docker/cbb090e6-5b5a-427c-b74e-25eff0d78b26", + "node_id": "cbb090e6-5b5a-427c-b74e-25eff0d78b26", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "start_command": "yes", - "status": "stopped" + "status": "stopped", + "usage": "" } diff --git a/docs/api/examples/compute_put_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_put_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 9ff834d9..9b714a07 100644 --- a/docs/api/examples/compute_put_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_put_projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/7536b21f-e0e1-4b0e-be34-b27c5bee5dc1/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/beb3ca05-9d30-4441-afc7-8880b8b5c714/adapters/0/ports/0/nio' -d '{"lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/7536b21f-e0e1-4b0e-be34-b27c5bee5dc1/adapters/0/ports/0/nio HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/docker/nodes/beb3ca05-9d30-4441-afc7-8880b8b5c714/adapters/0/ports/0/nio HTTP/1.1 { "lport": 4242, "rhost": "127.0.0.1", @@ -13,8 +13,8 @@ HTTP/1.1 201 Connection: close Content-Length: 89 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:46 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:39 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_put_projectsprojectidiounodesnodeid.txt b/docs/api/examples/compute_put_projectsprojectidiounodesnodeid.txt index ead7fafd..c226a9cb 100644 --- a/docs/api/examples/compute_put_projectsprojectidiounodesnodeid.txt +++ b/docs/api/examples/compute_put_projectsprojectidiounodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/2e54bfd5-33e4-4958-9eb5-9344095bcf3c' -d '{"console": 5005, "ethernet_adapters": 4, "l1_keepalives": true, "name": "test", "nvram": 2048, "ram": 512, "serial_adapters": 0, "use_default_iou_values": true}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/83f8d15d-1c9c-4b3c-8aec-10b6d0f3242e' -d '{"console": 5005, "ethernet_adapters": 4, "l1_keepalives": true, "name": "test", "nvram": 2048, "ram": 512, "serial_adapters": 0, "use_default_iou_values": true}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/2e54bfd5-33e4-4958-9eb5-9344095bcf3c HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/83f8d15d-1c9c-4b3c-8aec-10b6d0f3242e HTTP/1.1 { "console": 5005, "ethernet_adapters": 4, @@ -15,10 +15,10 @@ PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/2e54bfd5 HTTP/1.1 200 Connection: close -Content-Length: 660 +Content-Length: 625 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:48 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id} { @@ -30,13 +30,14 @@ X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id} "l1_keepalives": true, "md5sum": "e573e8f5c93c6c00783f20c7a170aa6c", "name": "test", - "node_directory": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_json4/project-files/iou/2e54bfd5-33e4-4958-9eb5-9344095bcf3c", - "node_id": "2e54bfd5-33e4-4958-9eb5-9344095bcf3c", + "node_directory": "/tmp/pytest-of-grossmj/pytest-0/test_json4/project-files/iou/83f8d15d-1c9c-4b3c-8aec-10b6d0f3242e", + "node_id": "83f8d15d-1c9c-4b3c-8aec-10b6d0f3242e", "nvram": 2048, "path": "iou.bin", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "ram": 512, "serial_adapters": 0, "status": "stopped", + "usage": "", "use_default_iou_values": true } diff --git a/docs/api/examples/compute_put_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_put_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 1a00d6ca..d4c42b25 100644 --- a/docs/api/examples/compute_put_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_put_projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/7e50dc2a-4a1e-44b7-8d5a-6b7de6f4ff07/adapters/1/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/7d79a73d-5060-4c75-ae83-45322b1547f3/adapters/1/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/7e50dc2a-4a1e-44b7-8d5a-6b7de6f4ff07/adapters/1/ports/0/nio HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/7d79a73d-5060-4c75-ae83-45322b1547f3/adapters/1/ports/0/nio HTTP/1.1 { "filters": {}, "lport": 4242, @@ -12,13 +12,14 @@ PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/iou/nodes/7e50dc2a HTTP/1.1 201 Connection: close -Content-Length: 89 +Content-Length: 108 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:48 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { + "filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, diff --git a/docs/api/examples/compute_put_projectsprojectidnatnodesnodeid.txt b/docs/api/examples/compute_put_projectsprojectidnatnodesnodeid.txt index a49acf6d..3aa4e055 100644 --- a/docs/api/examples/compute_put_projectsprojectidnatnodesnodeid.txt +++ b/docs/api/examples/compute_put_projectsprojectidnatnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/c567edc8-9230-41b5-a32c-cda1403eb187' -d '{"name": "test"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/7a7ec28f-76c9-49f8-bbdd-e77e99c16450' -d '{"name": "test"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/c567edc8-9230-41b5-a32c-cda1403eb187 HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/7a7ec28f-76c9-49f8-bbdd-e77e99c16450 HTTP/1.1 { "name": "test" } @@ -10,13 +10,13 @@ HTTP/1.1 200 Connection: close Content-Length: 334 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:54 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:57 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/nat/nodes/{node_id} { "name": "test", - "node_id": "c567edc8-9230-41b5-a32c-cda1403eb187", + "node_id": "7a7ec28f-76c9-49f8-bbdd-e77e99c16450", "ports_mapping": [ { "interface": "virbr0", diff --git a/docs/api/examples/compute_put_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_put_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index bbfbb4b8..1d557c3b 100644 --- a/docs/api/examples/compute_put_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_put_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/e44156c3-1ac8-4af3-81a1-049b7c441054/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/e527e297-3cc1-4d0a-82ad-cacfabf8eb56/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/e44156c3-1ac8-4af3-81a1-049b7c441054/adapters/0/ports/0/nio HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/nat/nodes/e527e297-3cc1-4d0a-82ad-cacfabf8eb56/adapters/0/ports/0/nio HTTP/1.1 { "filters": {}, "lport": 4242, @@ -14,8 +14,8 @@ HTTP/1.1 201 Connection: close Content-Length: 108 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:49 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:47:56 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_put_projectsprojectidqemunodesnodeid.txt b/docs/api/examples/compute_put_projectsprojectidqemunodesnodeid.txt index 06c76a3c..a4fb14ab 100644 --- a/docs/api/examples/compute_put_projectsprojectidqemunodesnodeid.txt +++ b/docs/api/examples/compute_put_projectsprojectidqemunodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/2b036990-caf0-422c-b18b-5b218bbe4504' -d '{"console": 5006, "hdb_disk_image": "linux\u8f7d.img", "name": "test", "ram": 1024}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/81fead0a-f831-4116-a6fa-cfa42819561c' -d '{"console": 5006, "hdb_disk_image": "linux\u8f7d.img", "name": "test", "ram": 1024}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/2b036990-caf0-422c-b18b-5b218bbe4504 HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/81fead0a-f831-4116-a6fa-cfa42819561c HTTP/1.1 { "console": 5006, "hdb_disk_image": "linux\u8f7d.img", @@ -11,14 +11,13 @@ PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/2b03699 HTTP/1.1 200 Connection: close -Content-Length: 1509 +Content-Length: 1422 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:38 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id} { - "acpi_shutdown": false, "adapter_type": "e1000", "adapters": 1, "bios_image": "", @@ -49,15 +48,16 @@ X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id} "kernel_image": "", "kernel_image_md5sum": null, "legacy_networking": false, - "mac_address": "00:dd:80:45:04:00", + "mac_address": "0c:dd:80:56:1c:00", "name": "test", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/qemu/2b036990-caf0-422c-b18b-5b218bbe4504", - "node_id": "2b036990-caf0-422c-b18b-5b218bbe4504", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/qemu/81fead0a-f831-4116-a6fa-cfa42819561c", + "node_id": "81fead0a-f831-4116-a6fa-cfa42819561c", + "on_close": "power_off", "options": "", "platform": "x86_64", "process_priority": "low", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", - "qemu_path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp26lo7e4o/qemu-system-x86_64", + "qemu_path": "/tmp/tmpjg3j58ga/qemu-system-x86_64", "ram": 1024, "status": "stopped", "usage": "" diff --git a/docs/api/examples/compute_put_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_put_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt index e6e107ba..a369bb24 100644 --- a/docs/api/examples/compute_put_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_put_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/b299b291-ca8d-4d12-b12a-2eab780a7a0a/adapters/1/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/623626b9-36e3-446b-a0b2-45f9acc6b71c/adapters/1/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/b299b291-ca8d-4d12-b12a-2eab780a7a0a/adapters/1/ports/0/nio HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/qemu/nodes/623626b9-36e3-446b-a0b2-45f9acc6b71c/adapters/1/ports/0/nio HTTP/1.1 { "filters": {}, "lport": 4242, @@ -14,8 +14,8 @@ HTTP/1.1 201 Connection: close Content-Length: 108 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:56 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:40 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_put_projectsprojectidtracengnodesnodeid.txt b/docs/api/examples/compute_put_projectsprojectidtracengnodesnodeid.txt new file mode 100644 index 00000000..d8a2f0db --- /dev/null +++ b/docs/api/examples/compute_put_projectsprojectidtracengnodesnodeid.txt @@ -0,0 +1,29 @@ +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/92c444a3-9022-4a38-bc22-b8f122ca7342' -d '{"ip_address": "192.168.1.1", "name": "test"}' + +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/92c444a3-9022-4a38-bc22-b8f122ca7342 HTTP/1.1 +{ + "ip_address": "192.168.1.1", + "name": "test" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 444 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id} + +{ + "command_line": "", + "console": null, + "console_type": "none", + "default_destination": "", + "ip_address": "192.168.1.1", + "name": "test", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/traceng/92c444a3-9022-4a38-bc22-b8f122ca7342", + "node_id": "92c444a3-9022-4a38-bc22-b8f122ca7342", + "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", + "status": "stopped" +} diff --git a/docs/api/examples/compute_put_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_put_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt new file mode 100644 index 00000000..e5f626bc --- /dev/null +++ b/docs/api/examples/compute_put_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -0,0 +1,27 @@ +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/457ed2f5-534b-4fc3-97c4-823fed6fa0b0/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' + +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/traceng/nodes/457ed2f5-534b-4fc3-97c4-823fed6fa0b0/adapters/0/ports/0/nio HTTP/1.1 +{ + "filters": {}, + "lport": 4242, + "rhost": "127.0.0.1", + "rport": 4343, + "type": "nio_udp" +} + + +HTTP/1.1 201 +Connection: close +Content-Length: 108 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:48:50 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/compute/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio + +{ + "filters": {}, + "lport": 4242, + "rhost": "127.0.0.1", + "rport": 4343, + "type": "nio_udp" +} diff --git a/docs/api/examples/compute_put_projectsprojectidvirtualboxnodesnodeid.txt b/docs/api/examples/compute_put_projectsprojectidvirtualboxnodesnodeid.txt index d406ff89..9edffd49 100644 --- a/docs/api/examples/compute_put_projectsprojectidvirtualboxnodesnodeid.txt +++ b/docs/api/examples/compute_put_projectsprojectidvirtualboxnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/07ae8a79-9a4c-4987-8fc9-e5c3c2ca541d' -d '{"console": 5005, "name": "test"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/290969e8-5a29-4c6f-8a5c-a683d5dbbe8a' -d '{"console": 5005, "name": "test"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/07ae8a79-9a4c-4987-8fc9-e5c3c2ca541d HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/290969e8-5a29-4c6f-8a5c-a683d5dbbe8a HTTP/1.1 { "console": 5005, "name": "test" @@ -9,14 +9,13 @@ PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/0 HTTP/1.1 200 Connection: close -Content-Length: 463 +Content-Length: 481 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:58 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id} { - "acpi_shutdown": false, "adapter_type": "Intel PRO/1000 MT Desktop (82540EM)", "adapters": 0, "console": 5005, @@ -25,10 +24,12 @@ X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id} "linked_clone": false, "name": "test", "node_directory": null, - "node_id": "07ae8a79-9a4c-4987-8fc9-e5c3c2ca541d", + "node_id": "290969e8-5a29-4c6f-8a5c-a683d5dbbe8a", + "on_close": "power_off", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "ram": 0, "status": "stopped", + "usage": "", "use_any_adapter": false, "vmname": "VMTEST" } diff --git a/docs/api/examples/compute_put_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_put_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 4b279b92..e8733cea 100644 --- a/docs/api/examples/compute_put_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_put_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/0676cad3-3893-4a88-9535-f4a248723907/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/e75046cc-bd06-473d-b1d6-efb999a516af/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/0676cad3-3893-4a88-9535-f4a248723907/adapters/0/ports/0/nio HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/virtualbox/nodes/e75046cc-bd06-473d-b1d6-efb999a516af/adapters/0/ports/0/nio HTTP/1.1 { "filters": {}, "lport": 4242, @@ -14,8 +14,8 @@ HTTP/1.1 201 Connection: close Content-Length: 108 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:15:58 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:48:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_put_projectsprojectidvmwarenodesnodeid.txt b/docs/api/examples/compute_put_projectsprojectidvmwarenodesnodeid.txt index eba662d7..370b5668 100644 --- a/docs/api/examples/compute_put_projectsprojectidvmwarenodesnodeid.txt +++ b/docs/api/examples/compute_put_projectsprojectidvmwarenodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/0984c2d0-0a0c-4b46-ba69-16bd5c0464fe' -d '{"console": 5005, "name": "test"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/01e4a958-04bd-4431-a924-af4ae2b77e8a' -d '{"console": 5005, "name": "test"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/0984c2d0-0a0c-4b46-ba69-16bd5c0464fe HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/01e4a958-04bd-4431-a924-af4ae2b77e8a HTTP/1.1 { "console": 5005, "name": "test" @@ -9,14 +9,13 @@ PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/0984c HTTP/1.1 200 Connection: close -Content-Length: 689 +Content-Length: 611 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:10 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:07 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id} { - "acpi_shutdown": false, "adapter_type": "e1000", "adapters": 0, "console": 5005, @@ -24,10 +23,12 @@ X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id} "headless": false, "linked_clone": false, "name": "test", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vmware/0984c2d0-0a0c-4b46-ba69-16bd5c0464fe", - "node_id": "0984c2d0-0a0c-4b46-ba69-16bd5c0464fe", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vmware/01e4a958-04bd-4431-a924-af4ae2b77e8a", + "node_id": "01e4a958-04bd-4431-a924-af4ae2b77e8a", + "on_close": "power_off", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "status": "stopped", + "usage": "", "use_any_adapter": false, - "vmx_path": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_vmware_update0/test.vmx" + "vmx_path": "/tmp/pytest-of-grossmj/pytest-0/test_vmware_update0/test.vmx" } diff --git a/docs/api/examples/compute_put_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_put_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 1015be6a..396936db 100644 --- a/docs/api/examples/compute_put_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_put_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/7334e124-eace-47e6-982b-ef6ce9382a7b/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/a01c18c6-0723-4781-b5be-7dd08689272d/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/7334e124-eace-47e6-982b-ef6ce9382a7b/adapters/0/ports/0/nio HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vmware/nodes/a01c18c6-0723-4781-b5be-7dd08689272d/adapters/0/ports/0/nio HTTP/1.1 { "filters": {}, "lport": 4242, @@ -14,8 +14,8 @@ HTTP/1.1 201 Connection: close Content-Length: 108 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:07 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:04 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/compute_put_projectsprojectidvpcsnodesnodeid.txt b/docs/api/examples/compute_put_projectsprojectidvpcsnodesnodeid.txt index a9caee6f..0c854acb 100644 --- a/docs/api/examples/compute_put_projectsprojectidvpcsnodesnodeid.txt +++ b/docs/api/examples/compute_put_projectsprojectidvpcsnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/892a8c7f-fd53-4721-a1f8-5fde82beb037' -d '{"console": 5006, "name": "test"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/8d487854-a7df-4f7e-8f5a-90a829830974' -d '{"console": 5006, "name": "test"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/892a8c7f-fd53-4721-a1f8-5fde82beb037 HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/8d487854-a7df-4f7e-8f5a-90a829830974 HTTP/1.1 { "console": 5006, "name": "test" @@ -9,10 +9,10 @@ PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/892a8c7 HTTP/1.1 200 Connection: close -Content-Length: 423 +Content-Length: 379 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:45 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id} { @@ -20,8 +20,8 @@ X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id} "console": 5006, "console_type": "telnet", "name": "test", - "node_directory": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpk__by17a/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vpcs/892a8c7f-fd53-4721-a1f8-5fde82beb037", - "node_id": "892a8c7f-fd53-4721-a1f8-5fde82beb037", + "node_directory": "/tmp/tmp2a2tb7g2/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/project-files/vpcs/8d487854-a7df-4f7e-8f5a-90a829830974", + "node_id": "8d487854-a7df-4f7e-8f5a-90a829830974", "project_id": "a1e920ca-338a-4e9f-b363-aa607b09dd80", "status": "stopped" } diff --git a/docs/api/examples/compute_put_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt b/docs/api/examples/compute_put_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt index 2910325e..0c0d19d4 100644 --- a/docs/api/examples/compute_put_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt +++ b/docs/api/examples/compute_put_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/fa95d435-5dc4-4e82-b8a5-7977de2daae6/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' +curl -i -X PUT 'http://localhost:3080/v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/f443ec09-14f8-4587-bb54-abb5cf142097/adapters/0/ports/0/nio' -d '{"filters": {}, "lport": 4242, "rhost": "127.0.0.1", "rport": 4343, "type": "nio_udp"}' -PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/fa95d435-5dc4-4e82-b8a5-7977de2daae6/adapters/0/ports/0/nio HTTP/1.1 +PUT /v2/compute/projects/a1e920ca-338a-4e9f-b363-aa607b09dd80/vpcs/nodes/f443ec09-14f8-4587-bb54-abb5cf142097/adapters/0/ports/0/nio HTTP/1.1 { "filters": {}, "lport": 4242, @@ -14,8 +14,8 @@ HTTP/1.1 201 Connection: close Content-Length: 108 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:11 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:44 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio { diff --git a/docs/api/examples/controller_delete_computescomputeid.txt b/docs/api/examples/controller_delete_computescomputeid.txt index 9a296e44..9000f52f 100644 --- a/docs/api/examples/controller_delete_computescomputeid.txt +++ b/docs/api/examples/controller_delete_computescomputeid.txt @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:24 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:47 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/computes/{compute_id} diff --git a/docs/api/examples/controller_delete_projectsprojectid.txt b/docs/api/examples/controller_delete_projectsprojectid.txt index 5e3f48e5..ae2d3600 100644 --- a/docs/api/examples/controller_delete_projectsprojectid.txt +++ b/docs/api/examples/controller_delete_projectsprojectid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/projects/5b7149f0-17dd-48f0-a908-99dd4b4de0d4' +curl -i -X DELETE 'http://localhost:3080/v2/projects/015cc0ed-b38b-4fab-a639-5469dfe1de95' -DELETE /v2/projects/5b7149f0-17dd-48f0-a908-99dd4b4de0d4 HTTP/1.1 +DELETE /v2/projects/015cc0ed-b38b-4fab-a639-5469dfe1de95 HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:38 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:00 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id} diff --git a/docs/api/examples/controller_delete_projectsprojectiddrawingsdrawingid.txt b/docs/api/examples/controller_delete_projectsprojectiddrawingsdrawingid.txt index 5c232cf7..0177906e 100644 --- a/docs/api/examples/controller_delete_projectsprojectiddrawingsdrawingid.txt +++ b/docs/api/examples/controller_delete_projectsprojectiddrawingsdrawingid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/projects/3cf20b3c-0602-49a6-b593-d49b6a1a5238/drawings/df4f6a0a-429a-40c9-ae38-dbb4733d0750' +curl -i -X DELETE 'http://localhost:3080/v2/projects/d355abec-d468-4730-8540-291c1745e44c/drawings/a9c5b7b1-e286-4c54-ba54-cdc5f127f0cc' -DELETE /v2/projects/3cf20b3c-0602-49a6-b593-d49b6a1a5238/drawings/df4f6a0a-429a-40c9-ae38-dbb4733d0750 HTTP/1.1 +DELETE /v2/projects/d355abec-d468-4730-8540-291c1745e44c/drawings/a9c5b7b1-e286-4c54-ba54-cdc5f127f0cc HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/drawings/{drawing_id} diff --git a/docs/api/examples/controller_delete_projectsprojectidlinkslinkid.txt b/docs/api/examples/controller_delete_projectsprojectidlinkslinkid.txt index 00b9e571..c6c852ce 100644 --- a/docs/api/examples/controller_delete_projectsprojectidlinkslinkid.txt +++ b/docs/api/examples/controller_delete_projectsprojectidlinkslinkid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/projects/2883d355-8b23-4ddd-a21b-ff213e485c29/links/3b6257c1-ce3b-44c8-8c6c-a0457d6e9e04' +curl -i -X DELETE 'http://localhost:3080/v2/projects/5b0d6522-946f-4e88-b4cc-055812007d17/links/56ee24d1-9e61-4239-a9fb-d0496c021c91' -DELETE /v2/projects/2883d355-8b23-4ddd-a21b-ff213e485c29/links/3b6257c1-ce3b-44c8-8c6c-a0457d6e9e04 HTTP/1.1 +DELETE /v2/projects/5b0d6522-946f-4e88-b4cc-055812007d17/links/56ee24d1-9e61-4239-a9fb-d0496c021c91 HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:36 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/links/{link_id} diff --git a/docs/api/examples/controller_delete_projectsprojectidnodesnodeid.txt b/docs/api/examples/controller_delete_projectsprojectidnodesnodeid.txt index 5b0c9f70..2f826b91 100644 --- a/docs/api/examples/controller_delete_projectsprojectidnodesnodeid.txt +++ b/docs/api/examples/controller_delete_projectsprojectidnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/projects/86bbdba1-356e-4abf-94af-42c002782a60/nodes/f22f2164-5f3f-4dd8-b88b-cca9e32f4f5c' +curl -i -X DELETE 'http://localhost:3080/v2/projects/b741e18e-e007-4adc-bc4e-b9210f1760bf/nodes/1525cc56-03aa-48fa-accc-b22f855ea868' -DELETE /v2/projects/86bbdba1-356e-4abf-94af-42c002782a60/nodes/f22f2164-5f3f-4dd8-b88b-cca9e32f4f5c HTTP/1.1 +DELETE /v2/projects/b741e18e-e007-4adc-bc4e-b9210f1760bf/nodes/1525cc56-03aa-48fa-accc-b22f855ea868 HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:38 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:56 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id} diff --git a/docs/api/examples/controller_delete_projectsprojectidsnapshotssnapshotid.txt b/docs/api/examples/controller_delete_projectsprojectidsnapshotssnapshotid.txt index 71686b4d..a80ac500 100644 --- a/docs/api/examples/controller_delete_projectsprojectidsnapshotssnapshotid.txt +++ b/docs/api/examples/controller_delete_projectsprojectidsnapshotssnapshotid.txt @@ -1,6 +1,6 @@ -curl -i -X DELETE 'http://localhost:3080/v2/projects/0b8da5eb-a8e3-47a7-b74a-b8440087ad20/snapshots/47c9b602-6e34-4190-94f9-6e7bd7d18c2d' +curl -i -X DELETE 'http://localhost:3080/v2/projects/930a588e-b58a-4424-9aa4-d0265f2f82df/snapshots/bacb46af-507e-462e-9833-4d278bac7925' -DELETE /v2/projects/0b8da5eb-a8e3-47a7-b74a-b8440087ad20/snapshots/47c9b602-6e34-4190-94f9-6e7bd7d18c2d HTTP/1.1 +DELETE /v2/projects/930a588e-b58a-4424-9aa4-d0265f2f82df/snapshots/bacb46af-507e-462e-9833-4d278bac7925 HTTP/1.1 @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:40 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:09 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/snapshots/{snapshot_id} diff --git a/docs/api/examples/controller_delete_templatestemplateid.txt b/docs/api/examples/controller_delete_templatestemplateid.txt new file mode 100644 index 00000000..a991e1dc --- /dev/null +++ b/docs/api/examples/controller_delete_templatestemplateid.txt @@ -0,0 +1,14 @@ +curl -i -X DELETE 'http://localhost:3080/v2/templates/34671a00-c069-4631-8007-7f73aa462d7f' + +DELETE /v2/templates/34671a00-c069-4631-8007-7f73aa462d7f HTTP/1.1 + + + +HTTP/1.1 204 +Connection: close +Content-Length: 0 +Content-Type: application/octet-stream +Date: Sat, 30 Mar 2019 08:50:14 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/templates/{template_id} + diff --git a/docs/api/examples/controller_get_appliances.txt b/docs/api/examples/controller_get_appliances.txt index dcb385ca..4b0fb0ce 100644 --- a/docs/api/examples/controller_get_appliances.txt +++ b/docs/api/examples/controller_get_appliances.txt @@ -6,99 +6,14218 @@ GET /v2/appliances HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 2694 +Content-Length: 632570 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:12 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:45 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/appliances [ { - "appliance_id": "39e257dc-8412-3174-b6b3-0ee3ed6a43e9", "builtin": true, - "category": "guest", - "compute_id": null, - "default_name_format": "{name}-{0}", - "name": "Cloud", - "node_type": "cloud", - "platform": null, - "symbol": ":/symbols/cloud.svg" - }, - { - "appliance_id": "df8f4ea9-33b7-3e96-86a2-c39bc9bb649c", - "builtin": true, - "category": "guest", - "compute_id": null, - "default_name_format": "{name}-{0}", - "name": "NAT", - "node_type": "nat", - "platform": null, - "symbol": ":/symbols/cloud.svg" - }, - { - "appliance_id": "19021f99-e36f-394d-b4a1-8aaa902ab9cc", - "builtin": true, - "category": "guest", - "compute_id": null, - "default_name_format": "{name}-{0}", - "name": "VPCS", - "node_type": "vpcs", - "platform": null, - "symbol": ":/symbols/vpcs_guest.svg" - }, - { - "appliance_id": "1966b864-93e7-32d5-965f-001384eec461", - "builtin": true, - "category": "switch", - "compute_id": null, - "default_name_format": "{name}-{0}", - "name": "Ethernet switch", - "node_type": "ethernet_switch", - "platform": null, - "symbol": ":/symbols/ethernet_switch.svg" - }, - { - "appliance_id": "b4503ea9-d6b6-3695-9fe4-1db3b39290b0", - "builtin": true, - "category": "switch", - "compute_id": null, - "default_name_format": "{name}-{0}", - "name": "Ethernet hub", - "node_type": "ethernet_hub", - "platform": null, - "symbol": ":/symbols/hub.svg" - }, - { - "appliance_id": "dd0f6f3a-ba58-3249-81cb-a1dd88407a47", - "builtin": true, - "category": "switch", - "compute_id": null, - "default_name_format": "{name}-{0}", - "name": "Frame Relay switch", - "node_type": "frame_relay_switch", - "platform": null, - "symbol": ":/symbols/frame_relay_switch.svg" - }, - { - "appliance_id": "aaa764e2-b383-300f-8a0e-3493bbfdb7d2", - "builtin": true, - "category": "switch", - "compute_id": null, - "default_name_format": "{name}-{0}", - "name": "ATM switch", - "node_type": "atm_switch", - "platform": null, - "symbol": ":/symbols/atm_switch.svg" - }, - { - "appliance_id": "dd7ae518-30e9-48fd-b6de-bc9a69720c00", - "builtin": false, "category": "router", - "compute_id": "local", - "default_name_format": "{name}-{0}", - "name": "test", - "node_type": "qemu", - "platform": null, - "symbol": "guest.svg" + "description": "The HPE VSR1000 Virtual Services Router Series is a software application, running on a server, which provides functionality similar to that of a physical router: robust routing between networked devices using a number of popular routing protocols. It also delivers the critical network services associated with today's enterprise routers such as VPN gateway, firewall and other security and traffic management functions.\n\nThe virtual services router (VSR) application runs on a hypervqcor on the server, and supports VMware vSphere and Linux KVM hypervqcors. From one to eight virtual CPUs are supported, depending on license.\n\nBecause the VSR1000 Series application runs the same HPE Comware version 7 operating system as HPE switches and routers, it enables significant operational savings. And being virtual, additional agility and ease of deployment is realized, as resources on the VSR can be dynamically allocated and upgraded upon demand as performance requirements grow.\n\nA variety of deployment models are supported including enterprise branch CPE routing, and cloud offload for small to medium workloads.", + "documentation_url": "https://support.hpe.com/hpesc/public/home/documentHome?document_type=135&sp4ts.oid=5195141", + "images": [ + { + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=23726&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", + "filename": "VSR1000_HPE-CMW710-E0519L03-X64.qco", + "filesize": 202047488, + "md5sum": "83e23d27e7c3ef7ce813e6aad31d74f7", + "version": "7.10.E0519L03" + }, + { + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=22702&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", + "filename": "VSR1000_HPE-CMW710-R0327L01-X64.qco", + "filesize": 138739712, + "md5sum": "907de5140a4a029afe1c517cfc27ecde", + "version": "7.10.R0327L01" + }, + { + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=21985&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", + "filename": "VSR1000_HPE-CMW710-R0326-X64.qco", + "filesize": 138412032, + "md5sum": "4153d638bfa72ca72a957ea8682ad0e2", + "version": "7.10.R0326" + }, + { + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=20278&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", + "filename": "VSR1000_HPE-CMW710-E0325-X64.qco", + "filesize": 111738880, + "md5sum": "a6731f3af86bee9b209a8b342be6bf75", + "version": "7.10.E0325" + }, + { + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=21929&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", + "filename": "VSR1000_HPE-CMW710-E0518-X64.qco", + "filesize": 201588736, + "md5sum": "4991436442ae706df8041c69778a48df", + "version": "7.10.E0518" + }, + { + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=18977&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", + "filename": "VSR1000_HPE-CMW710-E0324-X64.qco", + "filesize": 111411200, + "md5sum": "7a0ff32281284c042591c6181426effd", + "version": "7.10.E0324" + }, + { + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=18976&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", + "filename": "VSR1000_HPE-CMW710-E0322P01-X64.qco", + "filesize": 110428160, + "md5sum": "0aa2dbe5910fa64eb8c623e083b21a5e", + "version": "7.10.E0322P01" + }, + { + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=18975&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", + "filename": "VSR1000_HPE-CMW710-E0322-X64.qco", + "filesize": 113770496, + "md5sum": "05e0dab6b7aa489f627448b4d79b1f50", + "version": "7.10.E0322" + }, + { + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=16838&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", + "filename": "VSR1000_HPE-CMW710-E0321P01-X64.qco", + "filesize": 113639424, + "md5sum": "26d4375fafeedc81f298f29f593de252", + "version": "7.10.E0321P01" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "HPE VSR1001", + "port_name_format": "GE{port1}/0", + "product_name": "VSR1001", + "product_url": "https://www.hpe.com/us/en/product-catalog/networking/networking-routers/pip.hpe-flexnetwork-vsr1000-virtual-services-router-series.5443163.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 16, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "options": "-machine type=pc-1.0", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "HPE", + "vendor_url": "http://www.hpe.com", + "versions": [ + { + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-E0519L03-X64.qco" + }, + "name": "7.10.E0519L03" + }, + { + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-R0327L01-X64.qco" + }, + "name": "7.10.R0327L01" + }, + { + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-R0326-X64.qco" + }, + "name": "7.10.R0326" + }, + { + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-E0325-X64.qco" + }, + "name": "7.10.E0325" + }, + { + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-E0518-X64.qco" + }, + "name": "7.10.E0518" + }, + { + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-E0324-X64.qco" + }, + "name": "7.10.E0324" + }, + { + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-E0322P01-X64.qco" + }, + "name": "7.10.E0322P01" + }, + { + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-E0322-X64.qco" + }, + "name": "7.10.E0322" + }, + { + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-E0321P01-X64.qco" + }, + "name": "7.10.E0321P01" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox.", + "docker": { + "adapters": 1, + "console_type": "telnet", + "image": "alpine" + }, + "documentation_url": "http://wiki.alpinelinux.org", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Alpine Linux", + "product_name": "Alpine Linux", + "registry_version": 3, + "status": "stable", + "symbol": "linux_guest.svg", + "vendor_name": "Alpine Linux Development Team", + "vendor_url": "http://alpinelinux.org" + }, + { + "builtin": true, + "category": "router", + "description": "Cisco 3725 Router", + "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", + "dynamips": { + "nvram": 256, + "platform": "c3725", + "ram": 128, + "slot0": "GT96100-FE", + "startup_config": "ios_base_startup-config.txt" + }, + "images": [ + { + "filename": "c3725-adventerprisek9-mz.124-15.T14.image", + "filesize": 97859480, + "md5sum": "64f8c427ed48fd21bd02cf1ff254c4eb", + "version": "124-25.T14" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco 3725", + "product_name": "3725", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "idlepc": "0x60c09aa0", + "images": { + "image": "c3725-adventerprisek9-mz.124-15.T14.image" + }, + "name": "124-25.T14" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "To ensure efficient email communication and business continuity, IT professionals depend on reliable spam and virus blocking software. With Proxmox Mail Gateway you get the job done.\n\nProxmox Mail Gateway helps you protect your business against all email threats like spam, viruses, phishing and trojans at the moment they emerge. The flexible architecture combined with the userfriendly, web-based management make it simple for you to control all incoming and outgoing emails. You maintain a professional email workflow and gain high business reputation as well as customer satisfaction.", + "documentation_url": "http://www.proxmox.com/en/downloads/category/documentation-pmg", + "images": [ + { + "direct_download_url": "https://www.proxmox.com/en/downloads?task=callelement&format=raw&item_id=415&element=f85c494b-2b32-4109-b8c1-083cca2b7db6&method=download&args[0]=7348486df9daacc8bd891a1d7ef1e5cb", + "download_url": "http://www.proxmox.com/en/downloads", + "filename": "proxmox-mailgateway_5.1-1.iso", + "filesize": 724660224, + "md5sum": "e629d5ff3213ff3ffbe5a8ab8ef87489", + "version": "5.1-1" + }, + { + "direct_download_url": "http://www.proxmox.com/en/downloads?task=callelement&format=raw&item_id=201&element=f85c494b-2b32-4109-b8c1-083cca2b7db6&method=download&args[0]=1f39333ff32bef6001584670e439c842", + "download_url": "http://www.proxmox.com/en/downloads", + "filename": "proxmox-mailgateway_4.1-5.iso", + "filesize": 746586112, + "md5sum": "f0b90f525b6f0fd51889ee48e44980b7", + "version": "4.1-5" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Proxmox MG", + "port_name_format": "eth{0}", + "product_name": "Proxmox MG", + "product_url": "http://www.proxmox.com/en/proxmox-mail-gateway", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 3, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 4096 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "User: root\nPassword: admin", + "vendor_name": "Proxmox Server Solutions GmbH", + "vendor_url": "http://www.proxmox.com/en/", + "versions": [ + { + "images": { + "cdrom_image": "proxmox-mailgateway_5.1-1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "5.1-1" + }, + { + "images": { + "cdrom_image": "proxmox-mailgateway_4.1-5.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "4.1-5" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Cisco Stealthwatch is the most comprehensive visibility and network traffic security analytics solution that uses enterprise telemetry from the existing network infrastructure. It provides advanced threat detection, accelerated threat response, and simplified network segmentation using multilayer machine learning and entity modeling. With advanced behavioral analytics, you\u2019ll always know who is on your network and what they are doing.\n\nAs the control center for the Stealthwatch System, the SMC manages, coordinates, configures, and organizes all of the different components of the system. The SMC client software allows you to access the SMC\u2019s user-friendly graphical user interface from any local computer with access to a Web browser. Through the client interface, you can easily access real-time security and network information about critical segments throughout your enterprise. ", + "documentation_url": "https://www.cisco.com/c/en/us/support/security/stealthwatch/tsd-products-support-series-home.html", + "first_port_name": "eth0", + "images": [ + { + "download_url": "https://stealthwatch.flexnetoperations.com/control/lncp/product?child_plneID=786407", + "filename": "SMC-6.10.4-2018.11.14.1757-0.iso", + "filesize": 2518747136, + "md5sum": "1de82eddf5303012aa8701144a7d4c7b", + "version": "6.10.4-2018.11.14.1757-0" + }, + { + "download_url": "https://software.cisco.com/download/home/286307342/type/286307754/release/6.10.2", + "filename": "SMC-6.10.2-2018.03.19.2228-0.iso", + "filesize": 2311847936, + "md5sum": "e4e31ea6eb5c17c12769724f0c70b452", + "version": "6.10.2-2018.03.19.2228-0" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty200G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty200G.qcow2", + "filesize": 200192, + "md5sum": "d1686d2f25695dee32eab9a6f4652c7c", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco Stealthwatch Management Console", + "port_name_format": "eth{port1}", + "product_name": "Stealthwatch Management Console", + "product_url": "https://www.cisco.com/c/en/us/products/security/stealthwatch/index.html", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "cpus": 3, + "hda_disk_interface": "scsi", + "kvm": "require", + "options": "", + "ram": 8192 + }, + "registry_version": 4, + "status": "experimental", + "symbol": "cisco-fmcv.svg", + "usage": "Starting Stealthwatch Management Console will start an installation of SMC onto a blank 200GB Drive.\nDefault console username/password: sysadmin/lan1cope.\nDefault web username/password: admin/lan411cope.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "cdrom_image": "SMC-6.10.4-2018.11.14.1757-0.iso", + "hda_disk_image": "empty200G.qcow2" + }, + "name": "6.10.4-2018.11.14.1757-0" + }, + { + "images": { + "cdrom_image": "SMC-6.10.2-2018.03.19.2228-0.iso", + "hda_disk_image": "empty200G.qcow2" + }, + "name": "6.10.2-2018.03.19.2228-0" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Trend Micro InterScan Messaging Security stops email threats in the cloud with global threat intelligence, protects your data with data loss prevention and encryption, and identifies targeted email attacks,ransomware, and APTs as part of the Trend Micro Network Defense Solution. The hybrid SaaS deployment combines the privacy and control of an on-premises virtual appliance with the proactive protection of a cloud-based pre-filter service. It\u2019s the enterprise-level protection you need with the highest spam and phishing detection rates\u2014consistently #1 in quarterly Opus One competitive tests since 2011.", + "documentation_url": "https://success.trendmicro.com/product-support/interscan-messaging-security", + "images": [ + { + "direct_download_url": "http://files.trendmicro.com/products/imsva/9.1/IMSVA-9.1-1600-x86_64-r1.iso", + "download_url": "http://downloadcenter.trendmicro.com/index.php?regs=NABU&clk=latest&clkval=4913&lang_loc=1", + "filename": "IMSVA-9.1-1600-x86-64-r1.iso", + "filesize": 797560832, + "md5sum": "581278e8ddb25486539dfe3ad0b3ac94", + "version": "9.1" + }, + { + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty200G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty200G.qcow2", + "filesize": 200192, + "md5sum": "d1686d2f25695dee32eab9a6f4652c7c", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "IMS VA", + "port_name_format": "eth{0}", + "product_name": "IMS VA", + "product_url": "http://www.trendmicro.com/enterprise/network-security/interscan-message-security/index.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 4096 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Default credentials: admin / imsva", + "vendor_name": "Trend Micro Inc.", + "vendor_url": "http://www.trendmicro.com/", + "versions": [ + { + "images": { + "cdrom_image": "IMSVA-9.1-1600-x86-64-r1.iso", + "hda_disk_image": "empty200G.qcow2" + }, + "name": "9.1" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "The vSRX delivers core firewall, networking, advanced security, and automated lifecycle management capabilities for enterprises and service providers. The industry\u2019s fastest virtual security platform, the vSRX offers firewall speeds up to 17 Gbps using only two virtual CPUs, providing scalable, secure protection across private, public, and hybrid clouds.\n\nJuniper version 12 can support only 1GB of ram.", + "documentation_url": "http://www.juniper.net/techpubs/", + "first_port_name": "fxp0", + "images": [ + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "junos-media-vsrx-vmdisk-18.1R1.9.qcow2", + "filesize": 4418961408, + "md5sum": "4e9393142afc675d5d3d03c5071e70ce", + "version": "18.1R1" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-17.4R1.16.qcow2", + "filesize": 3965386752, + "md5sum": "616c4742b09652318c73a7cc598468e7", + "version": "17.4R1" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-17.3R2.10.qcow2", + "filesize": 3784572928, + "md5sum": "8f2adfb0515913e0c7db32628a5deb3e", + "version": "17.3R2" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-17.3R1.10.qcow2", + "filesize": 3782541312, + "md5sum": "49b276e9ccdd8588f9e2ff38cccc884a", + "version": "17.3R1" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-15.1X49-D130.6.qcow2", + "filesize": 3300917248, + "md5sum": "8ad03f4067b3fe5d2ed378733a5e8541", + "version": "15.1X49-D130" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-15.1X49-D120.3.qcow2", + "filesize": 3280273408, + "md5sum": "02cf4df3dc988a407ccd5ddc30ee5385", + "version": "15.1X49-D120" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-15.1X49-D110.4.qcow2", + "filesize": 3280011264, + "md5sum": "8d74641594eb036b2e2c6b462d541156", + "version": "15.1X49-D110" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-15.1X49-D100.6.qcow2", + "filesize": 3279290368, + "md5sum": "aa29686dd6f2d38f668f23cb4bc9f354", + "version": "15.1X49-D100" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-15.1X49-D90.7.qcow2", + "filesize": 3189440512, + "md5sum": "a64f3910054d461c4bbb32620008cba3", + "version": "15.1X49-D90" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-15.1X49-D80.4.qcow2", + "filesize": 3186884608, + "md5sum": "ceb9d06a827c8f8bfb4fd1c9065bdd20", + "version": "15.1X49-D80" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-15.1X49-D75.5.qcow2", + "filesize": 3116236800, + "md5sum": "197f167f338420d36a6db0f4e84ad376", + "version": "15.1X49-D75" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "media-vsrx-vmdisk-15.1X49-D70.3.qcow2", + "filesize": 3115450368, + "md5sum": "7b11babaef0b775f36281ec1d16f1708", + "version": "15.1X49-D70" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "junos-vsrx-vmdisk-15.1X49-D60.qcow2", + "filesize": 3094478848, + "md5sum": "d2ec79880f67e141c4dd662c656da278", + "version": "15.1X49-D60" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "junos-vsrx-vmdisk-15.1X49-D50.qcow2", + "filesize": 3063021568, + "md5sum": "60e1b80603c2ecf8aa9920c384209863", + "version": "15.1X49-D50" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "junos-vsrx-vmdisk-15.1X49-D40.qcow2", + "filesize": 3054043136, + "md5sum": "8d929c0262fd1eea3b3d02ef9e73c8c5", + "version": "15.1X49-D40" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "junos-vsrx-vmdisk-15.1X49-D20.2.qcow2", + "filesize": 2904096768, + "md5sum": "43e8000870207db47c1382192319eb45", + "version": "15.1X49-D20.2" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", + "filename": "junos-vsrx-12.1X47-D20.7-domestic-disk1.vmdk", + "filesize": 235894272, + "md5sum": "d22ed7a7eb131984e892a4430c5f4730", + "version": "12.1X47-D20.7" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "vSRX", + "port_name_format": "ge-0/0/{0}", + "product_name": "Juniper vSRX", + "product_url": "https://www.juniper.net/us/en/products-services/security/srx-series/vsrx/", + "qemu": { + "adapter_type": "e1000", + "adapters": 6, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "options": "-smp 2", + "ram": 4096 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Initial username is root, no password.", + "vendor_name": "Juniper", + "vendor_url": "https://www.juniper.net/us/en/", + "versions": [ + { + "images": { + "hda_disk_image": "junos-media-vsrx-vmdisk-18.1R1.9.qcow2" + }, + "name": "18.1R1" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-17.4R1.16.qcow2" + }, + "name": "17.4R1" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-17.3R2.10.qcow2" + }, + "name": "17.3R2" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-17.3R1.10.qcow2" + }, + "name": "17.3R1" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D130.6.qcow2" + }, + "name": "15.1X49-D130" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D120.3.qcow2" + }, + "name": "15.1X49-D120" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D110.4.qcow2" + }, + "name": "15.1X49-D110" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D100.6.qcow2" + }, + "name": "15.1X49-D100" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D90.7.qcow2" + }, + "name": "15.1X49-D90" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D80.4.qcow2" + }, + "name": "15.1X49-D80" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D75.5.qcow2" + }, + "name": "15.1X49-D75" + }, + { + "images": { + "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D70.3.qcow2" + }, + "name": "15.1X49-D70" + }, + { + "images": { + "hda_disk_image": "junos-vsrx-vmdisk-15.1X49-D60.qcow2" + }, + "name": "15.1X49-D60" + }, + { + "images": { + "hda_disk_image": "junos-vsrx-vmdisk-15.1X49-D50.qcow2" + }, + "name": "15.1X49-D50" + }, + { + "images": { + "hda_disk_image": "junos-vsrx-vmdisk-15.1X49-D40.qcow2" + }, + "name": "15.1X49-D40" + }, + { + "images": { + "hda_disk_image": "junos-vsrx-vmdisk-15.1X49-D20.2.qcow2" + }, + "name": "15.1X49-D20" + }, + { + "images": { + "hda_disk_image": "junos-vsrx-12.1X47-D20.7-domestic-disk1.vmdk" + }, + "name": "12.1X47-D20" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "FortiProxy is a secure web proxy that protects employees against internet-borne attacks by incorporating multiple detection techniques such as web filtering, DNS filtering, data loss prevention, antivirus, intrusion prevention and advanced threat protection. It helps enterprises enforce internet compliance using granular application control.", + "documentation_url": "https://docs.fortinet.com/fortiproxy/", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FPX_KVM-v100-build0147-FORTINET.out.kvm.qcow2", + "filesize": 42668032, + "md5sum": "d7c60693bfa58246e5063304cd450c89", + "version": "1.1.0" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiProxy", + "port_name_format": "Port{port1}", + "product_name": "FortiProxy", + "product_url": "https://www.fortinet.com/content/dam/fortinet/assets/data-sheets/FortiProxy.pdf", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 10, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "The system reboots twice during the initial setup; this is normal.\nDefault username is admin, no password is set.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FPX_KVM-v100-build0147-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "1.1.0" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco 3745 Multiservice Access Router", + "documentation_url": "http://www.cisco.com/c/en/us/support/routers/3745-multiservice-access-router/model.html", + "dynamips": { + "chassis": "", + "nvram": 256, + "platform": "c3745", + "ram": 256, + "slot0": "GT96100-FE", + "slot1": "NM-1FE-TX", + "slot2": "NM-4T", + "slot3": "", + "slot4": "", + "startup_config": "ios_base_startup-config.txt", + "wic0": "WIC-1T", + "wic1": "WIC-1T", + "wic2": "WIC-1T" + }, + "images": [ + { + "filename": "c3745-adventerprisek9-mz.124-25d.image", + "filesize": 82053028, + "md5sum": "ddbaf74274822b50fa9670e10c75b08f", + "version": "124-25d" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco 3745", + "product_name": "3745", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "idlepc": "0x60aa1da0", + "images": { + "image": "c3745-adventerprisek9-mz.124-25d.image" + }, + "name": "124-25d" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "A light Linux based on TinyCore Linux with Firefox preinstalled", + "documentation_url": "https://support.mozilla.org", + "images": [ + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-tinycore-linux-6.4-firefox-33.1.1-2.img", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "linux-tinycore-linux-6.4-firefox-33.1.1-2.img", + "filesize": 93257728, + "md5sum": "8db0d8dc890797cc335ceb8aaf2255f0", + "version": "31.1.1~2" + }, + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-tinycore-linux-6.4-firefox-33.1.1.img", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "linux-tinycore-linux-6.4-firefox-33.1.1.img", + "filesize": 82313216, + "md5sum": "9e51ad24dc25c4a26f7a8fb99bc77830", + "version": "31.1.1~1" + } + ], + "maintainer": "GNS3 team", + "maintainer_email": "developers@gns3.net", + "name": "Firefox", + "product_name": "Firefox", + "product_url": "https://www.mozilla.org/firefox", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "i386", + "console_type": "vnc", + "kvm": "allow", + "options": "-vga std -usbdevice tablet", + "ram": 256 + }, + "registry_version": 3, + "status": "stable", + "symbol": "firefox.svg", + "vendor_name": "Mozilla Foundation", + "vendor_url": "http://www.mozilla.org", + "versions": [ + { + "images": { + "hda_disk_image": "linux-tinycore-linux-6.4-firefox-33.1.1-2.img" + }, + "name": "31.1.1~2" + }, + { + "images": { + "hda_disk_image": "linux-tinycore-linux-6.4-firefox-33.1.1.img" + }, + "name": "31.1.1~1" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Don't you hate it when companies artificially cripple performance? We just give you two simple choices - Now isn't that a refreshing change?", + "documentation_url": "https://loadbalancer.org/support/support-resources", + "images": [ + { + "download_url": "https://loadbalancer.org/resources/free-trial", + "filename": "Loadbalancer.org_Enterprise_VA-8.3-disk1.qcow2", + "filesize": 368332288, + "md5sum": "f0e41f39a5cab47990edc0509c579bac", + "version": "8.3" + }, + { + "download_url": "https://loadbalancer.org/resources/free-trial", + "filename": "Loadbalancer.org_Enterprise_VA-8.2-disk1.qcow2", + "filesize": 8430419968, + "md5sum": "8b74b330a6f629a081f3b36a5d64605b", + "version": "8.2" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Loadbalancer.org Enterprise VA", + "product_name": "Loadbalancer.org Enterprise VA", + "product_url": "https://loadbalancer.org/products/virtual", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 2, + "arch": "x86_64", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "loadbalancer.svg", + "usage": "Default credentials:\n Network config CLI: setup / setup\n CLI: root / loadbalancer\n WebUI: loadbalancer / loadbalancer", + "vendor_name": "Loadbalancer.org", + "vendor_url": "https://loadbalancer.org/", + "versions": [ + { + "images": { + "hda_disk_image": "Loadbalancer.org_Enterprise_VA-8.3-disk1.qcow2" + }, + "name": "8.3" + }, + { + "images": { + "hda_disk_image": "Loadbalancer.org_Enterprise_VA-8.2-disk1.qcow2" + }, + "name": "8.2" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco 3640 Router", + "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", + "dynamips": { + "chassis": "3640", + "nvram": 256, + "platform": "c3600", + "ram": 192, + "startup_config": "ios_base_startup-config.txt" + }, + "images": [ + { + "filename": "c3640-a3js-mz.124-25d.image", + "filesize": 65688632, + "md5sum": "493c4ef6578801d74d715e7d11596964", + "version": "124-25d" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco 3640", + "product_name": "3640", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "idlepc": "0x6050b114", + "images": { + "image": "c3640-a3js-mz.124-25d.image" + }, + "name": "124-25d" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "FortiCache VM high performance Web Caching virtual appliances address bandwidth saturation, high latency, and poor performance caused by caching popular internet content locally for carriers, service providers, enterprises and educational networks. FortiCache VM appliances reduce the cost and impact of cached content on the network, while increasing performance and end- user satisfaction by improving the speed of delivery of popular repeated content.", + "documentation_url": "http://docs.fortinet.com/forticache/admin-guides", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0226-FORTINET.out.kvm.qcow2", + "filesize": 27676672, + "md5sum": "17efdc8f037c8ec1d1fc67ae262f619e", + "version": "4.2.8" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0222-FORTINET.out.kvm.qcow2", + "filesize": 27631616, + "md5sum": "d77790e414f4e2b31c756906a720e681", + "version": "4.2.7" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0216-FORTINET.out.kvm.qcow2", + "filesize": 27553792, + "md5sum": "867e0569b8466db744547422a1d6f17a", + "version": "4.2.6" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0213-FORTINET.out.kvm.qcow2", + "filesize": 27508736, + "md5sum": "78db88447f29f363b4ba8e4833474637", + "version": "4.2.5" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0204-FORTINET.out.kvm.qcow2", + "filesize": 27623424, + "md5sum": "8f0aad31131add43ac6bf709dd708970", + "version": "4.2.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0200-FORTINET.out.kvm.qcow2", + "filesize": 27467776, + "md5sum": "7ec6c4c4e4ba7976793769422550fc30", + "version": "4.2.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0127-FORTINET.out.kvm.qcow2", + "filesize": 26087424, + "md5sum": "c607391c3aaaa014e9cec8c61354485b", + "version": "4.1.6" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0123-FORTINET.out.kvm.qcow2", + "filesize": 25845760, + "md5sum": "f6d161636528ecee87243174c51e56e7", + "version": "4.1.5" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0119-FORTINET.out.kvm.qcow2", + "filesize": 25825280, + "md5sum": "d2c8236768e795eb80114e5c5f4dfac9", + "version": "4.1.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0112-FORTINET.out.kvm.qcow2", + "filesize": 25812992, + "md5sum": "554ebdf8874753b275c2f1ed9104e081", + "version": "4.1.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FCHKVM-v400-build0109-FORTINET.out.kvm.qcow2", + "filesize": 25829376, + "md5sum": "c54246365b3d3f03c9ff2184127695ea", + "version": "4.1.2" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 198656, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiCache", + "port_name_format": "Port{port1}", + "product_name": "FortiCache", + "product_url": "https://www.fortinet.com/products-services/products/wan-appliances/forticache.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 3, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "ide", + "hdb_disk_interface": "ide", + "kvm": "require", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "Default username is admin, no password is set.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0226-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.2.8" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0222-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.2.7" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0216-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.2.6" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0213-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.2.5" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0204-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.2.4" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0200-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.2.3" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0127-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.1.6" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0123-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.1.5" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0119-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.1.4" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0112-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.1.3" + }, + { + "images": { + "hda_disk_image": "FCHKVM-v400-build0109-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "4.1.2" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.", + "docker": { + "adapters": 16, + "image": "gns3/openvswitch:latest" + }, + "documentation_url": "http://openvswitch.org/support/", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Open vSwitch", + "product_name": "Open vSwitch", + "product_url": "http://openvswitch.org/", + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "By default all interfaces are connected to the br0", + "vendor_name": "Open vSwitch", + "vendor_url": "http://openvswitch.org/" + }, + { + "builtin": true, + "category": "guest", + "description": "Ostinato is an open-source, cross-platform network packet crafter/traffic generator and analyzer with a friendly GUI. Craft and send packets of several streams with different protocols at different rates.", + "documentation_url": "http://ostinato.org/docs.html", + "images": [ + { + "direct_download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/ostinato-0.9-1.qcow2", + "download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/index.html", + "filename": "ostinato-0.9-1.qcow2", + "filesize": 101646336, + "md5sum": "00b4856ec9fffbcbcab7a8f757355d69", + "version": "0.9" + }, + { + "direct_download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/ostinato-0.8-1.qcow2", + "download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/index.html", + "filename": "ostinato-0.8-1.qcow2", + "filesize": 57344000, + "md5sum": "12e990ba695103cfac82f8771b8015d4", + "version": "0.8" + } + ], + "maintainer": "Bernhard Ehlers", + "maintainer_email": "be@bernhard-ehlers.de", + "name": "Ostinato", + "port_name_format": "eth{0}", + "product_name": "Ostinato", + "product_url": "http://ostinato.org/", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "arch": "i386", + "console_type": "vnc", + "kvm": "allow", + "options": "-vga std -usbdevice tablet", + "ram": 256 + }, + "registry_version": 3, + "status": "experimental", + "symbol": "ostinato-3d-icon.svg", + "usage": "Use interfaces starting with eth1 as traffic interfaces, eth0 is only for the (optional) management of the server/drone.", + "vendor_name": "Ostinato", + "vendor_url": "http://ostinato.org/", + "versions": [ + { + "images": { + "hda_disk_image": "ostinato-0.9-1.qcow2" + }, + "name": "0.9" + }, + { + "images": { + "hda_disk_image": "ostinato-0.8-1.qcow2" + }, + "name": "0.8" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "IPFire was designed with both modularity and a high-level of flexibility in mind. You can easily deploy many variations of it, such as a firewall, a proxy server or a VPN gateway. The modular design ensures that it runs exactly what you've configured it for and nothing more. Everything is simple to manage and update through the package manager, making maintenance a breeze.", + "documentation_url": "http://wiki.ipfire.org/en/start", + "images": [ + { + "compression": "xz", + "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.21-core124/ipfire-2.21.2gb-ext4.x86_64-full-core124.img.xz", + "download_url": "http://www.ipfire.org/download", + "filename": "ipfire-2.21.2gb-ext4.x86_64-full-core124.img", + "filesize": 1541160960, + "md5sum": "970a5cafaa0cb4cfbf42772f41d24932", + "version": "2.21.124" + }, + { + "compression": "gzip", + "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.19-core119/ipfire-2.19.1gb-ext4-scon.x86_64-full-core119.img.gz", + "download_url": "http://www.ipfire.org/download", + "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core119.img", + "filesize": 1063256064, + "md5sum": "b57be976ff54569b71eae4ee66634b0d", + "version": "2.19.119" + }, + { + "compression": "gzip", + "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.19-core118/ipfire-2.19.1gb-ext4-scon.x86_64-full-core118.img.gz", + "download_url": "http://www.ipfire.org/download", + "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core118.img", + "filesize": 1063256064, + "md5sum": "4dbeb474848d87c16c20ff4e31feb204", + "version": "2.19.118" + }, + { + "compression": "gzip", + "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.19-core117/ipfire-2.19.1gb-ext4-scon.x86_64-full-core117.img.gz", + "download_url": "http://www.ipfire.org/download", + "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core117.img", + "filesize": 1063256064, + "md5sum": "657673d88b94ed7d22332aebe817bc86", + "version": "2.19.117" + }, + { + "compression": "gzip", + "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.19-core116/ipfire-2.19.1gb-ext4-scon.x86_64-full-core116.img.gz", + "download_url": "http://www.ipfire.org/download", + "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core116.img", + "filesize": 1063256064, + "md5sum": "2a8df99d117a0dbfb67870494c0c67cd", + "version": "2.19.116" + }, + { + "compression": "gzip", + "direct_download_url": "http://downloads.ipfire.org/releases/ipfire-2.x/2.19-core110/ipfire-2.19.1gb-ext4-scon.x86_64-full-core110.img.gz", + "download_url": "http://www.ipfire.org/download", + "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core111.img", + "filesize": 1063256064, + "md5sum": "741ab771cadd2f6a1fc4a85b3478ae5f", + "version": "2.19.111" + }, + { + "compression": "gzip", + "direct_download_url": "http://downloads.ipfire.org/releases/ipfire-2.x/2.19-core110/ipfire-2.19.1gb-ext4-scon.x86_64-full-core110.img.gz", + "download_url": "http://www.ipfire.org/download", + "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core110.img", + "filesize": 958398464, + "md5sum": "d91bdabee5db83d0f93573f88ea542b1", + "version": "2.19.110" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "IPFire", + "port_name_format": "eth{0}", + "product_name": "IPFire", + "product_url": "http://www.ipfire.org/features", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "A config wizard will be started at first boot.", + "vendor_name": "IPFire Project", + "vendor_url": "http://www.ipfire.org/", + "versions": [ + { + "images": { + "hda_disk_image": "ipfire-2.21.2gb-ext4.x86_64-full-core124.img" + }, + "name": "2.21.124" + }, + { + "images": { + "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core119.img" + }, + "name": "2.19.119" + }, + { + "images": { + "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core118.img" + }, + "name": "2.19.118" + }, + { + "images": { + "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core117.img" + }, + "name": "2.19.117" + }, + { + "images": { + "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core116.img" + }, + "name": "2.19.116" + }, + { + "images": { + "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core111.img" + }, + "name": "2.19.111" + }, + { + "images": { + "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core110.img" + }, + "name": "2.19.110" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "From the creators of BackTrack comes Kali Linux, the most advanced and versatile penetration testing platform ever created. We have a set of amazing features lined up in our security distribution geared at streamlining the penetration testing experience.", + "documentation_url": "https://www.kali.org/kali-linux-documentation/", + "images": [ + { + "direct_download_url": "http://cdimage.kali.org/kali-2018.4/kali-linux-2018.4-amd64.iso", + "download_url": "https://www.kali.org/downloads/", + "filename": "kali-linux-2018.4-amd64.iso", + "filesize": 3139436544, + "md5sum": "1b2d598bb8d2003e6207c119c0ba42fe", + "version": "2018.4" + }, + { + "direct_download_url": "http://cdimage.kali.org/kali-2018.3a/kali-linux-2018.3a-amd64.iso", + "download_url": "https://www.kali.org/downloads/", + "filename": "kali-linux-2018.3a-amd64.iso", + "filesize": 3192651776, + "md5sum": "2da675d016bd690c05e180e33aa98b94", + "version": "2018.3a" + }, + { + "direct_download_url": "http://cdimage.kali.org/kali-2018.1/kali-linux-2018.1-amd64.iso", + "download_url": "https://www.kali.org/downloads/", + "filename": "kali-linux-2018.1-amd64.iso", + "filesize": 3028500480, + "md5sum": "a3feb90df5b71b3c7f4a02bdddf221d7", + "version": "2018.1" + }, + { + "direct_download_url": "http://cdimage.kali.org/kali-2017.3/kali-linux-2017.3-amd64.iso", + "download_url": "http://cdimage.kali.org/kali-2017.3/", + "filename": "kali-linux-2017.3-amd64.iso", + "filesize": 2886402048, + "md5sum": "b465580c897e94675ac1daf031fa66b9", + "version": "2017.3" + }, + { + "direct_download_url": "http://cdimage.kali.org/kali-2017.2/kali-linux-2017.2-amd64.iso", + "download_url": "http://cdimage.kali.org/kali-2017.2/", + "filename": "kali-linux-2017.2-amd64.iso", + "filesize": 3020619776, + "md5sum": "541654f8f818450dc0db866a0a0f6eec", + "version": "2017.2" + }, + { + "direct_download_url": "http://cdimage.kali.org/kali-2017.1/kali-linux-2017.1-amd64.iso", + "download_url": "http://cdimage.kali.org/kali-2017.1/", + "filename": "kali-linux-2017.1-amd64.iso", + "filesize": 2794307584, + "md5sum": "c8e742283929d7a12dbe7c58e398ff08", + "version": "2017.1" + }, + { + "direct_download_url": "http://cdimage.kali.org/kali-2016.2/kali-linux-2016.2-amd64.iso", + "download_url": "http://cdimage.kali.org/kali-2016.2/", + "filename": "kali-linux-2016.2-amd64.iso", + "filesize": 3076767744, + "md5sum": "3d163746bc5148e61ad689d94bc263f9", + "version": "2016.2" + }, + { + "direct_download_url": "http://cdimage.kali.org/kali-2016.1/kali-linux-2016.1-amd64.iso", + "download_url": "http://cdimage.kali.org/kali-2016.1/", + "filename": "kali-linux-2016.1-amd64.iso", + "filesize": 2945482752, + "md5sum": "2e1230dc14036935b3279dfe3e49ad39", + "version": "2016.1" + }, + { + "direct_download_url": "http://images.kali.org/Kali-Linux-2.0.0-vm-amd64.7z", + "download_url": "https://www.offensive-security.com/kali-linux-vmware-arm-image-download/", + "filename": "kali-linux-2.0-amd64.iso", + "filesize": 3320512512, + "md5sum": "ef192433017c5d99a156eaef51fd389d", + "version": "2.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Kali Linux", + "product_name": "Kali Linux", + "qemu": { + "adapter_type": "e1000", + "adapters": 8, + "arch": "x86_64", + "console_type": "vnc", + "kvm": "require", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Default password is toor", + "vendor_name": "Kali Linux", + "vendor_url": "https://www.kali.org/", + "versions": [ + { + "images": { + "cdrom_image": "kali-linux-2018.4-amd64.iso" + }, + "name": "2018.4" + }, + { + "images": { + "cdrom_image": "kali-linux-2018.3a-amd64.iso" + }, + "name": "2018.3a" + }, + { + "images": { + "cdrom_image": "kali-linux-2018.1-amd64.iso" + }, + "name": "2018.1" + }, + { + "images": { + "cdrom_image": "kali-linux-2017.3-amd64.iso" + }, + "name": "2017.3" + }, + { + "images": { + "cdrom_image": "kali-linux-2017.2-amd64.iso" + }, + "name": "2017.2" + }, + { + "images": { + "cdrom_image": "kali-linux-2017.1-amd64.iso" + }, + "name": "2017.1" + }, + { + "images": { + "cdrom_image": "kali-linux-2016.2-amd64.iso" + }, + "name": "2016.2" + }, + { + "images": { + "cdrom_image": "kali-linux-2016.1-amd64.iso" + }, + "name": "2016.1" + }, + { + "images": { + "cdrom_image": "kali-linux-2.0-amd64.iso" + }, + "name": "2.0" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "The Open Network Operating System (ONOS) is a software defined networking (SDN) OS for service providers that has scalability, high availability, high performance and abstractions to make it easy to create apps and services. The platform is based on a solid architecture and has quickly matured to be feature rich and production ready. The community has grown to include over 50 partners and collaborators that contribute to all aspects of the project including interesting use cases such as CORD", + "docker": { + "adapters": 1, + "image": "onosproject/onos:latest" + }, + "documentation_url": "https://wiki.onosproject.org", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Onos", + "product_name": "Onos", + "product_url": "http://onosproject.org/", + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "vendor_name": "Onos", + "vendor_url": "http://onosproject.org/" + }, + { + "builtin": true, + "category": "firewall", + "description": "FortiWeb Web Application Firewalls provide specialized, layered web application threat protection for medium/large enterprises, application service providers, and SaaS providers.", + "documentation_url": "http://docs.fortinet.com/fortiweb", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v600-build0056-FORTINET.out.kvm.qcow2", + "filesize": 156959232, + "md5sum": "cc7800bc6c2dd60c583d2d4ef1965e01", + "version": "6.0.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v600-build0036-FORTINET.out.kvm.qcow2", + "filesize": 138412544, + "md5sum": "220170383b66a6f8091729d67a8fef3e", + "version": "6.0.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v500-build1618-FORTINET.out.kvm.qcow2", + "filesize": 132579840, + "md5sum": "12bafff7bbfbf9a49554c6378f0e1a46", + "version": "5.9.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v500-build1609-FORTINET.out.kvm.qcow2", + "filesize": 140837376, + "md5sum": "a957ae3d60eabc685fcda015c31a5d01", + "version": "5.9.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v500-build1413-FORTINET.out.kvm.qcow2", + "filesize": 105775616, + "md5sum": "910fefe796daa5c963b0bde121996306", + "version": "5.8.6" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v500-build0739-FORTINET.out.kvm-log.qcow2", + "filesize": 7602176, + "md5sum": "d42225723d2e2ee0160f101c5b9663d5", + "version": "5.5.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v500-FORTINET.out.kvm-log.qcow2", + "filesize": 7602176, + "md5sum": "b90cd0a382cb09db31cef1d0cdf7d6e9", + "version": "5.5.2 - 5.5.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v500-build0739-FORTINET.out.kvm-boot.qcow2", + "filesize": 87228416, + "md5sum": "a11b91efacce70212b6b9e1f9916cc3e", + "version": "5.5.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v500-build0730-FORTINET.out.kvm-boot.qcow2", + "filesize": 87228416, + "md5sum": "12ebec432a54900e6c63540af8ebfbb4", + "version": "5.5.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FWB_KVM-v500-build0723-FORTINET.out.kvm-boot.qcow2", + "filesize": 87162880, + "md5sum": "0a613191948d3618ae16cd9f11988448", + "version": "5.5.2" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiWeb", + "port_name_format": "Port{port1}", + "product_name": "FortiWeb", + "product_url": "http://www.fortinet.com/products/fortiweb/index.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "Default username is admin, no password is set. Console keeps sending 'access uuid file failed, error number 2' messages; ignore it.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FWB_KVM-v600-build0056-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.2" + }, + { + "images": { + "hda_disk_image": "FWB_KVM-v600-build0036-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.1" + }, + { + "images": { + "hda_disk_image": "FWB_KVM-v500-build1618-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.9.1" + }, + { + "images": { + "hda_disk_image": "FWB_KVM-v500-build1609-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.9.0" + }, + { + "images": { + "hda_disk_image": "FWB_KVM-v500-build1413-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.8.6" + }, + { + "images": { + "hda_disk_image": "FWB_KVM-v500-build0739-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FWB_KVM-v500-build0739-FORTINET.out.kvm-log.qcow2" + }, + "name": "5.5.4" + }, + { + "images": { + "hda_disk_image": "FWB_KVM-v500-build0730-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FWB_KVM-v500-FORTINET.out.kvm-log.qcow2" + }, + "name": "5.5.3" + }, + { + "images": { + "hda_disk_image": "FWB_KVM-v500-build0723-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FWB_KVM-v500-FORTINET.out.kvm-log.qcow2" + }, + "name": "5.5.2" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "IOS XRv supports the control plane features introduced in Cisco IOS XR.", + "documentation_url": "http://www.cisco.com/c/en/us/td/docs/ios_xr_sw/ios_xrv/release/notes/xrv-rn.html", + "first_port_name": "MgmtEth0/0/CPU0/0", + "images": [ + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "iosxrv-k9-demo-6.1.3.qcow2", + "filesize": 428588544, + "md5sum": "1693b5d22a398587dd0fed2877d8dfac", + "version": "6.1.3" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "iosxrv-k9-demo-6.0.1.qcow2", + "filesize": 908132352, + "md5sum": "0831ecf43628eccb752ebb275de9a62a", + "version": "6.0.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco IOS XRv", + "port_name_format": "Gi0/0/0/{0}", + "product_name": "IOS XRv", + "product_url": "http://virl.cisco.com/", + "qemu": { + "adapter_type": "e1000", + "adapters": 9, + "arch": "i386", + "console_type": "telnet", + "kvm": "require", + "ram": 3072 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "You can set admin username and password on first boot. Don't forget about the two-staged configuration, you have to commit your changes.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "iosxrv-k9-demo-6.1.3.qcow2" + }, + "name": "6.1.3" + }, + { + "images": { + "hda_disk_image": "iosxrv-k9-demo-6.0.1.qcow2" + }, + "name": "6.0.1" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "BSD Router Project (BSDRP) is an embedded free and open source router distribution based on FreeBSD with Quagga and Bird.", + "images": [ + { + "compression": "xz", + "direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.91/amd64/BSDRP-1.91-full-amd64-serial.img.xz/download", + "download_url": "https://bsdrp.net/downloads", + "filename": "BSDRP-1.91-full-amd64-serial.img", + "filesize": 1000000000, + "md5sum": "cea67b29ce94e66b617e7dc90956af45", + "version": "1.91" + }, + { + "compression": "xz", + "direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.90/amd64/BSDRP-1.90-full-amd64-serial.img.xz/download", + "download_url": "https://bsdrp.net/downloads", + "filename": "BSDRP-1.90-full-amd64-serial.img", + "filesize": 1000000000, + "md5sum": "78b7182bed93888d17d18a67d5fec3a7", + "version": "1.90" + }, + { + "compression": "xz", + "direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.80/amd64/BSDRP-1.80-full-amd64-serial.img.xz/download", + "download_url": "https://bsdrp.net/downloads", + "filename": "BSDRP-1.80-full-amd64-serial.img", + "filesize": 1000000000, + "md5sum": "a4285be15ac85f67b3c7f044872a54b6", + "version": "1.80" + }, + { + "compression": "xz", + "direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.70/amd64/BSDRP-1.70-full-amd64-serial.img.xz/download", + "download_url": "https://bsdrp.net/downloads", + "filename": "BSDRP-1.70-full-amd64-serial.img", + "filesize": 1000000000, + "md5sum": "9c11f61ddf03ee9a9ae4149676175821", + "version": "1.70" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "BSDRP", + "product_name": "BSDRP", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "allow", + "ram": 256 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "Default user: root (no password set)", + "vendor_name": "Olivier Cochard-Labbe", + "vendor_url": "https://bsdrp.net/", + "versions": [ + { + "images": { + "hda_disk_image": "BSDRP-1.91-full-amd64-serial.img" + }, + "name": "1.91" + }, + { + "images": { + "hda_disk_image": "BSDRP-1.90-full-amd64-serial.img" + }, + "name": "1.90" + }, + { + "images": { + "hda_disk_image": "BSDRP-1.80-full-amd64-serial.img" + }, + "name": "1.80" + }, + { + "images": { + "hda_disk_image": "BSDRP-1.70-full-amd64-serial.img" + }, + "name": "1.70" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "AsteriskNOW makes it easy to create custom telephony solutions by automatically installing the 'plumbing'. It's a complete Linux distribution with Asterisk, the DAHDI driver framework, and, the FreePBX administrative GUI. Much of the complexity of Asterisk and Linux is handled by the installer, the yum package management utility and the administrative GUI. With AsteriskNOW, application developers and integrators can concentrate on building solutions, not maintaining the plumbing.", + "documentation_url": "https://wiki.asterisk.org/wiki/display/AST/Installing+AsteriskNOW", + "images": [ + { + "direct_download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/AsteriskNow-1013-current-64.iso", + "download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/", + "filename": "AsteriskNow-1013-current-64.iso", + "filesize": 1343909888, + "md5sum": "1badc6d68b59b57406e1b9ae69acf2e2", + "version": "10.13" + }, + { + "direct_download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/AsteriskNOW-612-current-64.iso", + "download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/", + "filename": "AsteriskNOW-612-current-64.iso", + "filesize": 1135714304, + "md5sum": "cc31e6d9b88d49e8eb182f1e2fb85479", + "version": "6.12" + }, + { + "direct_download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/AsteriskNOW-5211-current-64.iso", + "download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/", + "filename": "AsteriskNOW-5211-current-64.iso", + "filesize": 1124741120, + "md5sum": "aef2b0fffd637b9c666e8ce904bbd714", + "version": "5.211" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "AsteriskNOW", + "port_name_format": "eth{0}", + "product_name": "AsteriskNOW", + "product_url": "http://www.asterisk.org/downloads/asterisknow", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Select 'No RAID' option when installing the appliance using the VNC console. Installing the freepbx package takes a lot of time (15+ minutes).", + "vendor_name": "Digium", + "vendor_url": "http://www.asterisk.org/", + "versions": [ + { + "images": { + "cdrom_image": "AsteriskNow-1013-current-64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "10.13" + }, + { + "images": { + "cdrom_image": "AsteriskNOW-612-current-64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "6.12" + }, + { + "images": { + "cdrom_image": "AsteriskNOW-5211-current-64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "5.211" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Cisco Stealthwatch is the most comprehensive visibility and network traffic security analytics solution that uses enterprise telemetry from the existing network infrastructure. It provides advanced threat detection, accelerated threat response, and simplified network segmentation using multilayer machine learning and entity modeling. With advanced behavioral analytics, you\u2019ll always know who is on your network and what they are doing.\n\nAt the heart of the Stealthwatch System is the highly scalable Stealthwatch Flow Collector. The Flow Collector is available as either a physical or a virtual appliance. The Flow Collector VE performs the same functions as its physical counterpart, but in a virtual environment. The Stealthwatch Flow Collector for NetFlow gathers NetFlow, cFlow, J-Flow, Packeteer 2, NetStream, and IPFIX data. To achieve full network visibility with a traditional probe-based approach, you would need to install a probe for each router or switch on your network. This results in many costly hardware installations. Conversely, Stealthwatch\u2019s flow-based approach provides you with full network visibility at a fraction of the cost. Each Flow Collector can process data for as many as 1,000,000 hosts from up to 2,000 flow exporters, depending on the Flow Collector model and license restrictions. ", + "documentation_url": "https://www.cisco.com/c/en/us/support/security/stealthwatch/tsd-products-support-series-home.html", + "first_port_name": "eth0", + "images": [ + { + "download_url": "https://stealthwatch.flexnetoperations.com/control/lncp/product?child_plneID=786407", + "filename": "FlowCollector-NetFlow-6.10.4-2018.11.14.1757-0.iso", + "filesize": 2479288320, + "md5sum": "accd9fb9dd2d312805883749899a2fc0", + "version": "6.10.4-2018.11.14.1757-0" + }, + { + "download_url": "https://software.cisco.com/download/home/286307342/type/286307754/release/6.10.2", + "filename": "FlowCollector-NetFlow-6.10.2-2018.03.19.2230-0.iso", + "filesize": 2430076928, + "md5sum": "e2ac83fa617ed9e073e845cedae76873", + "version": "6.10.2-2018.03.19.2230-0" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty200G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty200G.qcow2", + "filesize": 200192, + "md5sum": "d1686d2f25695dee32eab9a6f4652c7c", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco Flow Collector for NetFlow", + "port_name_format": "eth{port1}", + "product_name": "Flow Collector for NetFlow", + "product_url": "https://www.cisco.com/c/en/us/products/security/stealthwatch/index.html", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "cpus": 2, + "hda_disk_interface": "scsi", + "kvm": "require", + "options": "", + "ram": 8192 + }, + "registry_version": 4, + "status": "experimental", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Starting Flow Collector for NetFlow will start an installation of FCNF onto a blank 200GB Drive.\nDefault console username/password: sysadmin/lan1cope.\nDefault web username/password: admin/lan411cope.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "cdrom_image": "FlowCollector-NetFlow-6.10.4-2018.11.14.1757-0.iso", + "hda_disk_image": "empty200G.qcow2" + }, + "name": "6.10.4-2018.11.14.1757-0" + }, + { + "images": { + "cdrom_image": "FlowCollector-NetFlow-6.10.2-2018.03.19.2230-0.iso", + "hda_disk_image": "empty200G.qcow2" + }, + "name": "6.10.2-2018.03.19.2230-0" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "CentOS official image for self-hosted cloud", + "documentation_url": "https://wiki.centos.org/Documentation", + "images": [ + { + "download_url": "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1809.qcow2", + "filename": "CentOS-7-x86_64-GenericCloud-1809.qcow2", + "filesize": 914948096, + "md5sum": "da79108d1324b27bd1759362b82fbe40", + "version": "7-1809" + }, + { + "download_url": "https://github.com/asenci/gns3-centos-cloud-init-data/raw/master/centos-cloud-init-data.iso", + "filename": "centos-cloud-init-data.iso", + "filesize": 378880, + "md5sum": "15ca60c12db6d13b8eeae1a19613fd6e", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "CentOS Cloud Guest", + "port_name_format": "Ethernet{0}", + "product_name": "Centos Cloud", + "product_url": "https://wiki.centos.org/Cloud", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "options": "-nographic", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Username: centos\nPassword: centos", + "vendor_name": "The CentOS Project", + "vendor_url": "https://www.centos.org/", + "versions": [ + { + "images": { + "cdrom_image": "centos-cloud-init-data.iso", + "hda_disk_image": "CentOS-7-x86_64-GenericCloud-1809.qcow2" + }, + "name": "7 (1809)" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "FortiMail is a complete Secure Email Gateway offering suitable for any size organization. It provides a single solution to protect against inbound attacks - including advanced malware -, as well as outbound threats and data loss with a wide range of top-rated security capabilities.", + "documentation_url": "http://docs.fortinet.com/fortimail/admin-guides", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v60-build0126-FORTINET.out.kvm.qcow2", + "filesize": 96731136, + "md5sum": "b062636f029ff0f3d4b74451cc70b755", + "version": "6.0.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v54-build0719-FORTINET.out.kvm.qcow2", + "filesize": 97255424, + "md5sum": "e2f202efd28039a6f1f4ebb7ee69e214", + "version": "5.4.5" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v54-build0714-FORTINET.out.kvm.qcow2", + "filesize": 93519872, + "md5sum": "6a3155d9cee6af3ecb016e59c0a0765f", + "version": "5.4.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v54-build0712-FORTINET.out.kvm.qcow2", + "filesize": 93454336, + "md5sum": "977effe7b885ca5cedec7740a2a637aa", + "version": "5.4.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v54-build0707-FORTINET.out.kvm.qcow2", + "filesize": 92864512, + "md5sum": "b51260cc3e408bf1352a204b8370254b", + "version": "5.4.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v54-build0704-FORTINET.out.kvm.qcow2", + "filesize": 94568448, + "md5sum": "1f6553e182512cc87e20f47cc2b65abf", + "version": "5.4.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v54-build0692-FORTINET.out.kvm.qcow2", + "filesize": 101253120, + "md5sum": "c9e0885cab65e52ab01d8143ed466b01", + "version": "5.4.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0653-FORTINET.out.kvm.qcow2", + "filesize": 89980928, + "md5sum": "aed4dcb17de047860736d8742362a754", + "version": "5.3.12" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0648-FORTINET.out.kvm.qcow2", + "filesize": 88670208, + "md5sum": "bd34a81c1bb6772c7e4919620027a5d4", + "version": "5.3.11" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0643-FORTINET.out.kvm.qcow2", + "filesize": 88801280, + "md5sum": "08f3258533ac2b4f15e86ca3973be17e", + "version": "5.3.10" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0634-FORTINET.out.kvm.qcow2", + "filesize": 86376448, + "md5sum": "a66b82f0713ba4ea418bd959d0cb5732", + "version": "5.3.9" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0627-FORTINET.out.kvm.qcow2", + "filesize": 86769664, + "md5sum": "83108e5cb68bad681b68ec1ef7e29f25", + "version": "5.3.8" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0623-FORTINET.out.kvm.qcow2", + "filesize": 86573056, + "md5sum": "7e208d04c3f9bc4dedcf6d45e8d99a76", + "version": "5.3.7" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0621-FORTINET.out.kvm.qcow2", + "filesize": 86638592, + "md5sum": "3fe1521b73af886359d78eb4c1509466", + "version": "5.3.6" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0618-FORTINET.out.kvm.qcow2", + "filesize": 86376448, + "md5sum": "5f4159956b87538c008654c030e00e37", + "version": "5.3.5" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0608-FORTINET.out.kvm.qcow2", + "filesize": 86048768, + "md5sum": "b78f647148923e1bddfa2dcfbcc0c85c", + "version": "5.3.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0599-FORTINET.out.kvm.qcow2", + "filesize": 84606976, + "md5sum": "f1f3ae5593029d4fc0a5024bcf786cc7", + "version": "5.3.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FML_VMKV-64-v53-build0593-FORTINET.out.kvm.qcow2", + "filesize": 84541440, + "md5sum": "0447819ed4aa382ea6871c0cb913b592", + "version": "5.3.2" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiMail", + "port_name_format": "Port{port1}", + "product_name": "FortiMail", + "product_url": "http://www.fortinet.com/products/fortimail/index.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "First boot takes a few minutes. Admin URL is https://x.x.x.x/admin, default username is admin, no password is set.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FML_VMKV-64-v60-build0126-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.3" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v54-build0719-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.5" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v54-build0714-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.4" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v54-build0712-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.3" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v54-build0707-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.2" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v54-build0704-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.1" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v54-build0692-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.0" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0653-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.12" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0648-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.11" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0643-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.10" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0634-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.9" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0627-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.8" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0623-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.7" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0621-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.6" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0618-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.5" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0608-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.4" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0599-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.3" + }, + { + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0593-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.3.2" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Check Point Gaia is the next generation Secure Operating System for all Check Point Appliances, Open Servers and Virtualized Gateways.\n\nGaia combines the best features from IPSO and SecurePlatform (SPLAT) into a single unified OS providing greater efficiency and robust performance. By upgrading to Gaia, customers will benefit from improved appliance connection capacity and reduced operating costs. With Gaia, IP Appliance customers will gain the ability to leverage the full breadth and power of all Check Point Software Blades.\n\nGaia secures IPv6 networks utilizing the Check Point Acceleration & Clustering technology and it protects the most dynamic network and virtualized environments by supporting 5 different dynamic routing protocols. As a 64-Bit OS, Gaia increases the connection capacity of existing appliances supporting up-to 10M concurrent connections for select 2012 Models.\n\nGaia simplifies management with segregation of duties by enabling role-based administrative access. Furthermore, Gaia greatly increases operation efficiency by offering Automatic Software Update.\n\nThe feature-rich Web interface allows for search of any command or property in a second.\n\nGaia provides backward compatibility with IPSO and SPLAT CLI-style commands making it an easy transition for existing Check Point customers.", + "documentation_url": "http://downloads.checkpoint.com/dc/download.htm?ID=26770", + "images": [ + { + "download_url": "https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk104859", + "filename": "Check_Point_R80.10_T421_Gaia.iso", + "filesize": 3420127232, + "md5sum": "12d9723fadb89bb722e20ca3f89012ce", + "version": "80.10" + }, + { + "download_url": "https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk104859", + "filename": "Check_Point_R77.30_T204_Install_and_Upgrade.Gaia.iso", + "filesize": 2799271936, + "md5sum": "6fa7586bbb6832fa965d3173276c5b87", + "version": "77.30" + }, + { + "download_url": "https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk104859", + "filename": "Check_Point_R77.20_T124_Install.Gaia.iso", + "filesize": 2632974336, + "md5sum": "7552fa2ad3e1f0ac31615b60b736969c", + "version": "77.20" + }, + { + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 197120, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Checkpoint GAiA", + "product_name": "Gaia", + "qemu": { + "adapter_type": "e1000", + "adapters": 8, + "arch": "x86_64", + "boot_priority": "dc", + "console_type": "telnet", + "cpus": 2, + "kvm": "require", + "process_priority": "normal", + "ram": 4096 + }, + "registry_version": 4, + "status": "experimental", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "At boot choose the install on disk options. You need to open quickly the terminal after launching the appliance if you want to see the menu. You need a web browser in order to finalize the installation. You can use the firefox appliance for this.", + "vendor_name": "Checkpoint", + "vendor_url": "https://www.checkpoint.com", + "versions": [ + { + "images": { + "cdrom_image": "Check_Point_R80.10_T421_Gaia.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "80.10" + }, + { + "images": { + "cdrom_image": "Check_Point_R77.30_T204_Install_and_Upgrade.Gaia.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "77.30" + }, + { + "images": { + "cdrom_image": "Check_Point_R77.20_T124_Install.Gaia.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "77.20" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "The on-premise Mail and Directory server. Native compatibility with Microsoft Active Directory. You can control your IT infrastructure from a single point of user management, regardless of the different offices and locations your business has. True Microsoft Outlook compatibility. Your users can continue using their favorite email clients, without any service interruptions and without having to install any plug-in or connector.", + "documentation_url": "https://wiki.zentyal.org/wiki/Zentyal_Wiki", + "images": [ + { + "direct_download_url": "http://download.zentyal.com/zentyal-6.0-development-amd64.iso", + "download_url": "http://download.zentyal.com/", + "filename": "zentyal-6.0-development-amd64.iso", + "filesize": 895483904, + "md5sum": "e1765d2c4d86debc9d9cbab2b7a8adbd", + "version": "6.0" + }, + { + "direct_download_url": "http://download.zentyal.com/zentyal-5.1-development-amd64.iso", + "download_url": "http://download.zentyal.com/", + "filename": "zentyal-5.1-development-amd64.iso", + "filesize": 947912704, + "md5sum": "dac5623b92c1b361d7805ab8c95c0d99", + "version": "5.1" + }, + { + "direct_download_url": "http://download.zentyal.com/zentyal-5.0.1-development-amd64.iso", + "download_url": "http://download.zentyal.com/", + "filename": "zentyal-5.0.1-development-amd64.iso", + "filesize": 953155584, + "md5sum": "1ac74be6563f0b21b337c274e62cdd32", + "version": "5.0.1" + }, + { + "direct_download_url": "http://download.zentyal.com/zentyal-5.0-development-amd64.iso", + "download_url": "http://download.zentyal.com/", + "filename": "zentyal-5.0-development-amd64.iso", + "filesize": 914565120, + "md5sum": "ddaa3b2bf2cd6cae8bcfbcb88ca636a8", + "version": "5.0" + }, + { + "direct_download_url": "http://download.zentyal.com/zentyal-4.2-development-amd64.iso", + "download_url": "http://download.zentyal.com/", + "filename": "zentyal-4.2-development-amd64.iso", + "filesize": 629284864, + "md5sum": "22b165a49adbc4eff033ced01e71fe3a", + "version": "4.2" + }, + { + "direct_download_url": "http://download.zentyal.com/zentyal-4.1-development-amd64.iso", + "download_url": "http://download.zentyal.com/", + "filename": "zentyal-4.1-development-amd64.iso", + "filesize": 612206592, + "md5sum": "40a8ff15a60ff862a110a17f941edf2a", + "version": "4.1" + }, + { + "direct_download_url": "http://download.zentyal.com/zentyal-4.0-amd64.iso", + "download_url": "http://download.zentyal.com/", + "filename": "zentyal-4.0-amd64.iso", + "filesize": 666370048, + "md5sum": "d63b15f1edcd2c3c03ab3a36e833e211", + "version": "4.0" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 198656, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Zentyal Server", + "port_name_format": "eth{0}", + "product_name": "Zentyal Server", + "product_url": "http://www.zentyal.com/zentyal-server/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 3, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Follow installation instructions. Once the installation process is done, you can access the web interface using a web browser: https://:8443/", + "vendor_name": "Zentyal S.L.", + "vendor_url": "http://www.zentyal.com/", + "versions": [ + { + "images": { + "cdrom_image": "zentyal-6.0-development-amd64.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "6.0" + }, + { + "images": { + "cdrom_image": "zentyal-5.1-development-amd64.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "5.1" + }, + { + "images": { + "cdrom_image": "zentyal-5.0.1-development-amd64.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "5.0.1" + }, + { + "images": { + "cdrom_image": "zentyal-5.0-development-amd64.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "5.0" + }, + { + "images": { + "cdrom_image": "zentyal-4.2-development-amd64.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "4.2" + }, + { + "images": { + "cdrom_image": "zentyal-4.1-development-amd64.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "4.1" + }, + { + "images": { + "cdrom_image": "zentyal-4.0-amd64.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "4.0" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Cisco Stealthwatch is the most comprehensive visibility and network traffic security analytics solution that uses enterprise telemetry from the existing network infrastructure. It provides advanced threat detection, accelerated threat response, and simplified network segmentation using multilayer machine learning and entity modeling. With advanced behavioral analytics, you\u2019ll always know who is on your network and what they are doing.\n\nUsing the same technology as the Stealthwatch Flow Sensor appliance, the Flow Sensor VE is a virtual appliance that provides visibility into virtual environments, generating flow data for areas that are not flow-enabled. ", + "documentation_url": "https://www.cisco.com/c/en/us/support/security/stealthwatch/tsd-products-support-series-home.html", + "first_port_name": "eth0", + "images": [ + { + "download_url": "https://software.cisco.com/download/home/286307342/type/286307754/release/6.10.2", + "filename": "FlowSensor-AE-6.10.2-2018.03.19.2224-0.iso", + "filesize": 1287245824, + "md5sum": "ef8712e655fcbc92dc1a1551ee2e4a80", + "version": "6.10.2-2018.03.19.2224-0" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 198656, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco Flow Sensor", + "port_name_format": "eth{port1}", + "product_name": "Flow Sensor VE", + "product_url": "https://www.cisco.com/c/en/us/products/security/stealthwatch/index.html", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "cpus": 1, + "hda_disk_interface": "scsi", + "kvm": "require", + "options": "", + "ram": 8192 + }, + "registry_version": 4, + "status": "experimental", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Starting Flow Sensor will start an installation of FSVE onto a blank 100GB Drive.\nDefault console username/password: sysadmin/lan1cope.\nDefault web username/password: admin/lan411cope.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "cdrom_image": "FlowSensor-AE-6.10.2-2018.03.19.2224-0.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "6.10.2-2018.03.19.2224-0" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Core Linux is a smaller variant of Tiny Core without a graphical desktop.\n\nIt's provide a complete Linux system in few MB.", + "documentation_url": "http://wiki.tinycorelinux.net/", + "images": [ + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-tinycore-linux-6.4-2.img", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "linux-tinycore-6.4-2.img", + "filesize": 36503552, + "md5sum": "dcbb5318c3e18ab085088d4474d8de85", + "version": "6.4" + }, + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-tinycore-linux-6.4.img", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "linux-tinycore-6.4.img", + "filesize": 22544384, + "md5sum": "e3de478780c0acb76ef92f872fe734c4", + "version": "6.4" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Tiny Core Linux", + "product_name": "Tiny Core Linux", + "product_url": "http://distro.ibiblio.org/tinycorelinux", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "i386", + "console_type": "vnc", + "kvm": "allow", + "options": "-vga std -usbdevice tablet", + "ram": 96 + }, + "registry_version": 3, + "status": "stable", + "symbol": "linux_guest.svg", + "usage": "Login is gns3/gns3. sudo works without password", + "vendor_name": "Team Tiny Core", + "vendor_url": "http://distro.ibiblio.org/tinycorelinux", + "versions": [ + { + "images": { + "hda_disk_image": "linux-tinycore-6.4-2.img" + }, + "name": "6.4~2" + }, + { + "images": { + "hda_disk_image": "linux-tinycore-6.4.img" + }, + "name": "6.4~1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Container with integrated Python 2 & 3, Perl, PHP, and PHP7.0 interpreters, and a Go compiler.", + "docker": { + "adapters": 1, + "image": "adosztal/python-go-perl-php:latest" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Python, Go, Perl, PHP", + "product_name": "Python, Go, Perl, PHP", + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/docker_guest.svg", + "vendor_name": "GNS3 Team", + "vendor_url": "https://www.gns3.com" + }, + { + "builtin": true, + "category": "guest", + "description": "The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, machine learning and much more.", + "docker": { + "adapters": 1, + "console_http_path": "/", + "console_http_port": 8888, + "console_type": "http", + "image": "gns3/jupyter:v2" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Jupyter", + "product_name": "Jupyter", + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/docker_guest.svg", + "vendor_name": "Project Jupyter", + "vendor_url": "http://jupyter.org/" + }, + { + "builtin": true, + "category": "router", + "description": "OpenWrt is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers). Unlike many other distributions for these routers, OpenWrt is built from the ground up to be a full-featured, easily modifiable operating system for your router. In practice, this means that you can have all the features you need with none of the bloat, powered by a Linux kernel that's more recent than most other distributions.\n\nThe realview platform is meant for use with QEMU for emulating an ARM system.", + "documentation_url": "http://wiki.openwrt.org/doc/", + "images": [ + { + "direct_download_url": "http://downloads.openwrt.org/chaos_calmer/15.05.1/realview/generic/openwrt-15.05.1-realview-vmlinux-initramfs.elf", + "download_url": "http://downloads.openwrt.org/chaos_calmer/15.05.1/realview/generic/", + "filename": "openwrt-15.05.1-realview-vmlinux-initramfs.elf", + "filesize": 2278696, + "md5sum": "3660b9de654cf03f2a50997ae89c2daf", + "version": "15.05.1" + }, + { + "direct_download_url": "http://downloads.openwrt.org/barrier_breaker/14.07/realview/generic/openwrt-realview-vmlinux-initramfs.elf", + "download_url": "http://downloads.openwrt.org/barrier_breaker/14.07/realview/generic/", + "filename": "openwrt-realview-vmlinux-initramfs-14.07.elf", + "filesize": 2183520, + "md5sum": "2411307d0794baa618537c5dfcb19575", + "version": "14.07" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "OpenWrt Realview", + "product_name": "OpenWrt", + "product_url": "http://openwrt.org", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "arm", + "console_type": "telnet", + "kvm": "allow", + "options": "-M realview-eb-mpcore", + "ram": 128 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "OpenWrt", + "vendor_url": "http://openwrt.org", + "versions": [ + { + "images": { + "kernel_image": "openwrt-15.05.1-realview-vmlinux-initramfs.elf" + }, + "name": "Chaos Calmer 15.05.1" + }, + { + "images": { + "kernel_image": "openwrt-realview-vmlinux-initramfs-14.07.elf" + }, + "name": "Barrier Breaker 14.07" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "webterm is a debian based networking toolbox.\nIt contains the firefox web browser plus the following utilities: net-tools, iproute2, ping, traceroute, curl, host, iperf3, mtr, socat, ssh client, tcpdump, ab(apache benchmark) and the multicast testing tools msend/mreceive.", + "docker": { + "adapters": 1, + "console_type": "vnc", + "image": "gns3/webterm:latest" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "webterm", + "product_name": "webterm", + "registry_version": 3, + "status": "stable", + "symbol": "firefox.svg", + "usage": "The /root directory is persistent.", + "vendor_name": "webterm", + "vendor_url": "https://www.debian.org" + }, + { + "builtin": true, + "category": "guest", + "description": "FortiAnalyzer Network Security Logging, Analysis, and Reporting Appliances securely aggregate log data from Fortinet Security Appliances. A comprehensive suite of easily customable reports allows you to quickly analyze and visualize network threats, inefficiencies and usage.", + "documentation_url": "http://docs.fortinet.com/fortianalyzer/", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2", + "filesize": 114589696, + "md5sum": "14c98b20ed1d0729e2d04aad49ff1be5", + "version": "6.0.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v6-build0205-FORTINET.out.kvm.qcow2", + "filesize": 115777536, + "md5sum": "1c9c6a99244aaf8b215c52194e1f82ed", + "version": "6.0.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v6-build0092-FORTINET.out.kvm.qcow2", + "filesize": 117940224, + "md5sum": "e870087db55a095c75ddcafe73e1ea27", + "version": "6.0.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build1782-FORTINET.out.kvm.qcow2", + "filesize": 110862336, + "md5sum": "f67c115cc51e911802e9cbcb5cb0c8c2", + "version": "5.6.7" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build1631-FORTINET.out.kvm.qcow2", + "filesize": 105816064, + "md5sum": "c7f1cf26051b50b86e7e59b99e36756f", + "version": "5.6.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build1619-FORTINET.out.kvm.qcow2", + "filesize": 105705472, + "md5sum": "1bd94c920f8747de671832ef92e8dfbc", + "version": "5.6.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build1557-FORTINET.out.kvm.qcow2", + "filesize": 106905600, + "md5sum": "6aa0a185723efcab464aa298b364d12b", + "version": "5.6.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build1225-FORTINET.out.kvm.qcow2", + "filesize": 88715264, + "md5sum": "69cddb5c3e49bab3dc287353d8600b45", + "version": "5.4.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build1187-FORTINET.out.kvm.qcow2", + "filesize": 86036480, + "md5sum": "4f9fa1e7dbfa9187a4cb479458144596", + "version": "5.4.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build1151-FORTINET.out.kvm.qcow2", + "filesize": 85651456, + "md5sum": "c4f7bf355c7483f23edd4f6bf34bc602", + "version": "5.4.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build1082-FORTINET.out.kvm.qcow2", + "filesize": 81580032, + "md5sum": "e9bae3fc7195200f659178060968c7c4", + "version": "5.4.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build1019-FORTINET.out.kvm.qcow2", + "filesize": 66256896, + "md5sum": "72530309422616a1a1478fa0c78fbb08", + "version": "5.4.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build0786-FORTINET.out.kvm.qcow2", + "filesize": 55238656, + "md5sum": "b9553e0f1cfc875d2121c840a1fafebc", + "version": "5.2.10" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build0780-FORTINET.out.kvm.qcow2", + "filesize": 55042048, + "md5sum": "e79581adb9ac36913823f0119a1c8da8", + "version": "5.2.9" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build0777-FORTINET.out.kvm.qcow2", + "filesize": 55361536, + "md5sum": "9a061657c3fdac9e9b631621a100cdc8", + "version": "5.2.8" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAZ_VM64_KVM-v5-build0760-FORTINET.out.kvm.qcow2", + "filesize": 55070720, + "md5sum": "a349f4d9f4f12e8963e3b471357dcbb6", + "version": "5.2.7" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiAnalyzer", + "port_name_format": "Port{port1}", + "product_name": "FortiAnalyzer", + "product_url": "https://www.fortinet.com/products-services/products/management-reporting/fortianalyzer.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "Default username is admin, no password is set.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.3" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v6-build0205-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.2" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v6-build0092-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.0" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1782-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.7" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1631-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.2" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1619-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.1" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1557-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.0" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1225-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.4" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1187-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.3" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1151-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.2" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1082-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.1" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1019-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.0" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build0786-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.10" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build0780-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.9" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build0777-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.8" + }, + { + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build0760-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.7" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Today\u2019s enterprises face more demands than ever, from cloud computing to 24/7 availability to increasing security threats. NetScaler ADC, an advanced software-defined application delivery controller, is your networking power player. It provides outstanding delivery of business applications\u2014to any device and any location\u2014with unmatched security, superior L4-7 load balancing, reliable GSLB, and 100 percent uptime. In fact, NetScaler ADC offers up to five times the performance of our closest competitor. Plus our TriScale technology saves you money by allowing your network to scale up or down without additional hardware costs.", + "documentation_url": "https://www.citrix.com/products/netscaler-adc/support.html", + "images": [ + { + "download_url": "https://www.citrix.com/lp/try/netscaler-vpx-express.html", + "filename": "NSVPX-KVM-12.0-56.20_nc_32.qcow2", + "filesize": 739704832, + "md5sum": "0ea1c23e3b8eb8451037d46ee472cfa6", + "version": "12.0-56.20" + }, + { + "download_url": "https://www.citrix.com/downloads/netscaler-adc/virtual-appliances/netscaler-vpx-express.html", + "filename": "NSVPX-KVM-11.1-47.14_nc.raw", + "filesize": 21474836480, + "md5sum": "f7100f8b6588e152ce6f64e45b1e99fc", + "version": "11.1-47.14 F" + }, + { + "download_url": "https://www.citrix.com/downloads/netscaler-adc/virtual-appliances/netscaler-vpx-express.html", + "filename": "NSVPX-KVM-10.5-56.22_nc.raw", + "filesize": 21474836480, + "md5sum": "b7569f09d4c348c5cf825627169131e7", + "version": "10.5-56.22" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "NetScaler VPX", + "port_name_format": "1/{0}", + "product_name": "NetScaler VPX", + "product_url": "https://www.citrix.com/products/netscaler-adc/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "telnet", + "hda_disk_interface": "ide", + "kvm": "require", + "options": "-smp 2 -cpu host", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "loadbalancer.svg", + "usage": "The image file is large (21.5 GB), make sure you have enough space. Default credentials: nsroot / nsroot", + "vendor_name": "Citrix", + "vendor_url": "http://www.citrix.com/", + "versions": [ + { + "images": { + "hda_disk_image": "NSVPX-KVM-12.0-56.20_nc_32.qcow2" + }, + "name": "12.0-56.20" + }, + { + "images": { + "hda_disk_image": "NSVPX-KVM-11.1-47.14_nc.raw" + }, + "name": "11.1-47.14 F" + }, + { + "images": { + "hda_disk_image": "NSVPX-KVM-10.5-56.22_nc.raw" + }, + "name": "10.5-56.22" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "The BIRD project aims to develop a fully functional dynamic IP routing daemon primarily targeted on (but not limited to) Linux, FreeBSD and other UNIX-like systems and distributed under the GNU General Public License.", + "documentation_url": "http://bird.network.cz/?get_doc&f=bird.html", + "images": [ + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/bird-tinycore64-1.5.0.img", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "bird-tinycore64-1.5.0.img", + "filesize": 22413312, + "md5sum": "08d50ba2b1b262e2e03e4babf90abf69", + "version": "1.5.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "BIRD", + "product_name": "BIRD internet routing daemon", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "allow", + "ram": 128 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "Configure interfaces in /opt/bootlocal.sh, BIRD configuration is done in /usr/local/etc/bird", + "vendor_name": "CZ.NIC Labs", + "vendor_url": "http://bird.network.cz/", + "versions": [ + { + "images": { + "hda_disk_image": "bird-tinycore64-1.5.0.img" + }, + "name": "1.5.0" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Over 200,000 IT staff across medium to large enterprises worldwide are currently using OP5 Monitor as their preferred network monitoring software.\nOP5 Monitor allows you to take control of your IT, enabling your network to be more responsive, more reliable and even faster than ever before. With unparalleled scalability, OP5 Monitor grows as your company grows, so you\u2019ll understand why we say this is the last network monitor you\u2019ll ever need to purchase.", + "documentation_url": "https://kb.op5.com/display/MAN/Documentation+Home#sthash.pohb5bis.dpbs", + "images": [ + { + "download_url": "https://www.op5.com/download/", + "filename": "op5-Monitor-Virtual-Appliance-7.4.10.x86_64-disk1.vmdk", + "filesize": 1111941120, + "md5sum": "48ec6d7ee3809d9ed705a089c679e076", + "version": "7.4.10" + }, + { + "download_url": "https://www.op5.com/download/", + "filename": "op5-Monitor-Virtual-Appliance-7.3.15.x86_64.vmdk", + "filesize": 779687424, + "md5sum": "634acc6266237d99bf1bfbcf9284beca", + "version": "7.3.15" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "OP5 Monitor", + "port_name_format": "eth{0}", + "product_name": "OP5 Monitor", + "product_url": "https://www.op5.com/op5-monitor/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": "mgmt_station.svg", + "usage": "Interface eth0 is set to DHCP. Default credentials:\n- CLI: root / monitor\n- Web access: admin / monitor\n- Logserver Extension: admin / admin", + "vendor_name": "OP5", + "vendor_url": "https://www.op5.com/", + "versions": [ + { + "images": { + "hda_disk_image": "op5-Monitor-Virtual-Appliance-7.4.10.x86_64-disk1.vmdk" + }, + "name": "7.4.10" + }, + { + "images": { + "hda_disk_image": "op5-Monitor-Virtual-Appliance-7.3.15.x86_64.vmdk" + }, + "name": "7.3.15" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "DEFT (acronym for Digital Evidence & Forensics Toolkit) is a distribution made for Computer Forensics, with the purpose of running live on systems without tampering or corrupting devices (hard disks, pendrives, etc\u2026) connected to the PC where the boot process takes place.\nThe DEFT system is based on GNU Linux, it can run live (via DVDROM or USB pendrive), installed or run as a Virtual Appliance on VMware or Virtualbox. DEFT employs LXDE as desktop environment and WINE for executing Windows tools under Linux. It features a comfortable mount manager for device management.\nDEFT is paired with DART (acronym for Digital Advanced Response Toolkit), a Forensics System which can be run on Windows and contains the best tools for Forensics and Incident Response. DART features a GUI with logging and integrity check for the instruments here contained.\nBesides all this, the DEFT staff is devoted to implementing and developing applications which are released to Law Enforcement Officers, such as Autopsy 3 for Linux.", + "documentation_url": "http://www.deftlinux.net/deft-manual/", + "images": [ + { + "direct_download_url": "http://na.mirror.garr.it/mirrors/deft/deft-8.2.iso", + "download_url": "http://www.deftlinux.net/download/", + "filename": "deft-8.2.iso", + "filesize": 3317876736, + "md5sum": "8a70f61507251355153cbe94809323dd", + "version": "8.2" + }, + { + "direct_download_url": "http://na.mirror.garr.it/mirrors/deft/deft-8.1.iso", + "download_url": "http://www.deftlinux.net/download/", + "filename": "deft-8.1.iso", + "filesize": 3267639296, + "md5sum": "76bad80c7ea1552c9bd97bcca5de8d50", + "version": "8.1" + }, + { + "direct_download_url": "http://na.mirror.garr.it/mirrors/deft/deft-8.0.iso", + "download_url": "http://www.deftlinux.net/download/", + "filename": "deft-8.0.iso", + "filesize": 2898477056, + "md5sum": "fcedb54176de7a3018adfa7571a3a626", + "version": "8.0" + }, + { + "direct_download_url": "http://na.mirror.garr.it/mirrors/deft/deft-7.2.iso", + "download_url": "http://www.deftlinux.net/download/", + "filename": "deft-7.2.iso", + "filesize": 2695090176, + "md5sum": "1ea8ec6a2d333d0f0a64656bdf595a28", + "version": "7.2" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "DEFT Linux", + "product_name": "DEFT Linux", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "You can run the LiveCD or install to the local disk. Default root password: deft", + "vendor_name": "DEFT Association", + "vendor_url": "http://www.deftlinux.net/", + "versions": [ + { + "images": { + "cdrom_image": "deft-8.2.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "8.2" + }, + { + "images": { + "cdrom_image": "deft-8.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "8.1" + }, + { + "images": { + "cdrom_image": "deft-8.0.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "8.0" + }, + { + "images": { + "cdrom_image": "deft-7.2.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "7.2" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "NETem emulates a network link, typically a WAN link. It supports bandwidth limitation, delay, jitter and packet loss. All this functionality is already build in the linux kernel, NETem is just a menu system to make the configuration user-friendly.", + "documentation_url": "http://www.cs.unm.edu/~crandall/netsfall13/TCtutorial.pdf", + "images": [ + { + "direct_download_url": "http://bernhard-ehlers.de/projects/netem/NETem-v4.qcow2", + "download_url": "http://bernhard-ehlers.de/projects/netem/index.html", + "filename": "NETem-v4.qcow2", + "filesize": 26476544, + "md5sum": "e678698c97804901c7a53f6b68c8b861", + "version": "0.4" + } + ], + "maintainer": "Bernhard Ehlers", + "maintainer_email": "be@bernhard-ehlers.de", + "name": "NETem", + "port_name_format": "eth{0}", + "product_name": "netem", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "i386", + "console_type": "telnet", + "kvm": "allow", + "options": "-nographic", + "ram": 96 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Insert the NETem VM between two network elements and connect it to them. NETem is fully transparent, it bridges the traffic from one interface to the other one. As NETem only bridges, it needs no IP addresses. On start a menu on the console allows a user-friendy configuration of the line parameters.", + "vendor_name": "Linux", + "vendor_url": "http://www.linuxfoundation.org/", + "versions": [ + { + "images": { + "hda_disk_image": "NETem-v4.qcow2" + }, + "name": "0.4" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "The term 'Ubuntu Cloud Guest' refers to the Official Ubuntu images that are available at http://cloud-images.ubuntu.com . These images are built by Canonical. They are then registered on EC2, and compressed tarfiles are made also available for download. For using those images on a public cloud such as Amazon EC2, you simply choose an image and launch it. To use those images on a private cloud, or to run the image on a local hypervisor (such as KVM) you would need to download those images and either publish them to your private cloud, or launch them directly on a hypervisor. The following sections explain in more details how to perform each of those actions", + "documentation_url": "https://help.ubuntu.com/community/UEC/Images", + "images": [ + { + "download_url": "https://cloud-images.ubuntu.com/releases/18.04/release-20180426.2/ubuntu-18.04-server-cloudimg-amd64.img", + "filename": "ubuntu-18.04-server-cloudimg-amd64.img", + "filesize": 336134144, + "md5sum": "f4134e7fa16d7fa766c7467cbe25c949", + "version": "18.04" + }, + { + "download_url": "https://cloud-images.ubuntu.com/releases/17.10/release-20180404/ubuntu-17.10-server-cloudimg-amd64.img", + "filename": "ubuntu-17.10-server-cloudimg-amd64.img", + "filesize": 320405504, + "md5sum": "331b44f2b05858c251b3ea92c8b65152", + "version": "17.10" + }, + { + "download_url": "https://cloud-images.ubuntu.com/releases/16.04/release-20180405/ubuntu-16.04-server-cloudimg-amd64-disk1.img", + "filename": "ubuntu-16.04-server-cloudimg-amd64-disk1.img", + "filesize": 290193408, + "md5sum": "22c124ba65ea096cdef8b0a197dd613a", + "version": "16.04" + }, + { + "download_url": "https://cloud-images.ubuntu.com/releases/14.04/release-20180404/ubuntu-14.04-server-cloudimg-amd64-disk1.img", + "filename": "ubuntu-14.04-server-cloudimg-amd64-disk1.img", + "filesize": 262668800, + "md5sum": "d11b89321d41d0eeddcacf73bf0d2262", + "version": "14.04" + }, + { + "download_url": "https://github.com/asenci/gns3-ubuntu-cloud-init-data/raw/master/ubuntu-cloud-init-data.iso", + "filename": "ubuntu-cloud-init-data.iso", + "filesize": 131072, + "md5sum": "328469100156ae8dbf262daa319c27ff", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Ubuntu Cloud Guest", + "port_name_format": "Ethernet{0}", + "product_name": "Ubuntu Cloud Guest", + "product_url": "https://www.ubuntu.com/cloud", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "options": "-nographic", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Username: ubuntu\nPassword: ubuntu", + "vendor_name": "Canonical Inc.", + "vendor_url": "https://www.ubuntu.com", + "versions": [ + { + "images": { + "cdrom_image": "ubuntu-cloud-init-data.iso", + "hda_disk_image": "ubuntu-18.04-server-cloudimg-amd64.img" + }, + "name": "18.04 (LTS)" + }, + { + "images": { + "cdrom_image": "ubuntu-cloud-init-data.iso", + "hda_disk_image": "ubuntu-17.10-server-cloudimg-amd64.img" + }, + "name": "17.10" + }, + { + "images": { + "cdrom_image": "ubuntu-cloud-init-data.iso", + "hda_disk_image": "ubuntu-16.04-server-cloudimg-amd64-disk1.img" + }, + "name": "16.04 (LTS)" + }, + { + "images": { + "cdrom_image": "ubuntu-cloud-init-data.iso", + "hda_disk_image": "ubuntu-14.04-server-cloudimg-amd64-disk1.img" + }, + "name": "14.04 (LTS)" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "IOS XRv 9000 (aka Sunstone) is the 1st VM released running the 64-bit IOS XR operating system as used on the NCS-6xxx platform. This appliance requires 4 vCPUs and 16GB of memory to run!", + "documentation_url": "http://www.cisco.com/c/en/us/td/docs/ios_xr_sw/ios_xrv/release/notes/xrv-rn.html", + "first_port_name": "MgmtEth0/0/CPU0/0", + "images": [ + { + "download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.5.1", + "filename": "xrv9k-fullk9-x-6.5.1.qcow2", + "filesize": 1208811520, + "md5sum": "730868e7cd46de9aa2e950899c7f9498", + "version": "6.5.1" + }, + { + "download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.4.2", + "filename": "xrv9k-fullk9-x-6.4.2.qcow2", + "filesize": 1311703040, + "md5sum": "6958763192c7bb59a1b8049d377de1b4", + "version": "6.4.2" + }, + { + "download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.4.1", + "filename": "xrv9k-fullk9-x-6.4.1.qcow2", + "filesize": 1304887296, + "md5sum": "9c56b684e307706005a503e289cb9317", + "version": "6.4.1" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "xrv9k-fullk9-x-6.2.25.qcow2", + "filesize": 1190723584, + "md5sum": "3f54e62b6f7cedfb2607233e5e465766", + "version": "6.2.25" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "xrv9k-fullk9-x.qcow2-6.0.1", + "filesize": 2109210624, + "md5sum": "e20d046807075046c35b6ce7d6766a7f", + "version": "6.0.1" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "xrv9k-fullk9-x.qcow2-6.0.0", + "filesize": 2572943360, + "md5sum": "64c538c34252aaeb4ed1ddb93d6803fd", + "version": "6.0.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco IOS XRv 9000", + "port_name_format": "NIC{0}", + "product_name": "IOS XRv 9000", + "product_url": "http://virl.cisco.com/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 7, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "options": "-smp 4 -cpu host", + "ram": 16384 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "usage": "Default username/password: admin/admin, cisco/cisco and lab/lab. There is no default configuration present. Interfaces may take several minutes to be usable after appliance boot.\n\nThe interfaces are mapped the following way:\n- NIC0: unused\n- NIC1: unused\n- NIC2: Gi0/0/0/0\n- NIC3: Gi0/0/0/1\n- NICn: Gi0/0/0/(n-2)", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "xrv9k-fullk9-x-6.5.1.qcow2" + }, + "name": "6.5.1" + }, + { + "images": { + "hda_disk_image": "xrv9k-fullk9-x-6.4.2.qcow2" + }, + "name": "6.4.2" + }, + { + "images": { + "hda_disk_image": "xrv9k-fullk9-x-6.4.1.qcow2" + }, + "name": "6.4.1" + }, + { + "images": { + "hda_disk_image": "xrv9k-fullk9-x-6.2.25.qcow2" + }, + "name": "6.2.25" + }, + { + "images": { + "hda_disk_image": "xrv9k-fullk9-x.qcow2-6.0.1" + }, + "name": "6.0.1" + }, + { + "images": { + "hda_disk_image": "xrv9k-fullk9-x.qcow2-6.0.0" + }, + "name": "6.0.0" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Junos Space Network Management Platform works with Juniper's management applications to simplify and automate management of Juniper's switching, routing, and security devices. As part of a complete solution, the platform provides broad fault, configuration, accounting, performance, and security management (FCAPS) capability, same day support for new devices and Junos OS releases, a task-specific user interface, and northbound APIs for integration with existing network management systems (NMS) or operations/business support systems (OSS/BSS).\n\nThe platform helps network operators at enterprises and service providers scale operations, reduce complexity, and enable new applications and services to be brought to market quickly, through multilayered network abstractions, operator-centric automation schemes, and a simple point-and-click UI.", + "documentation_url": "http://www.juniper.net/techpubs/", + "images": [ + { + "download_url": "https://www.juniper.net/support/downloads/?p=space#sw", + "filename": "space-17.2R1.4.qcow2", + "filesize": 5150474240, + "md5sum": "4124fa756c3a78be0619e876b8ee687e", + "version": "17.2R1.4" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Junos Space", + "port_name_format": "em{0}", + "product_name": "Junos Space", + "product_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "options": "-smp 4 -nographic", + "ram": 16384 + }, + "registry_version": 3, + "status": "stable", + "symbol": "juniper-vqfx.svg", + "usage": "16 GB RAM is the bare minimum; you should use 32/64 GB in production deplyments.\nDefault credentials:\n- CLI: admin / abc123\n- WebUI: super / juniper123", + "vendor_name": "Juniper", + "vendor_url": "https://www.juniper.net/us/en/", + "versions": [ + { + "images": { + "hda_disk_image": "space-17.2R1.4.qcow2" + }, + "name": "17.2R1.4" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco 2600 Router", + "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", + "dynamips": { + "chassis": "2610", + "nvram": 128, + "platform": "c2600", + "ram": 160, + "startup_config": "ios_base_startup-config.txt" + }, + "images": [ + { + "filename": "c2600-adventerprisek9-mz.124-15.T14.image", + "filesize": 87256400, + "md5sum": "483e3a579a5144ec23f2f160d4b0c0e2", + "version": "124-15.T14" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco 2600", + "product_name": "2600", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "idlepc": "0x8027ec88", + "images": { + "image": "c2600-adventerprisek9-mz.124-15.T14.image" + }, + "name": "124-15.T14" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Protect your network from viruses, malware and malicious activity with Kerio Control, the easy-to-administer yet powerful all-in-one security solution.\nKerio Control brings together next-generation firewall capabilities - including a network firewall and router, intrusion detection and prevention (IPS), gateway anti-virus, VPN, and web content and application filtering. These comprehensive capabilities and unmatched deployment flexibility make Kerio Control the ideal choice for small and mid-sized businesses.", + "documentation_url": "http://kb.kerio.com/product/kerio-control/", + "images": [ + { + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.7-2921/kerio-control-appliance-9.2.7-2921-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-control", + "filename": "kerio-control-appliance-9.2.7-2921-vmware-disk1.vmdk", + "filesize": 191135232, + "md5sum": "d286a240be53f8dd9da5f80deb9086b0", + "version": "9.2.7" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.5-2641/kerio-control-appliance-9.2.5-2641-p5-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-control", + "filename": "kerio-control-appliance-9.2.5-2641-p5-vmware-disk1.vmdk", + "filesize": 190706688, + "md5sum": "fbb2824eb91ca2502c952c2e9c4e635d", + "version": "9.2.5p5" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.4-2223/kerio-control-appliance-9.2.4-2223-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-control", + "filename": "kerio-control-appliance-9.2.4-2223-vmware-disk1.vmdk", + "filesize": 191687168, + "md5sum": "20970f3638c7ca5603c2afbe56e89421", + "version": "9.2.4" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.3-2219/kerio-control-appliance-9.2.3-2219-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-control", + "filename": "kerio-control-appliance-9.2.3-2219-vmware-disk1.vmdk", + "filesize": 191716352, + "md5sum": "767d5b25bdca2b45c2ba269189ea9bd0", + "version": "9.2.3" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.2-2172/kerio-control-appliance-9.2.2-2172-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-control", + "filename": "kerio-control-appliance-9.2.2-2172-vmware-disk1.vmdk", + "filesize": 190841856, + "md5sum": "4efeacbc39db1b3e53ef96af1338cf52", + "version": "9.2.2" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.1-2019/kerio-control-appliance-9.2.1-2019-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-control", + "filename": "kerio-control-appliance-9.2.1-2019-vmware-disk1.vmdk", + "filesize": 254364160, + "md5sum": "0405890e323e29a4808ec288600875ba", + "version": "9.2.1" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.1.4-1535/kerio-control-appliance-9.1.4-1535-vmware.vmdk", + "download_url": "http://www.kerio.com/support/kerio-control", + "filename": "kerio-control-appliance-9.1.4-1535-vmware.vmdk", + "filesize": 483459072, + "md5sum": "5ea5a7f103b1f008d4c24444400333ec", + "version": "9.1.4" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Kerio Control", + "port_name_format": "eth{0}", + "product_name": "Kerio Control", + "product_url": "http://www.kerio.com/products/kerio-control", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 4096 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "vendor_name": "Kerio Technologies Inc.", + "vendor_url": "http://www.kerio.com", + "versions": [ + { + "images": { + "hda_disk_image": "kerio-control-appliance-9.2.7-2921-vmware-disk1.vmdk" + }, + "name": "9.2.7" + }, + { + "images": { + "hda_disk_image": "kerio-control-appliance-9.2.5-2641-p5-vmware-disk1.vmdk" + }, + "name": "9.2.5p5" + }, + { + "images": { + "hda_disk_image": "kerio-control-appliance-9.2.4-2223-vmware-disk1.vmdk" + }, + "name": "9.2.4" + }, + { + "images": { + "hda_disk_image": "kerio-control-appliance-9.2.3-2219-vmware-disk1.vmdk" + }, + "name": "9.2.3" + }, + { + "images": { + "hda_disk_image": "kerio-control-appliance-9.2.2-2172-vmware-disk1.vmdk" + }, + "name": "9.2.2" + }, + { + "images": { + "hda_disk_image": "kerio-control-appliance-9.2.1-2019-vmware-disk1.vmdk" + }, + "name": "9.2.1" + }, + { + "images": { + "hda_disk_image": "kerio-control-appliance-9.1.4-1535-vmware.vmdk" + }, + "name": "9.1.4" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "Cisco IOS on UNIX Layer 2 image.", + "images": [ + { + "filename": "i86bi-linux-l2-ipbasek9-15.1g.bin", + "filesize": 62137336, + "md5sum": "0b8b9e14ca99b68c654e44c4296857ba", + "version": "15.1g" + }, + { + "filename": "i86bi-linux-l2-adventerprisek9-15.1a.bin", + "filesize": 72726092, + "md5sum": "9549a20a7391fb849da32caa77a0d254", + "version": "15.1a" + }, + { + "filename": "i86bi-linux-l2-adventerprisek9-15.2d.bin", + "filesize": 105036380, + "md5sum": "f16db44433beb3e8c828db5ddad1de8a", + "version": "15.2d" + } + ], + "iou": { + "ethernet_adapters": 4, + "nvram": 128, + "ram": 256, + "serial_adapters": 0, + "startup_config": "iou_l2_base_startup-config.txt" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco IOU L2", + "product_name": "Cisco IOU L2", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "images": { + "image": "i86bi-linux-l2-ipbasek9-15.1g.bin" + }, + "name": "15.1g" + }, + { + "images": { + "image": "i86bi-linux-l2-adventerprisek9-15.1a.bin" + }, + "name": "15.1a" + }, + { + "images": { + "image": "i86bi-linux-l2-adventerprisek9-15.2d.bin" + }, + "name": "15.2d" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Fortinet ADC appliances optimize the availability, user experience, and scalability of enterprise application delivery. They deliver fast, secure, and intelligent acceleration and distribution of even the most demanding enterprise applications.", + "documentation_url": "http://docs.fortinet.com/fortiadc-d-series/admin-guides", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-FORTINET.out.kvm-data.qcow2", + "filesize": 30998528, + "md5sum": "b7500835594e62d8acb1c6ec43d597c1", + "version": "ALL" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V500-build0423-FORTINET.out.kvm-boot.qcow2", + "filesize": 104333312, + "md5sum": "993bcd0e8e5496fdacb78dffb3c9a9b3", + "version": "5.2.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V500-build0239-FORTINET.out.kvm-boot.qcow2", + "filesize": 75235328, + "md5sum": "f94323bc6415dd1477f2352bd3323d14", + "version": "5.1.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V500-build0056-FORTINET.out.kvm-boot.qcow2", + "filesize": 75038720, + "md5sum": "8b3b789fb540b2c30066f66bcbe7f307", + "version": "5.0.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V500-build0045-FORTINET.out.kvm-boot.qcow2", + "filesize": 74383360, + "md5sum": "d7381b3fb7a4534370ce8983e441d888", + "version": "5.0.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0999-FORTINET.out.kvm-boot.qcow2", + "filesize": 73334784, + "md5sum": "d7825b8d0962800c37ffa814a6b2ad45", + "version": "4.8.5" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0989-FORTINET.out.kvm-boot.qcow2", + "filesize": 72810496, + "md5sum": "c1926d5979ef24d9d14d3394c0bb832b", + "version": "4.8.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0983-FORTINET.out.kvm-boot.qcow2", + "filesize": 72876032, + "md5sum": "d4cfc3b215780b2fb4c9d8f55208e8be", + "version": "4.8.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0977-FORTINET.out.kvm-boot.qcow2", + "filesize": 72876032, + "md5sum": "285ca7a601a0d06bb893ef91ad7748fd", + "version": "4.8.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0970-FORTINET.out.kvm-boot.qcow2", + "filesize": 72351744, + "md5sum": "8f604b2a89ac3d9cc3d2d79d85b2d7ff", + "version": "4.8.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0937-FORTINET.out.kvm-boot.qcow2", + "filesize": 72089600, + "md5sum": "448f5906c42dd7e535c3acb2adab253c", + "version": "4.8.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0858-FORTINET.out.kvm-boot.qcow2", + "filesize": 63700992, + "md5sum": "6d81b1b3df55174e4db8526d6cfd8b0e", + "version": "4.7.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0849-FORTINET.out.kvm-boot.qcow2", + "filesize": 64028672, + "md5sum": "c85f49cd320fdca36e71c0d7cdc26f8c", + "version": "4.7.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0844-FORTINET.out.kvm-boot.qcow2", + "filesize": 63963136, + "md5sum": "6f035cda6138af993153ef322231a201", + "version": "4.7.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0832-FORTINET.out.kvm-boot.qcow2", + "filesize": 67960832, + "md5sum": "70577d11ae77ce765cae944f3a7c3941", + "version": "4.7.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0828-FORTINET.out.kvm-boot.qcow2", + "filesize": 67960832, + "md5sum": "4a0bf9d4ad29628ca08a1638662a43a6", + "version": "4.7.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0679-FORTINET.out.kvm-boot.qcow2", + "filesize": 82903040, + "md5sum": "31147f42b54ce8e9c953dea519a4b9a6", + "version": "4.6.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0677-FORTINET.out.kvm-boot.qcow2", + "filesize": 82837504, + "md5sum": "2a9c32c7b32807f4dc384ed6e2082802", + "version": "4.6.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0660-FORTINET.out.kvm-boot.qcow2", + "filesize": 82509824, + "md5sum": "50cc9bc44409180f7106e4201b2dae2a", + "version": "4.6.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-V400-build0605-FORTINET.out.kvm-boot.qcow2", + "filesize": 48168960, + "md5sum": "d415bc621bf0abc2b5aa32c03390e11f", + "version": "4.5.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-v400-build0597-FORTINET.out.kvm-boot.qcow2", + "filesize": 66584576, + "md5sum": "47a905193e8f9ddc25be71aeccccc7b9", + "version": "4.5.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-v400-build0581-FORTINET.out.kvm-boot.qcow2", + "filesize": 67305472, + "md5sum": "bfc93d5881dda3f0a3123f54665bdcf0", + "version": "4.5.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAD_KVM-v400-build0560-FORTINET.out.kvm-boot.qcow2", + "filesize": 68026368, + "md5sum": "7a71f52bde93c0000b047626731b7aef", + "version": "4.5.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiADC", + "port_name_format": "Port{port1}", + "product_name": "FortiADC", + "product_url": "https://www.fortinet.com/products-services/products/application-delivery-controllers/fortiadc.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 10, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "Default username is admin, no password is set. Silent boot, it might take a while.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FAD_KVM-V500-build0423-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "5.2.0" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V500-build0239-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "5.1.1" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0989-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "5.0.1" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0989-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "5.0.0" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0999-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.8.5" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0989-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.8.4" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0983-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.8.3" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0977-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.8.2" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0970-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.8.1" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0937-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.8.0" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0858-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.7.4" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0849-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.7.3" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0844-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.7.2" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0832-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.7.1" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0828-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.7.0" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0679-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.6.2" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0677-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.6.1" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0660-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.6.0" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-V400-build0605-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.5.3" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-v400-build0597-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.5.2" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-v400-build0581-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.5.1" + }, + { + "images": { + "hda_disk_image": "FAD_KVM-v400-build0560-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + }, + "name": "4.5.0" + } + ] + }, + { + "availability": "free-to-try", + "builtin": true, + "category": "guest", + "description": "Microsoft Windows, or simply Windows, is a metafamily of graphical operating systems developed, marketed, and sold by Microsoft. It consists of several families of operating systems, each of which cater to a certain sector of the computing industry with the OS typically associated with IBM PC compatible architecture.", + "documentation_url": "https://technet.microsoft.com/en-us/library/cc498727.aspx", + "images": [ + { + "download_url": "https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2016", + "filename": "Win2k16_14393.0.161119-1705.RS1_REFRESH_SERVER_EVAL_X64FRE_EN-US.ISO", + "filesize": 6972221440, + "md5sum": "70721288bbcdfe3239d8f8c0fae55f1f", + "version": "2016" + }, + { + "download_url": "https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2012-r2", + "filename": "Win2k12_9600.16415.amd64fre.winblue_refresh.130928-2229_server_serverdatacentereval_en-us.vhd", + "filesize": 8024756224, + "md5sum": "b0a988a2e1f401c99c7c18a00391c4cc", + "version": "2012 R2" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 198656, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Windows Server", + "port_name_format": "NIC{port1}", + "product_name": "Windows Server", + "product_url": "https://www.microsoft.com/en-us/windows", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "sata", + "kvm": "require", + "options": "-usbdevice tablet", + "ram": 2048 + }, + "registry_version": 4, + "status": "stable", + "symbol": "microsoft.svg", + "vendor_name": "Microsoft", + "vendor_url": "http://www.microsoft.com/", + "versions": [ + { + "images": { + "cdrom_image": "Win2k16_14393.0.161119-1705.RS1_REFRESH_SERVER_EVAL_X64FRE_EN-US.ISO", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "2016" + }, + { + "images": { + "hda_disk_image": "Win2k12_9600.16415.amd64fre.winblue_refresh.130928-2229_server_serverdatacentereval_en-us.vhd" + }, + "name": "2012 R2" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "FRRouting (FRR) is an IP routing protocol suite for Linux and Unix platforms which includes protocol daemons for BGP, IS-IS, LDP, OSPF, PIM, and RIP.\n\nFRR\u2019s seamless integration with the native Linux/Unix IP networking stacks makes it applicable to a wide variety of use cases including connecting hosts/VMs/containers to the network, advertising network services, LAN switching and routing, Internet access routers, and Internet peering.\n\nThis is an unofficial VM or FRR.", + "images": [ + { + "compression": "bzip2", + "direct_download_url": "https://sourceforge.net/projects/frr/files/frr6.0-vm0.2.qcow2.bz2/download", + "download_url": "https://sourceforge.net/projects/frr/files/", + "filename": "frr6.0-vm0.2.qcow2", + "filesize": 1762066432, + "md5sum": "bf5aebd98352716bfabb119abb2ba19a", + "version": "FRR6.0 - VM0.2" + }, + { + "compression": "bzip2", + "direct_download_url": "https://sourceforge.net/projects/frr/files/frr4.0-vm0.1.qcow2.bz2/download", + "download_url": "https://sourceforge.net/projects/frr/files/", + "filename": "frr4.0-vm0.1.qcow2", + "filesize": 1670643712, + "md5sum": "e1dc58cbb2b71c58051538c07d412493", + "version": "FRR4.0 - VM0.1" + } + ], + "maintainer": "Andras Dosztal", + "maintainer_email": "developers@gns3.net", + "name": "FRR", + "port_name_format": "ens{port3}", + "product_name": "FRR", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 8, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "ram": 256 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "Credentials: frr / frr\nIf you exit from the router CLI, you can get back by typing 'vtysh' to the console.", + "vendor_name": "FRRouting Project", + "vendor_url": "https://frrouting.org", + "versions": [ + { + "images": { + "hda_disk_image": "frr6.0-vm0.2.qcow2" + }, + "name": "FRR6.0 - VM0.2" + }, + { + "images": { + "hda_disk_image": "frr4.0-vm0.1.qcow2" + }, + "name": "FRR4.0 - VM0.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "The chromium browser", + "docker": { + "adapters": 1, + "console_type": "vnc", + "image": "gns3/chromium:latest" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Chromium", + "product_name": "Chromium", + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/docker_guest.svg", + "vendor_name": "Chromium", + "vendor_url": "https://www.chromium.org/" + }, + { + "builtin": true, + "category": "router", + "description": "The Cisco Cloud Services Router 1000V (CSR 1000V) is a router and network services platform in virtual form factor that is intended for deployment in cloud and virtual data centers. It is optimized to serve as a single-tenant or multitenant WAN gateway. Using proven, industry-leading Cisco IOS\u00ae XE Software networking and security features, the CSR 1000V enables enterprises to transparently extend their WANs into external provider-hosted clouds and cloud providers to offer their tenants enterprise-class networking services.", + "documentation_url": "http://www.cisco.com/c/en/us/support/routers/cloud-services-router-1000v-series/products-installation-and-configuration-guides-list.html", + "images": [ + { + "download_url": "https://software.cisco.com/download/home/284364978/type/282046477/release/Gibraltar-16.10.1b", + "filename": "csr1000v-universalk9.16.10.01b-serial.qcow2", + "filesize": 950468608, + "md5sum": "0d3d647f83631c7955ad7899e6cce293", + "version": "16.10.1b" + }, + { + "download_url": "https://software.cisco.com/download/home/284364978/type/282046477/release/Fuji-16.9.1", + "filename": "csr1000v-universalk9.16.09.01-serial.qcow2", + "filesize": 917897216, + "md5sum": "d7e1c83b6f513beb4200c7691d119086", + "version": "16.9.1" + }, + { + "download_url": "https://software.cisco.com/download/home/284364978/type/282046477", + "filename": "csr1000v-universalk9.16.08.01a-serial.qcow2", + "filesize": 890044416, + "md5sum": "91e2572f20c77606d710223511cd279a", + "version": "16.8.1a" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284364978&flowid=39582&softwareid=282046477&release=Fuji-16.7.1", + "filename": "csr1000v-universalk9.16.07.01-serial.qcow2", + "filesize": 884539392, + "md5sum": "bad9000d4ae8317bbc99a34a8cdd2eb4", + "version": "16.7.1" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284364978&flowid=39582&softwareid=282046477&release=Everest-16.6.2", + "filename": "csr1000v-universalk9.16.06.02-serial.qcow2", + "filesize": 1570242560, + "md5sum": "11e393b31ab9d1ace8e5f7551c491ba2", + "version": "16.6.2" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284364978&flowid=39582&softwareid=282046477&release=Everest-16.6.1", + "filename": "csr1000v-universalk9.16.06.01-serial.qcow2", + "filesize": 1566179328, + "md5sum": "909e74446d3ff0b82c14327c0058fdc2", + "version": "16.6.1" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284364978&flowid=39582&softwareid=282046477&release=Everest-16.5.2", + "filename": "csr1000v-universalk9.16.05.02-serial.qcow2", + "filesize": 1322385408, + "md5sum": "59a84da28d59ee75176aa05ecde7f72a", + "version": "16.5.2" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "csr1000v-universalk9.16.5.1b-serial.qcow2", + "filesize": 1209543680, + "md5sum": "ac11d33041b8ff6dc3553e324d02cccb", + "version": "16.5.1b" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "csr1000v-universalk9.03.17.00.S.156-1.S-ext.qcow2", + "filesize": 1346305024, + "md5sum": "06cbfcd11f3557391db64fe2a6015a6e", + "version": "3.17" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "csr1000v-universalk9.16.3.1-build2.qcow2", + "filesize": 1280835584, + "md5sum": "a770e96de928265515304c9c9d6b46b9", + "version": "16.3.1-build2" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284364978&softwareid=282046477&release=Denali-16.3.1", + "filename": "csr1000v-universalk9.16.03.01.qcow2", + "filesize": 1351352320, + "md5sum": "0a7f3a4b93d425c2dcb2df5505816fa5", + "version": "16.3.1" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "csr1000v-universalk9.16.03.02.qcow2", + "filesize": 1167720448, + "md5sum": "2e5803d23cd52cba5d55fa8306be5f13", + "version": "16.3.2" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "csr1000v-universalk9.16.4.1.qcow2", + "filesize": 1261961216, + "md5sum": "3428e0dcf5132a1b11ab7696d8c61b2e", + "version": "16.4.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco CSR1000v", + "port_name_format": "Gi{port1}", + "product_name": "CSR1000v", + "product_url": "http://www.cisco.com/c/en/us/support/routers/cloud-services-router-1000v-series/tsd-products-support-series-home.html", + "qemu": { + "adapter_type": "vmxnet3", + "adapters": 4, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "ram": 3072 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "There is no default password and enable password. A default configuration is present.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.10.01b-serial.qcow2" + }, + "name": "16.10.1b" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.09.01-serial.qcow2" + }, + "name": "16.9.1" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.08.01a-serial.qcow2" + }, + "name": "16.8.1a" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.07.01-serial.qcow2" + }, + "name": "16.7.1" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.06.02-serial.qcow2" + }, + "name": "16.6.2" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.06.01-serial.qcow2" + }, + "name": "16.6.1" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.05.02-serial.qcow2" + }, + "name": "16.5.2" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.5.1b-serial.qcow2" + }, + "name": "16.5.1b" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.03.17.00.S.156-1.S-ext.qcow2" + }, + "name": "3.17" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.03.01.qcow2" + }, + "name": "16.3.1" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.3.1-build2.qcow2" + }, + "name": "16.3.1-build2" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.03.02.qcow2" + }, + "name": "16.3.2" + }, + { + "images": { + "hda_disk_image": "csr1000v-universalk9.16.4.1.qcow2" + }, + "name": "16.4.1" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "Cumulus VX is a community-supported virtual appliance that enables cloud admins and network engineers to preview and test Cumulus Networks technology at zero cost. You can build sandbox environments to learn Open Networking concepts, prototype network operations and script & develop applications risk-free. With Cumulus VX, you can get started with Open Networking at your pace, on your time, and in your environment!", + "documentation_url": "http://docs.cumulusnetworks.com/", + "first_port_name": "eth0", + "images": [ + { + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/CumulusLinux-3.7.2/cumulus-linux-3.7.2-vx-amd64-qemu.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.7.2-vx-amd64-qemu.qcow2", + "filesize": 1574502400, + "md5sum": "2fcd785da0452e403c44ba5f3ac4e870", + "version": "3.7.2" + }, + { + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/CumulusLinux-3.7.1/cumulus-linux-3.7.1-vx-amd64-qemu.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.7.1-vx-amd64-qemu.qcow2", + "filesize": 1640300544, + "md5sum": "201055c57e4a20bb5772289ea6216631", + "version": "3.7.1" + }, + { + "direct_download_url": "https://s3.amazonaws.com/cumulusfiles/CumulusLinux-3.6.2/cumulus-linux-3.6.2-vx-amd64.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.6.2-vx-amd64.qcow2", + "filesize": 1150746624, + "md5sum": "02b0621d68fb2e709b4bcc48748c7b6f", + "version": "3.6.2" + }, + { + "direct_download_url": "https://s3.amazonaws.com/cumulusfiles/CumulusLinux-3.6.1/cumulus-linux-3.6.1-vx-amd64.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.6.1-vx-amd64.qcow2", + "filesize": 1068761088, + "md5sum": "b2145a689ceea668d003a0d2f2faa045", + "version": "3.6.1" + }, + { + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.6.0-vx-amd64.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.6.0-vx-amd64.qcow2", + "filesize": 1105199104, + "md5sum": "b5356b6c922f5620d7e6971d44e9be4d", + "version": "3.6.0" + }, + { + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.5.3-vx-amd64.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.5.3-vx-amd64.qcow2", + "filesize": 1084358656, + "md5sum": "4ecbd7341b214fa3c3b27ab11d1df2fb", + "version": "3.5.3" + }, + { + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.5.3-vx-amd64.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.5.2-vx-amd64.qcow2", + "filesize": 996605952, + "md5sum": "87d1d8b297e5ebd77924669dfb7e4c9f", + "version": "3.5.2" + }, + { + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.5.0-vx-amd64.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.5.0-vx-amd64.qcow2", + "filesize": 1044250624, + "md5sum": "9ad1f352d0603becf4bcc749b77c99dd", + "version": "3.5.0" + }, + { + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.4.3-vx-amd64.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.4.3-vx-amd64.qcow2", + "filesize": 988872704, + "md5sum": "fd9144cdab7cac66cf421a13c6f50ac8", + "version": "3.4.3" + }, + { + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.4.2-vx-amd64.qcow2", + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.4.2-vx-amd64.qcow2", + "filesize": 1060700160, + "md5sum": "ca844684784ceeee893d0cd76dc44e3b", + "version": "3.4.2" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.4.1-vx-amd64.qcow2", + "filesize": 975503360, + "md5sum": "38319aa04533d91b1121a02f6ed99993", + "version": "3.4.1" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.4.0-vx-amd64.qcow2", + "filesize": 918355968, + "md5sum": "d93a15072bc7f8d15268f5e43f735a5e", + "version": "3.4.0" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.3.2-vx-amd64.qcow2", + "filesize": 980090880, + "md5sum": "8364f93cabaa442c13c8c6752a248a5d", + "version": "3.3.2" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.2.1-vx-amd64-1486153138.ac46c24zd00d13e.qcow2", + "filesize": 1232601088, + "md5sum": "145519af273d7f21ee1845780de7dce3", + "version": "3.2.1" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.2.0-vx-amd64-1481684769.ac46c24z090952a.qcow2", + "filesize": 1217593344, + "md5sum": "4cd6cee606483d4403d3329a72697ca4", + "version": "3.2.0" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.1.2-vx-amd64-1478059878.e1f18b3zacdc5c1.qcow2", + "filesize": 1291911168, + "md5sum": "e25d4dde0d2d5378a469380bd1d8d082", + "version": "3.1.2" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.1.1-vx-amd64-1474681409.bd4e10cz3c4e23f.qcow2", + "filesize": 1230372864, + "md5sum": "ad7688721417f167ea3537e60feac3da", + "version": "3.1.1" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.1.0-vx-amd64-1471979027.dc7e2adza017cfb.qcow2", + "filesize": 1190789120, + "md5sum": "6a68b8c8ef45c7227e80009e9920729c", + "version": "3.1.0" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.0.1-vx-amd64-1468215109.5d83176z20fa23d.qcow2", + "filesize": 1284112384, + "md5sum": "9f312bf4de1b410ce48e26b38f3bef48", + "version": "3.0.1" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "cumulus-linux-3.0.0-vx-amd64-1464279382.a8e7985zf0f5ad5.qcow2", + "filesize": 1237581824, + "md5sum": "ef23948870b77bb1373b9f06de4e7742", + "version": "3.0.0" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "CumulusVX-2.5.5-cc665123486ac43d.qcow2", + "filesize": 1092550656, + "md5sum": "e0cad2491d47f859828703a0b50cf633", + "version": "2.5.5" + }, + { + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "filename": "CumulusVX-2.5.3-4eb681f3df86c478.qcow2", + "filesize": 1040973824, + "md5sum": "5128aec2568991ea0586293cb85f7a97", + "version": "2.5.3" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cumulus VX", + "port_name_format": "swp{port1}", + "product_name": "Cumulus VX", + "product_url": "https://cumulusnetworks.com/cumulus-vx/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 7, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "ram": 512 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "Default username is cumulus and password is CumulusLinux!", + "vendor_name": "Cumulus Network", + "vendor_url": "https://www.cumulusnetworks.com", + "versions": [ + { + "images": { + "hda_disk_image": "cumulus-linux-3.7.2-vx-amd64-qemu.qcow2" + }, + "name": "3.7.2" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.7.1-vx-amd64-qemu.qcow2" + }, + "name": "3.7.1" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.6.2-vx-amd64.qcow2" + }, + "name": "3.6.2" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.6.1-vx-amd64.qcow2" + }, + "name": "3.6.1" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.6.0-vx-amd64.qcow2" + }, + "name": "3.6.0" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.5.3-vx-amd64.qcow2" + }, + "name": "3.5.3" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.5.2-vx-amd64.qcow2" + }, + "name": "3.5.2" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.5.0-vx-amd64.qcow2" + }, + "name": "3.5.0" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.4.3-vx-amd64.qcow2" + }, + "name": "3.4.3" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.4.2-vx-amd64.qcow2" + }, + "name": "3.4.2" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.4.1-vx-amd64.qcow2" + }, + "name": "3.4.1" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.4.0-vx-amd64.qcow2" + }, + "name": "3.4.0" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.3.2-vx-amd64.qcow2" + }, + "name": "3.3.2" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.2.1-vx-amd64-1486153138.ac46c24zd00d13e.qcow2" + }, + "name": "3.2.1" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.2.0-vx-amd64-1481684769.ac46c24z090952a.qcow2" + }, + "name": "3.2.0" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.1.2-vx-amd64-1478059878.e1f18b3zacdc5c1.qcow2" + }, + "name": "3.1.2" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.1.1-vx-amd64-1474681409.bd4e10cz3c4e23f.qcow2" + }, + "name": "3.1.1" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.1.0-vx-amd64-1471979027.dc7e2adza017cfb.qcow2" + }, + "name": "3.1.0" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.0.1-vx-amd64-1468215109.5d83176z20fa23d.qcow2" + }, + "name": "3.0.1" + }, + { + "images": { + "hda_disk_image": "cumulus-linux-3.0.0-vx-amd64-1464279382.a8e7985zf0f5ad5.qcow2" + }, + "name": "3.0.0" + }, + { + "images": { + "hda_disk_image": "CumulusVX-2.5.5-cc665123486ac43d.qcow2" + }, + "name": "2.5.5" + }, + { + "images": { + "hda_disk_image": "CumulusVX-2.5.3-4eb681f3df86c478.qcow2" + }, + "name": "2.5.3" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "Arista cEOS\u2122 introduces the containerized packaging of EOS software and its agents for deployment in cloud infrastructure with the same proven EOS software image that runs on all Arista products. These flexible deployment options empower cloud network operators that are customizing their operating environments to provide a uniform workflow for development, testing and deployment of differentiated services.", + "docker": { + "adapters": 8, + "console_type": "telnet", + "image": "ceosimage:GNS3" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "cEOS", + "product_name": "cEOS", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "Download:\nCreate a (free) Arista account and login.\nThen navigate to Support / Software Download and download the cEOS-lab image.\n\nInstallation:\nCopy the image to your GNS3VM (or other Linux) server, then run the following commands:\n\ncEOS-4.21.0F and newer, replace by the cEOS version:\ndocker import cEOS-lab.tar.xz ceosimage:\necho \"rm /etc/systemd/system/getty.target.wants/getty@tty1.service\" | \\\ndocker run --name=ceos-container -e CEOS=1 -e container=docker -e EOS_PLATFORM=ceoslab -e SKIP_ZEROTOUCH_BARRIER_IN_SYSDBINIT=1 -e ETBA=1 -e INTFTYPE=eth -i ceosimage: sh\ndocker commit --change='CMD [\"/sbin/init\"]' --change='VOLUME /mnt/flash' ceos-container ceosimage:GNS3\ndocker rm ceos-container\n\ncEOS-4.20.5F:\ndocker import cEOS-lab.tar.xz ceosimage:4.20.5F\necho \"rm /etc/systemd/system/getty.target.wants/getty@tty1.service\" | \\\ndocker run --name=ceos-container -e CEOS=1 -e container=docker -e EOS_PLATFORM=ceossim -e SKIP_ZEROTOUCH_BARRIER_IN_SYSDBINIT=1 -e ETBA=1 -e INTFTYPE=eth -i ceosimage:4.20.5F sh\ndocker commit --change='CMD [\"/sbin/init\"]' --change='VOLUME /mnt/flash' ceos-container ceosimage:GNS3\ndocker rm ceos-container\n\nUsage:\nStart an auxiliary console on the cEOS and issue the \"Cli\" command.\nOnly cEOS-4.20.5F: Login on the console with username \"admin\".", + "vendor_name": "Arista", + "vendor_url": "http://www.arista.com/" + }, + { + "builtin": true, + "category": "guest", + "description": "vRIN is a VM appliance capable to inject high number of routes into a network. It was tested on GNS3 topologies using VirtualBox and Qemu with up to 1M BGP routes. Runs Quagga. Supported protocols: BGP (IPv4/6), OSPF, OSPFv3, RIP v2, RIPng", + "images": [ + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.9.2.qcow2.bz2/download", + "download_url": "https://sourceforge.net/projects/vrin/files", + "filename": "vRIN-0.9.2.qcow2", + "filesize": 957087744, + "md5sum": "40afad2f5136e56f0cb45466847eae63", + "version": "0.9.2" + }, + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.9.1.qcow2.bz2/download", + "download_url": "https://sourceforge.net/projects/vrin/files", + "filename": "vRIN-0.9.1.qcow2", + "filesize": 1008926720, + "md5sum": "9f09f104917e19649598d9e2a5a3476b", + "version": "0.9.1" + }, + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.9.qcow2.bz2/download", + "download_url": "https://sourceforge.net/projects/vrin/files", + "filename": "vRIN-0.9.qcow2", + "filesize": 922943488, + "md5sum": "b9ec187d7a4743bb02339cf262767959", + "version": "0.9" + }, + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.8.qcow2.bz2/download", + "download_url": "https://sourceforge.net/projects/vrin/files", + "filename": "vRIN-0.8.qcow2", + "filesize": 625999872, + "md5sum": "38eb48d098d3e465422347f7983b9d86", + "version": "0.8" + }, + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.7.qcow2.bz2/download", + "download_url": "https://sourceforge.net/projects/vrin/files", + "filename": "vRIN-0.7.qcow2", + "filesize": 614268928, + "md5sum": "2e9802c403e34a91871922b9a26592ad", + "version": "0.7" + }, + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.6.qcow2.bz2/download", + "download_url": "https://sourceforge.net/projects/vrin/files", + "filename": "vRIN-0.6.qcow2", + "filesize": 609681408, + "md5sum": "6c763f609c05b5b9a3b1d422ab89dbac", + "version": "0.6" + } + ], + "maintainer": "Andras Dosztal", + "maintainer_email": "developers@gns3.net", + "name": "vRIN", + "product_name": "vRIN", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "allow", + "ram": 256 + }, + "registry_version": 3, + "status": "stable", + "symbol": "vRIN.svg", + "usage": "Connect eth0 to the network where you want vRIN to inject routes into then start the VM. You can either run the VM in normal or headless mode; in the latter case you can access vRIN through serial console. User input is not checked; it's your responsibility to enter valid information.\n\nAfter generating the routes, each Quagga process can be reached through eth0 using their default ports:\n - zebra: 2601\n - rip: 2602\n - ripng: 2603\n - ospf: 2604\n - bgp: 2605\n - ospf6d: 2606\nVTY password: vrin\n\nNotes:\n\n - Route generation may take a while when creating lots of routes (i.e. 10k+).\n - Login (serial / VM window): root / vrin", + "vendor_name": "Andras Dosztal", + "vendor_url": "https://sourceforge.net/projects/vrin/", + "versions": [ + { + "images": { + "hda_disk_image": "vRIN-0.9.2.qcow2" + }, + "name": "0.9.2" + }, + { + "images": { + "hda_disk_image": "vRIN-0.9.1.qcow2" + }, + "name": "0.9.1" + }, + { + "images": { + "hda_disk_image": "vRIN-0.9.qcow2" + }, + "name": "0.9" + }, + { + "images": { + "hda_disk_image": "vRIN-0.8.qcow2" + }, + "name": "0.8" + }, + { + "images": { + "hda_disk_image": "vRIN-0.7.qcow2" + }, + "name": "0.7" + }, + { + "images": { + "hda_disk_image": "vRIN-0.6.qcow2" + }, + "name": "0.6" + } + ] + }, + { + "availability": "service-contract", + "builtin": true, + "category": "guest", + "description": "Aruba Virtual Mobility Controller", + "first_port_name": "mgmt", + "images": [ + { + "download_url": "http://support.arubanetworks.com/", + "filename": "ArubaOS_VMC_8.2.1.1_65265-disk1.qcow2", + "filesize": 197066752, + "md5sum": "f3bc233f0714e4b1cc127e337d077574", + "version": "8.2.1.1" + }, + { + "download_url": "http://support.arubanetworks.com/", + "filename": "ArubaOS_VMC_8.2.1.1_65265-disk2.qcow2", + "filesize": 19202048, + "md5sum": "18ede2afc7595fdac4508a8a3972e302", + "version": "8.2.1.1" + } + ], + "maintainer": "Gary Ossewaarde", + "maintainer_email": "gary.ossewaarde@gmail.com", + "name": "Aruba VMC", + "port_name_format": "GE0/0/{0}", + "product_name": "Aruba VMC", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "arch": "x86_64", + "console_type": "vnc", + "cpus": 3, + "hda_disk_interface": "ide", + "hdb_disk_interface": "ide", + "hdc_disk_interface": "ide", + "kernel_command_line": "-smp cores=3,threads=1,sockets=1 -cpu host -nographic", + "kvm": "require", + "options": "-smp cores=3,threads=1,sockets=1 -cpu host -nographic", + "process_priority": "normal", + "ram": 6144 + }, + "registry_version": 4, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "vendor_name": "HPE Aruba", + "vendor_url": "arubanetworks.com", + "versions": [ + { + "images": { + "hda_disk_image": "ArubaOS_VMC_8.2.1.1_65265-disk1.qcow2", + "hdb_disk_image": "ArubaOS_VMC_8.2.1.1_65265-disk2.qcow2" + }, + "name": "8.2.1.1" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "The Alcatel-Lucent 7750 Service Router (SR) portfolio is a suite of multiservice edge routing platforms that deliver high performance, service richness, and creates exceptional value for networking in the cloud era. It is designed for the concurrent delivery of advanced residential, business and wireless broadband IP services, and provides cloud, data center and branch office connectivity for enterprise networking on a common IP edge routing platform.", + "documentation_url": "https://www.alcatel-lucent.com/support", + "first_port_name": "A/1", + "images": [ + { + "compression": "zip", + "download_url": "https://www.alcatel-lucent.com/support", + "filename": "TiMOS-SR-13.0.R4-vm.qcow2", + "filesize": 368508928, + "md5sum": "d7a3609e506acdcb55f6db5328dba8ed", + "version": "13.0.R4" + }, + { + "compression": "zip", + "download_url": "https://www.alcatel-lucent.com/support", + "filename": "TiMOS-SR-12.0.R6-vm.qcow2", + "filesize": 221511680, + "md5sum": "7d84d97a5664af2e3546bfa832fc1848", + "version": "12.0.R6" + }, + { + "compression": "zip", + "download_url": "https://www.alcatel-lucent.com/support", + "filename": "TiMOS-SR-12.0.R18.qcow2", + "filesize": 223870976, + "md5sum": "d0bba5feaaf09fd02185f25898a6afc7", + "version": "12.0.R18" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Alcatel 7750", + "port_name_format": "1/1/{port1}", + "product_name": "Alcatel 7750", + "product_url": "https://www.alcatel-lucent.com/products/7750-service-router", + "qemu": { + "adapter_type": "e1000", + "adapters": 6, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "options": "", + "ram": 2048 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "usage": "Login is admin and password is admin", + "vendor_name": "Alcatel", + "vendor_url": "https://www.alcatel-lucent.com/", + "versions": [ + { + "images": { + "hda_disk_image": "TiMOS-SR-13.0.R4-vm.qcow2" + }, + "name": "13.0.R4" + }, + { + "images": { + "hda_disk_image": "TiMOS-SR-12.0.R6-vm.qcow2" + }, + "name": "12.0.R6" + }, + { + "images": { + "hda_disk_image": "TiMOS-SR-12.0.R18.qcow2" + }, + "name": "12.0.R18" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco 1700 Router", + "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", + "dynamips": { + "chassis": "1720", + "nvram": 128, + "platform": "c1700", + "ram": 160, + "slot0": "C1700-MB-1FE", + "startup_config": "ios_base_startup-config.txt" + }, + "images": [ + { + "filename": "c1700-adventerprisek9-mz.124-25d.image", + "filesize": 57475320, + "md5sum": "7f4ae12a098391bc0edcaf4f44caaf9d", + "version": "124-25d" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco 1700", + "product_name": "1700", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "idlepc": "0x80358a60", + "images": { + "image": "c1700-adventerprisek9-mz.124-25d.image" + }, + "name": "124-25d" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Zeroshell is a Linux distribution for servers and embedded devices aimed at providing the main network services a LAN requires. It is available in the form of Live CD or Compact Flash image and you can configure and administer it using your web browser.", + "documentation_url": "http://www.zeroshell.org/documentation/", + "images": [ + { + "compression": "gzip", + "direct_download_url": "http://www.zeroshell.net/listing/ZeroShell-3.8.2-X86-USB.img.gz", + "download_url": "http://www.zeroshell.org/download/", + "filename": "ZeroShell-3.8.2-X86-USB.img", + "filesize": 1992294400, + "md5sum": "bb8c7f24c86eb59e26ce36ff1979ecd4", + "version": "3.8.2" + }, + { + "compression": "gzip", + "direct_download_url": "http://www.zeroshell.net/listing/ZeroShell-3.8.1-X86-USB.img.gz", + "download_url": "http://www.zeroshell.org/download/", + "filename": "ZeroShell-3.8.1-X86-USB.img", + "filesize": 1992294400, + "md5sum": "49256e396d160e88fbc3a3889e172482", + "version": "3.8.1" + }, + { + "compression": "gzip", + "direct_download_url": "http://www.zeroshell.net/listing/ZeroShell-3.8.0-X86-USB.img.gz", + "download_url": "http://www.zeroshell.org/download/", + "filename": "ZeroShell-3.8.0-X86-USB.img", + "filesize": 1992294400, + "md5sum": "a16d584c831f3e88ea442a2343d71cfa", + "version": "3.8.0" + }, + { + "compression": "gzip", + "direct_download_url": "http://www.zeroshell.net/listing/ZeroShell-3.7.1-USB.img.gz", + "download_url": "http://www.zeroshell.org/download/", + "filename": "ZeroShell-3.7.1-USB.img", + "filesize": 1992294400, + "md5sum": "22e739a24dc1c233d3eca5d8fedc97c8", + "version": "3.7.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "ZeroShell", + "product_name": "ZeroShell", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "arch": "x86_64", + "console_type": "vnc", + "kvm": "allow", + "ram": 256 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "Default WebUI credentials: admin / zeroshell", + "vendor_name": "Fulvio Ricciardi", + "vendor_url": "http://www.zeroshell.org", + "versions": [ + { + "images": { + "hda_disk_image": "ZeroShell-3.8.2-X86-USB.img" + }, + "name": "3.8.2" + }, + { + "images": { + "hda_disk_image": "ZeroShell-3.8.1-X86-USB.img" + }, + "name": "3.8.1" + }, + { + "images": { + "hda_disk_image": "ZeroShell-3.8.0-X86-USB.img" + }, + "name": "3.8.0" + }, + { + "images": { + "hda_disk_image": "ZeroShell-3.7.1-USB.img" + }, + "name": "3.7.1" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "The VM-Series combines next-generation firewall security and advanced threat prevention to protect your virtualized environments from advanced cyberthreats. The VM-Series natively analyzes all traffic in a single pass to determine the application identity, the content within, and the user identity.", + "documentation_url": "https://www.paloaltonetworks.com/documentation/80/virtualization/virtualization", + "first_port_name": "management", + "images": [ + { + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", + "filename": "PA-VM-ESX-8.1.0-disk1.vmdk", + "filesize": 2281454080, + "md5sum": "49af8e8225c2e90414bde0be15eaf421", + "version": "8.1.0" + }, + { + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", + "filename": "PA-VM-KVM-8.1.0.qcow2", + "filesize": 2260467712, + "md5sum": "459558515b965b2e43fde2842abbae66", + "version": "8.1.0" + }, + { + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", + "filename": "PA-VM-ESX-8.0.0-disk1.vmdk", + "filesize": 2002713088, + "md5sum": "a505fb1dbcc855ecf98630fd5d329f9a", + "version": "8.0.0" + }, + { + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", + "filename": "PA-VM-KVM-8.0.0.qcow2", + "filesize": 1987444736, + "md5sum": "b6a1ddc8552aff87f05f9c0d4cb54dc3", + "version": "8.0.0" + }, + { + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", + "filename": "PA-VM-ESX-7.1.0-disk1.vmdk", + "filesize": 1871149056, + "md5sum": "e044dc649b7146ee4f619edb0e5f6675", + "version": "7.1.0 (ESX)" + }, + { + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", + "filename": "PA-VM-KVM-7.1.0.qcow2", + "filesize": 1858797568, + "md5sum": "da300253709740068927408239c2e321", + "version": "7.1.0" + }, + { + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", + "filename": "PA-VM-ESX-6.1.0-disk1.vmdk", + "filesize": 2959736832, + "md5sum": "64b1e81cd54008318235832ea6d71424", + "version": "6.1.0 (ESX)" + } + ], + "maintainer": "Community", + "maintainer_email": "", + "name": "PA-VM", + "port_name_format": "ethernet1/{port1}", + "product_name": "PAN VM-Series Firewall", + "product_url": "https://www.paloaltonetworks.com/products/secure-the-network/virtualized-next-generation-firewall/vm-series", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 25, + "arch": "x86_64", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "options": "-smp 2", + "ram": 4096 + }, + "registry_version": 3, + "status": "experimental", + "symbol": "pan-vm-fw.svg", + "usage": "Default Username: admin\r\nDefault Password: admin\r\nPAN-VM goes through several iterations of host prompts during boot. This is normal and expected.\r\nLogin is available when prompt is PA-VM login:\r\n\r\nGetting Started:\r\nTo configure a static IP address at the console enter the following commands:\r\n\r\nconfigure\r\nset deviceconfig system ip-address netmask default-gateway type static\r\nset deviceconfig system dns-setting servers primary secondary \r\ncommit\r\n", + "vendor_name": "Palo Alto Networks", + "vendor_url": "http://www.paloaltonetworks.com/", + "versions": [ + { + "images": { + "hda_disk_image": "PA-VM-ESX-8.1.0-disk1.vmdk" + }, + "name": "8.1.0 (ESX)" + }, + { + "images": { + "hda_disk_image": "PA-VM-KVM-8.1.0.qcow2" + }, + "name": "8.1.0" + }, + { + "images": { + "hda_disk_image": "PA-VM-ESX-8.0.0-disk1.vmdk" + }, + "name": "8.0.0 (ESX)" + }, + { + "images": { + "hda_disk_image": "PA-VM-KVM-8.0.0.qcow2" + }, + "name": "8.0.0" + }, + { + "images": { + "hda_disk_image": "PA-VM-ESX-7.1.0-disk1.vmdk" + }, + "name": "7.1.0 (ESX)" + }, + { + "images": { + "hda_disk_image": "PA-VM-KVM-7.1.0.qcow2" + }, + "name": "7.1.0" + }, + { + "images": { + "hda_disk_image": "PA-VM-ESX-6.1.0-disk1.vmdk" + }, + "name": "6.1.0 (ESX)" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "WordPress is a state-of-the-art publishing platform with a focus on aesthetics, web standards, and usability. It is one of the worlds most popular blog publishing applications, includes tons of powerful core functionality, extendable via literally thousands of plugins, and supports full theming. This appliance includes all the standard features in TurnKey Core too.", + "docker": { + "adapters": 1, + "console_type": "telnet", + "image": "turnkeylinux/wordpress:latest" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "WordPress", + "product_name": "TurnKey Linux WordPress", + "product_url": "https://www.turnkeylinux.org/wordpress", + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/docker_guest.svg", + "usage": "For security reasons there are no default passwords. All passwords are set at system initialization time.", + "vendor_name": "Turnkey Linux", + "vendor_url": "https://www.turnkeylinux.org/" + }, + { + "availability": "service-contract", + "builtin": true, + "category": "firewall", + "description": "Cisco Firepower Threat Defense Virtual NGFW appliances combine Cisco's proven network firewall with the industry\u2019s most effective next-gen IPS and advanced malware protection. All so you can get more visibility, be more flexible, save more, and protect better.", + "documentation_url": "http://www.cisco.com/c/en/us/td/docs/security/firepower/quick_start/kvm/ftdv-kvm-qsg.html", + "first_port_name": "Gigabit0/0 (Mgmt)", + "images": [ + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.2.0&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.2.0-363.qcow2", + "filesize": 1022885888, + "md5sum": "fafdae94ead07b23d6c8dc5f7a731e74", + "version": "6.2.0 (363)" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.2.0&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.2.0-363.vmdk", + "filesize": 1042470912, + "md5sum": "10297ab20526a8b1586c6ce1cd3d9cbd", + "version": "6.2.0 (363) vmdk" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.1.0-330.qcow2", + "filesize": 1004601344, + "md5sum": "386ab2b3d6d1d28fd2cd03a83df5e00f", + "version": "6.1.0 (330)" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.1.0-330.vmdk", + "filesize": 1024162816, + "md5sum": "c1fa58448841b33d5eed6854dc608816", + "version": "6.1.0 (330) vmdk" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.0.1&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.0.1-1213.vmdk", + "filesize": 714577408, + "md5sum": "bc53461e2ec344814e41a6a8d3a5f774", + "version": "6.0.1 (1213) vmdk" + } + ], + "maintainer": "Community", + "maintainer_email": "", + "name": "Cisco FTDv", + "port_name_format": "Gigabit0/{port1}", + "product_name": "Cisco FTDv", + "product_url": "http://www.cisco.com/c/en/us/td/docs/security/firepower/quick_start/kvm/ftdv-kvm-qsg.html", + "qemu": { + "adapter_type": "e1000", + "adapters": 10, + "arch": "x86_64", + "console_type": "telnet", + "cpus": 4, + "hda_disk_interface": "ide", + "kvm": "require", + "ram": 8192 + }, + "registry_version": 4, + "status": "experimental", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Default username/password: admin/Admin123.", + "vendor_name": "Cisco Systems", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.2.0-363.qcow2" + }, + "name": "6.2.0 (363)" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.2.0-363.vmdk" + }, + "name": "6.2.0 (363) vmdk" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.1.0-330.qcow2" + }, + "name": "6.1.0 (330)" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.1.0-330.vmdk" + }, + "name": "6.1.0 (330) vmdk" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.0.1-1213.vmdk" + }, + "name": "6.0.1 (1213) vmdk" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco 3620 Router", + "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", + "dynamips": { + "chassis": "3620", + "nvram": 256, + "platform": "c3600", + "ram": 192, + "startup_config": "ios_base_startup-config.txt" + }, + "images": [ + { + "filename": "c3620-a3jk8s-mz.122-26c.image", + "filesize": 38947996, + "md5sum": "37b444b29191630e5b688f002de2171c", + "version": "122-26c" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco 3620", + "product_name": "3620", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "idlepc": "0x603a8bac", + "images": { + "image": "c3620-a3jk8s-mz.122-26c.image" + }, + "name": "122-26c" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco 2691 Router", + "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", + "dynamips": { + "nvram": 256, + "platform": "c3600", + "ram": 192, + "slot0": "GT96100-FE", + "startup_config": "ios_base_startup-config.txt" + }, + "images": [ + { + "filename": "c2691-adventerprisek9-mz.124-15.T14.image", + "filesize": 95976624, + "md5sum": "e7ee5a4a57ed1433e5f73ba6e7695c90", + "version": "124-15.T14" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco 2691", + "product_name": "2691", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "idlepc": "0x60bcf9f8", + "images": { + "image": "c2691-adventerprisek9-mz.124-15.T14.image" + }, + "name": "124-15.T14" + } + ] + }, + { + "availability": "service-contract", + "builtin": true, + "category": "firewall", + "description": "This is your administrative nerve center for managing critical Cisco network security solutions. It provides complete and unified management over firewalls, application control, intrusion prevention, URL filtering, and advanced malware protection. Easily go from managing a firewall to controlling applications to investigating and remediating malware outbreaks.", + "documentation_url": "http://www.cisco.com/c/en/us/td/docs/security/firepower/quick_start/kvm/fmcv-kvm-qsg.html", + "first_port_name": "eth0", + "images": [ + { + "download_url": "https://software.cisco.com/download/", + "filename": "Cisco_Firepower_Management_Center_Virtual-6.0.0-1005-disk1.vmdk", + "filesize": 1681540608, + "md5sum": "3fed60f1e7d6910c22d13e966acebd7f", + "version": "6.0.0 (1005) vmdk" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "Cisco_Firepower_Management_Center_Virtual-6.1.0-330.qcow2", + "filesize": 1909391360, + "md5sum": "e3c64179ec46671caeb7ac3e4e58064f", + "version": "6.1.0 (330)" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "Cisco_Firepower_Management_Center_Virtual_VMware-6.1.0-330-disk1.vmdk", + "filesize": 1938142720, + "md5sum": "8bc77b317cf0007dcbb0f187c1a0c01f", + "version": "6.1.0 (330) vmdk" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "Cisco_Firepower_Management_Center_Virtual-6.2.0-362.qcow2", + "filesize": 1949302784, + "md5sum": "26e66882bf5f68adc0eca2f6bef7b613", + "version": "6.2.0 (362)" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "Cisco_Firepower_Management_Center_Virtual_VMware-6.2.0-362-disk1.vmdk", + "filesize": 1983376384, + "md5sum": "772165cbda3c183bb0e77a1923dd4d09", + "version": "6.2.0 (362) vmdk" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "Cisco_Firepower_Management_Center_Virtual-6.2.1-342.qcow2", + "filesize": 2113732608, + "md5sum": "29ebbbe71a6b766f6dea81e5ca32c275", + "version": "6.2.1 (342)" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "Cisco_Firepower_Management_Center_Virtual_VMware-6.2.1-342-disk1.vmdk", + "filesize": 2150017536, + "md5sum": "4cf5b7fd68075b6f7ee0dd41a4029ca0", + "version": "6.2.1 (342) vmdk" + } + ], + "maintainer": "Community", + "maintainer_email": "", + "name": "Cisco FMCv", + "port_name_format": "eth{port1}", + "product_name": "Cisco Firepower Management Center Virtual", + "product_url": "http://www.cisco.com/c/en/us/td/docs/security/firepower/quick_start/kvm/fmcv-kvm-qsg.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "arch": "x86_64", + "console_type": "telnet", + "cpus": 4, + "hda_disk_interface": "scsi", + "kvm": "require", + "options": "", + "ram": 8192 + }, + "registry_version": 4, + "status": "experimental", + "symbol": "cisco-fmcv.svg", + "usage": "BE PATIENT\nOn first boot FMCv generates about 6GB of data. This can take 30 minutes or more. Plan on a long wait after the following line in the boot up:\n\n usbcore: registered new interface driver usb-storage\n\nInitial IP address: 192.168.45.45.\n\nDefault username/password: admin/Admin123.", + "vendor_name": "Cisco Systems", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual-6.0.0-1005-disk1.vmdk" + }, + "name": "6.0.0 (1005) vmdk" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual-6.1.0-330.qcow2" + }, + "name": "6.1.0 (330)" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual_VMware-6.1.0-330-disk1.vmdk" + }, + "name": "6.1.0 (330) vmdk" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual-6.2.0-362.qcow2" + }, + "name": "6.2.0 (362)" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual_VMware-6.2.0-362-disk1.vmdk" + }, + "name": "6.2.0 (362) vmdk" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual-6.2.1-342.qcow2" + }, + "name": "6.2.1 (342)" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual_VMware-6.2.1-342-disk1.vmdk" + }, + "name": "6.2.1 (342) vmdk" + } + ] + }, + { + "availability": "free", + "builtin": true, + "category": "guest", + "description": "The CentOS Linux distribution is a stable, predictable, manageable and reproducible platform derived from the sources of Red Hat Enterprise Linux (RHEL). We are now looking to expand on that by creating the resources needed by other communities to come together and be able to build on the CentOS Linux platform. And today we start the process by delivering a clear governance model, increased transparency and access. In the coming weeks we aim to publish our own roadmap that includes variants of the core CentOS Linux.", + "documentation_url": "https://wiki.centos.org/", + "images": [ + { + "download_url": "http://www.osboxes.org/centos/", + "filename": "CentOS 7-1611 (64bit).vmdk", + "filesize": 4365877248, + "md5sum": "1da15f6144eab25c8546f81dd1c34092", + "version": "7-1611" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Centos", + "port_name_format": "eth{0}", + "product_name": "Centos", + "product_url": "https://www.centos.org/download/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "spice", + "hda_disk_interface": "ide", + "kvm": "require", + "options": "-vga qxl", + "ram": 2048 + }, + "registry_version": 5, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Username: osboxes.org\nPassword: osboxes.org", + "vendor_name": "CentOS Linux", + "vendor_url": "https://www.centos.org/", + "versions": [ + { + "images": { + "hda_disk_image": "CentOS 7-1611 (64bit).vmdk" + }, + "name": "7-1611" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Ubuntu is a full-featured Linux operating system which is based on Debian distribution and freely available with both community and professional support, it comes with Unity as its default desktop environment. There are other flavors of Ubuntu available with other desktops as default like Ubuntu Gnome, Lubuntu, Xubuntu, and so on. A tightly-integrated selection of excellent applications is included, and an incredible variety of add-on software is just a few clicks away. A default installation of Ubuntu contains a wide range of software that includes LibreOffice, Firefox, Empathy, Transmission, etc.", + "documentation_url": "https://help.ubuntu.com", + "images": [ + { + "download_url": "http://www.osboxes.org/ubuntu/", + "filename": "Ubuntu_17.04-VM-64bit.vmdk", + "filesize": 4792123392, + "md5sum": "5c82d69c49ba08179e9a94901f67da1f", + "version": "17.04" + }, + { + "download_url": "http://www.osboxes.org/ubuntu/", + "filename": "Ubuntu_16.10_Yakkety-VM-64bit.vmdk", + "filesize": 9133293568, + "md5sum": "c835f24dbb86f5f61c78d992ed38b6b1", + "version": "16.10" + }, + { + "download_url": "http://www.osboxes.org/ubuntu/", + "filename": "Ubuntu_16.04.3-VM-64bit.vmdk", + "filesize": 4302110720, + "md5sum": "45bccf63f2777e492f022dbf025f67d0", + "version": "16.04" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Ubuntu Desktop Guest", + "port_name_format": "eth{0}", + "product_name": "Ubuntu", + "product_url": "https://www.ubuntu.com/desktop", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "options": "-vga virtio", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Username: osboxes\nPassword: osboxes.org", + "vendor_name": "Canonical Inc.", + "vendor_url": "https://www.ubuntu.com", + "versions": [ + { + "images": { + "hda_disk_image": "Ubuntu_17.04-VM-64bit.vmdk" + }, + "name": "17.04" + }, + { + "images": { + "hda_disk_image": "Ubuntu_16.10_Yakkety-VM-64bit.vmdk" + }, + "name": "16.10" + }, + { + "images": { + "hda_disk_image": "Ubuntu_16.04.3-VM-64bit.vmdk" + }, + "name": "16.04" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Dell Networking OS9 (formerly FTOS).\nOS9 powers the Dell Networking product portfolio and has been hardened in some of the largest and most demanding environments in the world to meet stringent reliability, scalability and serviceability requirements. \n\nDownload and uncompress zip files from the Dell support site - corresponding to the FTOS/OS9 image name. Please 'Select FTOS for S-Series OS-EMULATOR'. Import the resulting ISO image.", + "first_port_name": "Management0/0", + "images": [ + { + "compression": "zip", + "download_url": "https://www.force10networks.com/CSPortal20/Software/SSeriesDownloads.aspx", + "filename": "FTOS-SI-9.8.0.0.iso", + "filesize": 108115968, + "md5sum": "b9b50eda0a73407dc381792ff7975e24", + "version": "9.8.0" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Dell OS9", + "port_name_format": "fortyGigE0/{0}", + "product_name": "Dell OS9", + "product_url": "http://www.dell.com/us/business/p/open-platform-software/pd", + "qemu": { + "adapter_type": "e1000", + "adapters": 6, + "arch": "i386", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "ide", + "kvm": "require", + "ram": 512 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "usage": "Make sure the Boot priority of the configuration template is HDD or CD.\n\nAbort the BCM process and format the flash after first boot by entering these commands:\nen\nformat flash:\n\nSometimes the flash device is not available after boot.", + "vendor_name": "Dell Inc.", + "vendor_url": "http://www.dell.com/", + "versions": [ + { + "images": { + "cdrom_image": "FTOS-SI-9.8.0.0.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.8.0" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "VyOS is a community fork of Vyatta, a Linux-based network operating system that provides software-based network routing, firewall, and VPN functionality.", + "documentation_url": "http://vyos.net/wiki/User_Guide", + "images": [ + { + "direct_download_url": "http://dev.packages.vyos.net/iso/preview/1.2.0-beta1/vyos-1.2.0-beta1-amd64.iso", + "download_url": "http://dev.packages.vyos.net/iso/preview/1.2.0-beta1/", + "filename": "vyos-1.2.0-beta1-amd64.iso", + "filesize": 243269632, + "md5sum": "c2906532d4c7a0d29b61e8eab326d6c7", + "version": "1.2.0-beta1" + }, + { + "direct_download_url": "https://downloads.vyos.io/release/1.1.8/vyos-1.1.8-amd64.iso", + "download_url": "https://downloads.vyos.io/?dir=release/1.1.8", + "filename": "vyos-1.1.8-amd64.iso", + "filesize": 241172480, + "md5sum": "95a141d4b592b81c803cdf7e9b11d8ea", + "version": "1.1.8" + }, + { + "direct_download_url": "https://downloads.vyos.io/release/1.1.7/vyos-1.1.7-amd64.iso", + "download_url": "https://downloads.vyos.io/?dir=release/1.1.7/", + "filename": "vyos-1.1.7-amd64.iso", + "filesize": 245366784, + "md5sum": "9a7f745a0b0db0d4f1d9eee2a437fb54", + "version": "1.1.7" + }, + { + "direct_download_url": "https://downloads.vyos.io/release/1.1.6/vyos-1.1.6-amd64.iso", + "download_url": "hhttps://downloads.vyos.io/?dir=release/1.1.6/", + "filename": "vyos-1.1.6-amd64.iso", + "filesize": 245366784, + "md5sum": "3128954d026e567402a924c2424ce2bf", + "version": "1.1.6" + }, + { + "direct_download_url": "https://downloads.vyos.io/release/1.1.5/vyos-1.1.5-amd64.iso", + "download_url": "https://downloads.vyos.io/?dir=release/1.1.5/", + "filename": "vyos-1.1.5-amd64.iso", + "filesize": 247463936, + "md5sum": "193179532011ceaa87ee725bd8f22022", + "version": "1.1.5" + }, + { + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty8G.qcow2", + "filesize": 197120, + "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "VyOS", + "port_name_format": "eth{0}", + "product_name": "VyOS", + "product_url": "http://vyos.net/", + "qemu": { + "adapter_type": "e1000", + "adapters": 3, + "arch": "x86_64", + "boot_priority": "dc", + "console_type": "telnet", + "kvm": "allow", + "ram": 512 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "Default username/password is vyos/vyos. At first boot the router will start from the cdrom, login and then type install system and follow the instructions.", + "vendor_name": "Linux", + "vendor_url": "http://vyos.net/", + "versions": [ + { + "images": { + "cdrom_image": "vyos-1.2.0-beta1-amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "1.2.0-beta1" + }, + { + "images": { + "cdrom_image": "vyos-1.1.8-amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "1.1.8" + }, + { + "images": { + "cdrom_image": "vyos-1.1.7-amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "1.1.7" + }, + { + "images": { + "cdrom_image": "vyos-1.1.6-amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "1.1.6" + }, + { + "images": { + "cdrom_image": "vyos-1.1.5-amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "1.1.5" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco 7200 Router", + "documentation_url": "http://www.cisco.com/c/en/us/products/routers/7200-series-routers/index.html", + "dynamips": { + "midplane": "vxr", + "npe": "npe-400", + "nvram": 512, + "platform": "c7200", + "ram": 512, + "slot0": "C7200-IO-FE", + "startup_config": "ios_base_startup-config.txt" + }, + "images": [ + { + "filename": "c7200-adventerprisek9-mz.124-24.T5.image", + "filesize": 102345240, + "md5sum": "6b89d0d804e1f2bb5b8bda66b5692047", + "version": "124-24.T5" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco 7200", + "product_name": "7200", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "idlepc": "0x606df838", + "images": { + "image": "c7200-adventerprisek9-mz.124-24.T5.image" + }, + "name": "124-24.T5" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "CoreOS is designed for security, consistency, and reliability. Instead of installing packages via yum or apt, CoreOS uses Linux containers to manage your services at a higher level of abstraction. A single service's code and all dependencies are packaged within a container that can be run on one or many CoreOS machines.", + "documentation_url": "https://coreos.com/docs/", + "images": [ + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1911.5.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1911.5.0/", + "filename": "coreos_production_qemu_image.1911.5.0.img", + "filesize": 940507136, + "md5sum": "3b5b33697cfc545d8eb9fb461c612e76", + "version": "1911.5.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1855.5.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1855.5.0/", + "filename": "coreos_production_qemu_image.1855.5.0.img", + "filesize": 924319744, + "md5sum": "6b5b06bc47446277c5c536c09b5a7988", + "version": "1855.5.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1688.5.3/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1688.5.3/", + "filename": "coreos_production_qemu_image.1688.5.3.img", + "filesize": 867368960, + "md5sum": "f1015a9573fb6e378d2a5e86b4243acd", + "version": "1688.5.3" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1632.2.1/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1632.2.1/", + "filename": "coreos_production_qemu_image.1632.2.1.img", + "filesize": 885719040, + "md5sum": "facd05ca85eb87e2dc6aefd6779f6806", + "version": "1632.2.1" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1576.4.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1576.4.0/", + "filename": "coreos_production_qemu_image.1576.4.0.img", + "filesize": 849739776, + "md5sum": "7d3c647807afe1f18fd0c76730e612b4", + "version": "1576.4.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1520.8.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1520.8.0/", + "filename": "coreos_production_qemu_image.1520.8.0.img", + "filesize": 842661888, + "md5sum": "a69fb2cd3ae475f9afbc268f7d391e83", + "version": "1520.8.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1465.7.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1465.7.0/", + "filename": "coreos_production_qemu_image.1465.7.0.img", + "filesize": 796590080, + "md5sum": "1db77d47e76d3d9082846584e0f4b4bc", + "version": "1465.7.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1409.7.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1409.7.0/", + "filename": "coreos_production_qemu_image.1409.7.0.img", + "filesize": 812187648, + "md5sum": "b8db4a07bac71468ed47bd09bedc1bdf", + "version": "1409.7.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1353.8.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1353.8.0/", + "filename": "coreos_production_qemu_image.1353.8.0.img", + "filesize": 795934720, + "md5sum": "f84bf924d7b30190539a14e14d94d4f8", + "version": "1353.8.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1353.7.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1353.7.0/", + "filename": "coreos_production_qemu_image.1353.7.0.img", + "filesize": 796852224, + "md5sum": "2d4ecc377b41ee5b1ffd90090548ebc0", + "version": "1353.7.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.9.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1235.9.0/", + "filename": "coreos_production_qemu_image.1235.9.0.img", + "filesize": 795869184, + "md5sum": "77a256ceaa0da6960391c03ebfe5388c", + "version": "1235.9.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.8.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1235.8.0/", + "filename": "coreos_production_qemu_image.1235.8.0.img", + "filesize": 785252352, + "md5sum": "0eec78690fd9f6d3b9e8d8ff41bc10b5", + "version": "1235.8.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.6.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1235.6.0/", + "filename": "coreos_production_qemu_image.1235.6.0.img", + "filesize": 784990208, + "md5sum": "2ff81c223be4bfa40c9ef765bb0d7f26", + "version": "1235.6.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.5.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1235.5.0/", + "filename": "coreos_production_qemu_image.1235.5.0.img", + "filesize": 792592384, + "md5sum": "11aa05a27654b66a4e6dfb1e9f1c7ff9", + "version": "1235.5.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.4.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1235.4.0/", + "filename": "coreos_production_qemu_image.1235.4.0.img", + "filesize": 787415040, + "md5sum": "c59930b3b1ad0716c91a62ac56234d97", + "version": "1235.4.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1185.5.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1185.5.0/", + "filename": "coreos_production_qemu_image.1185.5.0.img", + "filesize": 754843648, + "md5sum": "97b6eaa9857c68c67e56d7b742d43f5e", + "version": "1185.5.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1185.3.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/1185.3.0/", + "filename": "coreos_production_qemu_image.1185.3.0.img", + "filesize": 753926144, + "md5sum": "a1b6b69e5a58a1900b145b024340eff0", + "version": "1185.3.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/835.9.0/coreos_production_qemu_image.img.bz2", + "download_url": "http://stable.release.core-os.net/amd64-usr/835.9.0/", + "filename": "coreos_production_qemu_image.835.9.img", + "filesize": 635633664, + "md5sum": "768a5df35784a014ba06609da88f5158", + "version": "835.9.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "CoreOS", + "product_name": "CoreOS", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "arch": "x86_64", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdd_disk_interface": "ide", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "vendor_name": "CoreOS, Inc", + "vendor_url": "https://coreos.com/", + "versions": [ + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1911.5.0.img" + }, + "name": "1911.5.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1855.5.0.img" + }, + "name": "1855.5.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1688.5.3.img" + }, + "name": "1688.5.3" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1632.2.1.img" + }, + "name": "1632.2.1" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1576.4.0.img" + }, + "name": "1576.4.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1520.8.0.img" + }, + "name": "1520.8.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1465.7.0.img" + }, + "name": "1465.7.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1409.7.0.img" + }, + "name": "1409.7.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1353.8.0.img" + }, + "name": "1353.8.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1353.7.0.img" + }, + "name": "1353.7.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1235.9.0.img" + }, + "name": "1235.9.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1235.8.0.img" + }, + "name": "1235.8.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1235.6.0.img" + }, + "name": "1235.6.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1235.5.0.img" + }, + "name": "1235.5.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1235.4.0.img" + }, + "name": "1235.4.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1185.5.0.img" + }, + "name": "1185.5.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.1185.3.0.img" + }, + "name": "1185.3.0" + }, + { + "images": { + "hda_disk_image": "coreos_production_qemu_image.835.9.img" + }, + "name": "835.9.0" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "The vQFX10000 makes it easy for you to try out our physical QFX10000 high-performance data center switch without the wait for physical delivery. Although the virtual version has limited performance relative to the physical switch, it lets you quickly emulate the same features for the control plane of the physical switch, or both its control and data planes.", + "documentation_url": "http://www.juniper.net/techpubs/", + "images": [ + { + "download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", + "filename": "jinstall-vqfx-10-f-17.4R1.16.img", + "filesize": 553910272, + "md5sum": "dd83313b0f5beaf68488ed3d5e1e5240", + "version": "17.4R1" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", + "filename": "vqfx10k-re-15.1X53-D60.vmdk", + "filesize": 355542528, + "md5sum": "758669e88213fbd7943f5da7f6d7bd59", + "version": "15.1X53-D60" + } + ], + "maintainer": "none", + "maintainer_email": "developers@gns3.net", + "name": "Juniper vQFX RE", + "port_name_format": "em{0}", + "product_name": "Juniper vQFX RE", + "product_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", + "qemu": { + "adapter_type": "e1000", + "adapters": 12, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "options": "-nographic -smp 2", + "ram": 1024 + }, + "registry_version": 3, + "status": "experimental", + "symbol": "juniper-vqfx.svg", + "usage": "Initial username is root, password is Juniper (capitol J).\n\nUSAGE INSTRUCTIONS\n\nConnect the first interface (em0) to your admin VLAN. Connect the second interface (em1) directly to the second interface (em1) of the PFE. The switch ports connect here on the RE", + "vendor_name": "Juniper", + "vendor_url": "https://www.juniper.net/us/en/", + "versions": [ + { + "images": { + "hda_disk_image": "jinstall-vqfx-10-f-17.4R1.16.img" + }, + "name": "17.4R1" + }, + { + "images": { + "hda_disk_image": "vqfx10k-re-15.1X53-D60.vmdk" + }, + "name": "15.1X53-D60" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Take control of your online applications with Brocade virtual Traffic Manager (Developer Edition). Enhance customer experience, inspect traffic in real-time, control service levels to differentiate users and services, and reduce your costs with an extensible delivery platform that can grow with your business using ADC-as-a-Service. A fully functional Developer Edition which needs no license key, is limited to 1 Mbps/100 SSL tps throughput, and has access to the Brocade Community support web pages.", + "documentation_url": "http://www.brocade.com/en/products-services/software-networking/application-delivery-controllers/virtual-traffic-manager.html", + "images": [ + { + "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", + "filename": "VirtualTrafficManager-174.qcow2", + "filesize": 2036465664, + "md5sum": "3c44f385e5faf310ca8e3d46bf4e0564", + "version": "17.4" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", + "filename": "VirtualTrafficManager-173.qcow2", + "filesize": 2022178816, + "md5sum": "c3425d8ec3f8c7789c0a88b8ed6bdf3b", + "version": "17.3" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", + "filename": "VirtualTrafficManager-172.qcow2", + "filesize": 2039742464, + "md5sum": "00d3ab0422eb786bcbd77f5841220956", + "version": "17.2" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", + "filename": "VirtualTrafficManager-171.qcow2", + "filesize": 1771175936, + "md5sum": "397672218292e739bd33b203a91dbcf4", + "version": "17.1" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", + "filename": "VirtualTrafficManager-111.qcow2", + "filesize": 12189564928, + "md5sum": "3c9c63e2071d79c64cb4b17b355d2582", + "version": "11.1" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", + "filename": "VirtualTrafficManager-110.img", + "filesize": 12191531008, + "md5sum": "7fb0bab8e1cf09076e87270b1418ec81", + "version": "11.0" + }, + { + "download_url": "http://my.brocade.com/", + "filename": "VirtualTrafficManager-104R1.img", + "filesize": 12193562624, + "md5sum": "395542073d6afb9e62e7d5a7b339c3b3", + "version": "10.4R1" + }, + { + "download_url": "http://my.brocade.com/", + "filename": "VirtualTrafficManager-104.img", + "filesize": 12190220288, + "md5sum": "88e31b072e17de12e241ef442bb5faae", + "version": "10.4" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "vTM DE", + "port_name_format": "eth{0}", + "product_name": "vTM DE", + "product_url": "http://www.brocade.com/en/products-services/software-networking/application-delivery-controllers/virtual-traffic-manager.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 8, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "loadbalancer.svg", + "usage": "Credentials: admin / admin. The device gets its initial IP address using DHCP. After getting an IP address, you can access the initial configuration using the WebUI at https://IP_ADDRESS:9090", + "vendor_name": "Brocade", + "vendor_url": "http://www.brocade.com/", + "versions": [ + { + "images": { + "hda_disk_image": "VirtualTrafficManager-174.qcow2" + }, + "name": "17.4" + }, + { + "images": { + "hda_disk_image": "VirtualTrafficManager-173.qcow2" + }, + "name": "17.3" + }, + { + "images": { + "hda_disk_image": "VirtualTrafficManager-172.qcow2" + }, + "name": "17.2" + }, + { + "images": { + "hda_disk_image": "VirtualTrafficManager-171.qcow2" + }, + "name": "17.1" + }, + { + "images": { + "hda_disk_image": "VirtualTrafficManager-111.qcow2" + }, + "name": "11.1" + }, + { + "images": { + "hda_disk_image": "VirtualTrafficManager-110.img" + }, + "name": "11.0" + }, + { + "images": { + "hda_disk_image": "VirtualTrafficManager-104R1.img" + }, + "name": "10.4R1" + }, + { + "images": { + "hda_disk_image": "VirtualTrafficManager-104.img" + }, + "name": "10.4" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "vThunder, part of A10 Networks' award-winning A10 Thunder and AX Series Application Delivery Controller (ADC) family, is designed to meet the growing needs of organizations that require a flexible and easy-to-deploy application delivery and server load balancer solution running within a virtualized infrastructure.", + "documentation_url": "https://www.a10networks.com/support", + "first_port_name": "mgmt", + "images": [ + { + "download_url": "https://www.a10networks.com/vthunder-embed", + "filename": "vThunder_410_P9.qcow2", + "filesize": 6311706624, + "md5sum": "6ef0f69ba7a099a7f43b5815c2abc691", + "version": "4.1.0.P9" + }, + { + "download_url": "https://www.a10networks.com/vthunder-embed", + "filename": "vThunder_410_P3.qcow2", + "filesize": 6098780160, + "md5sum": "daacefa4e0eb1cad9b253926624be4b9", + "version": "4.1.0.P3" + }, + { + "download_url": "https://www.a10networks.com/vthunder-embed", + "filename": "vth401.GA.12G_Disk.qcow2", + "filesize": 4768464896, + "md5sum": "311806ad414403359216da6119ddb823", + "version": "4.0.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "A10 vThunder", + "port_name_format": "ethernet {port1}", + "product_name": "A10 vThunder", + "product_url": "https://www.a10networks.com/products/thunder-series-appliances/vthunder-virtualized-application_delivery_controller/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 4096 + }, + "registry_version": 3, + "status": "stable", + "symbol": "loadbalancer.svg", + "usage": "Default credentials:\n- CLI: admin / a10.\n- Enable mode: \n\nDefault management IP: 172.31.31.31/24", + "vendor_name": "A10", + "vendor_url": "https://www.a10networks.com/", + "versions": [ + { + "images": { + "hda_disk_image": "vThunder_410_P9.qcow2" + }, + "name": "4.1.0.P9" + }, + { + "images": { + "hda_disk_image": "vThunder_410_P3.qcow2" + }, + "name": "4.1.0.P3" + }, + { + "images": { + "hda_disk_image": "vth401.GA.12G_Disk.qcow2" + }, + "name": "4.0.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "FreeNAS is a Free and Open Source Network Attached Storage (NAS) software appliance. This means that you can use FreeNAS to share data over file-based sharing protocols, including CIFS for Windows users, NFS for Unix-like operating systems, and AFP for Mac OS X users. FreeNAS uses the ZFS file system to store, manage, and protect data. ZFS provides advanced features like snapshots to keep old versions of files, incremental remote backups to keep your data safe on another device without huge file transfers, and intelligent compression, which reduces the size of files so quickly and efficiently that it actually helps transfers happen faster.", + "documentation_url": "https://doc.freenas.org/9.10/freenas.html", + "images": [ + { + "direct_download_url": "https://download.freenas.org/11.2/STABLE/RELEASE/x64/FreeNAS-11.2-RELEASE.iso", + "download_url": "http://www.freenas.org/download/", + "filename": "FreeNAS-11.2-RELEASE.iso", + "filesize": 603410432, + "md5sum": "bf4a9ebb19313c3d45f84c1550477727", + "version": "11.2" + }, + { + "direct_download_url": "https://download.freenas.org/11/11.1-U6/x64/FreeNAS-11.1-U6.iso", + "download_url": "http://www.freenas.org/download/", + "filename": "FreeNAS-11.1-U6.iso", + "filesize": 636065792, + "md5sum": "633d6444cad903c707983b54e04fc053", + "version": "11.1 U6" + }, + { + "direct_download_url": "https://download.freenas.org/11/11.1-U4/x64/FreeNAS-11.1-U4.iso", + "download_url": "http://www.freenas.org/download/", + "filename": "FreeNAS-11.1-U4.iso", + "filesize": 633833472, + "md5sum": "d75623e5671dbc82f32f4b4f8d46092f", + "version": "11.1 U4" + }, + { + "direct_download_url": "http://download.freenas.org/11/11.1-RELEASE/x64/FreeNAS-11.1-RELEASE.iso", + "download_url": "http://www.freenas.org/download/", + "filename": "FreeNAS-11.1-U1.iso", + "filesize": 626601984, + "md5sum": "ccbd9990a5878d35c6bc0cc6eea34b16", + "version": "11.1 U1" + }, + { + "direct_download_url": "http://download.freenas.org/11/11.1-RELEASE/x64/FreeNAS-11.1-RELEASE.iso", + "download_url": "http://www.freenas.org/download/", + "filename": "FreeNAS-11.1-RELEASE.iso", + "filesize": 626761728, + "md5sum": "67bea5816bc889169e5e3054362b2053", + "version": "11.1" + }, + { + "direct_download_url": "http://download.freenas.org/11/11.0-U4/x64/FreeNAS-11.0-U4.iso", + "download_url": "http://www.freenas.org/download/", + "filename": "FreeNAS-11.0-U4.iso", + "filesize": 567312384, + "md5sum": "4c210f1a6510d1fa95257d81ef569ff8", + "version": "11.0 U4" + }, + { + "direct_download_url": "https://download.freenas.org/9.10/STABLE/latest/x64/FreeNAS-9.10.1-U4.iso", + "download_url": "http://www.freenas.org/download/", + "filename": "FreeNAS-9.10.1-U4.iso", + "filesize": 533098496, + "md5sum": "b4fb14513dcbb4eb4c5596c5911ca9cc", + "version": "9.10 U4" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FreeNAS", + "port_name_format": "eth{0}", + "product_name": "FreeNAS", + "product_url": "http://www.openfiler.com/products", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "ide", + "hdb_disk_interface": "ide", + "kvm": "require", + "ram": 8192 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "vendor_name": "iXsystems", + "vendor_url": "http://www.freenas.org", + "versions": [ + { + "images": { + "cdrom_image": "FreeNAS-11.2-RELEASE.iso", + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "11.2" + }, + { + "images": { + "cdrom_image": "FreeNAS-11.1-U6.iso", + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "11.1 U6" + }, + { + "images": { + "cdrom_image": "FreeNAS-11.1-U4.iso", + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "11.1 U4" + }, + { + "images": { + "cdrom_image": "FreeNAS-11.1-U1.iso", + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "11.1 U1" + }, + { + "images": { + "cdrom_image": "FreeNAS-11.1-RELEASE.iso", + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "11.1" + }, + { + "images": { + "cdrom_image": "FreeNAS-11.0-U4.iso", + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "11.0 U4" + }, + { + "images": { + "cdrom_image": "FreeNAS-9.10.1-U4.iso", + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "9.10 U4" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "Cisco Virtual IOS L2 allows user to run a IOS switching image on a standard computer.", + "images": [ + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "vios_l2-adventerprisek9-m.03.2017.qcow2", + "filesize": 41157632, + "md5sum": "8f14b50083a14688dec2fc791706bb3e", + "version": "15.2(20170321:233949)" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "vios_l2-adventerprisek9-m.vmdk.SSA.152-4.0.55.E", + "filesize": 96862208, + "md5sum": "1a3a21f5697cae64bb930895b986d71e", + "version": "15.2.4055" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco IOSvL2", + "port_name_format": "Gi{1}/{0}", + "port_segment_size": 4, + "product_name": "IOSvL2", + "product_url": "http://virl.cisco.com/", + "qemu": { + "adapter_type": "e1000", + "adapters": 16, + "arch": "x86_64", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 768 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "There is no default password and enable password. There is no default configuration present.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "vios_l2-adventerprisek9-m.03.2017.qcow2" + }, + "name": "15.2(20170321:233949)" + }, + { + "images": { + "hda_disk_image": "vios_l2-adventerprisek9-m.vmdk.SSA.152-4.0.55.E" + }, + "name": "15.2.4055" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "The Cisco ISE platform is a comprehensive, next-generation, contextually-based access control solution. Cisco ISE offers authenticated network access, profiling, posture, guest management, and security group access services along with monitoring, reporting, and troubleshooting capabilities on a single physical or virtual appliance.", + "documentation_url": "http://www.cisco.com/c/en/us/support/security/identity-services-engine/tsd-products-support-series-home.html", + "images": [ + { + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.2.0", + "filename": "ise-2.2.0.470.SPA.x86_64.iso", + "filesize": 8044992512, + "md5sum": "7fe5e730d0a51ef66e69d1463717ff3f", + "version": "2.2.0.470" + }, + { + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.1.0", + "filename": "ise-2.1.0.474.SPA.x86_64.iso", + "filesize": 6161475584, + "md5sum": "8dc844696790f2f5f37054899fab3e2a", + "version": "2.1.0.474" + }, + { + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.0.1", + "filename": "ise-2.0.1.130.SPA.x86_64.iso", + "filesize": 5129990144, + "md5sum": "25ac842fdbb61f6e75f2f8b26beea28e", + "version": "2.0.1.130" + }, + { + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.0", + "filename": "ise-2.0.0.306.SPA.x86_64.iso", + "filesize": 5088827392, + "md5sum": "b7a454ee235db29b5c208b19bfd1fbd1", + "version": "2.0.0.306" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty200G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty200G.qcow2", + "filesize": 200192, + "md5sum": "d1686d2f25695dee32eab9a6f4652c7c", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco ISE", + "port_name_format": "GigabitEthernet{0}", + "product_name": "Identity Services Engine", + "product_url": "http://www.cisco.com/c/en/us/products/security/identity-services-engine/index.html", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "ide", + "kvm": "require", + "options": "-smp 2 -smbios type=1,product=KVM", + "ram": 4096 + }, + "registry_version": 3, + "status": "experimental", + "symbol": "cisco-ise.svg", + "usage": "Starting ISE will start an installation of ISE onto a blank 200GB Drive. This will take time. The intial username is setup.\n\nThis appliance requires KVM. You may try it on a system without KVM, but it will run really slow, if at all.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "cdrom_image": "ise-2.2.0.470.SPA.x86_64.iso", + "hda_disk_image": "empty200G.qcow2" + }, + "name": "2.2.0.470" + }, + { + "images": { + "cdrom_image": "ise-2.1.0.474.SPA.x86_64.iso", + "hda_disk_image": "empty200G.qcow2" + }, + "name": "2.1.0.474" + }, + { + "images": { + "cdrom_image": "ise-2.0.1.130.SPA.x86_64.iso", + "hda_disk_image": "empty200G.qcow2" + }, + "name": "2.0.1.130" + }, + { + "images": { + "cdrom_image": "ise-2.0.0.306.SPA.x86_64.iso", + "hda_disk_image": "empty200G.qcow2" + }, + "name": "2.0.0.306" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "The VOSS VM is a software emulation of a VSP8K switch.", + "documentation_url": "http://www.extremenetworks.com/support/documentation", + "first_port_name": "Mgmt", + "images": [ + { + "direct_download_url": "https://stackingtool.extremenetworks.com/github/VOSSGNS3.7.1.0.0.qcow2", + "filename": "VOSSGNS3.7.1.0.0.qcow2", + "filesize": 193724416, + "md5sum": "7bb2974efe1a1ab857debd9fa894dbe7", + "version": "voss_7.1.0.0" + }, + { + "direct_download_url": "https://stackingtool.extremenetworks.com/github/VOSSGNS3.7.0.0.0.img", + "filename": "VOSSGNS3.7.0.0.0.img", + "filesize": 419430400, + "md5sum": "65fe97461156aa88c836a90be1287649", + "version": "voss_7.0.0.0" + } + ], + "maintainer": "Extreme Networks", + "maintainer_email": "voss@extremenetworks.com", + "name": "VOSS VM", + "port_name_format": "1/{port1}", + "product_name": "VOSS_VM", + "qemu": { + "adapter_type": "e1000", + "adapters": 9, + "arch": "i386", + "console_type": "telnet", + "hda_disk_interface": "ide", + "kvm": "allow", + "options": "-nographic", + "ram": 1024 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "Boot up and login is rwa/rwa", + "vendor_name": "Extreme Networks", + "vendor_url": "http://www.extremenetworks.com", + "versions": [ + { + "images": { + "hda_disk_image": "VOSSGNS3.7.1.0.0.qcow2" + }, + "name": "7.1.0.0" + }, + { + "images": { + "hda_disk_image": "VOSSGNS3.7.0.0.0.img" + }, + "name": "7.0.0.0" + } + ] + }, + { + "availability": "free-to-try", + "builtin": true, + "category": "guest", + "description": "Microsoft Windows, or simply Windows, is a metafamily of graphical operating systems developed, marketed, and sold by Microsoft. It consists of several families of operating systems, each of which cater to a certain sector of the computing industry with the OS typically associated with IBM PC compatible architecture.", + "documentation_url": "https://technet.microsoft.com/en-us/library/cc498727.aspx", + "images": [ + { + "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", + "filename": "MSEdge-Win10-VMWare-disk1.vmdk", + "filesize": 5636608512, + "md5sum": "fef74c69e1949480d4e2095324a169af", + "version": "10 w/ Edge" + }, + { + "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", + "filename": "MSEdge_-_Win10_preview.vmdk", + "filesize": 10907287552, + "md5sum": "e06d97b871581d91b7363bf72a81553d", + "version": "10 w/ Edge" + }, + { + "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", + "filename": "IE11_-_Win8.1-disk1.vmdk", + "filesize": 5704344064, + "md5sum": "6c8691c7d58bf2c33f6ca242ace6b9bd", + "version": "8.1 w/ IE11" + }, + { + "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", + "filename": "IE11_-_Win7-disk1.vmdk", + "filesize": 4101495296, + "md5sum": "5733cc93a6ed756c2358f0a383b411a8", + "version": "7 w/ IE11" + }, + { + "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", + "filename": "IE10_-_Win7-disk1.vmdk", + "filesize": 4062174208, + "md5sum": "ed18b5903fb7d778b847c8d1cef807c4", + "version": "7 w/ IE10" + }, + { + "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", + "filename": "IE9_-_Win7-disk1.vmdk", + "filesize": 4040829440, + "md5sum": "82370cfa215002a49651b773a3a569f2", + "version": "7 w/ IE9" + }, + { + "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", + "filename": "IE8_-_Win7-disk1.vmdk", + "filesize": 4228026368, + "md5sum": "63456b42eb8e184b3e7c675645a3c32c", + "version": "7 w/ IE8" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Windows", + "port_name_format": "NIC{port1}", + "product_name": "Windows", + "product_url": "https://www.microsoft.com/en-us/windows", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "sata", + "kvm": "require", + "ram": 1024 + }, + "registry_version": 4, + "status": "stable", + "symbol": "microsoft.svg", + "usage": "These virtual machines expire after 90 days; i.e. you have to re-create them in your project after this time but you don't have to re-import the appliance.\n\nDefault credentials: IEUser / Passw0rd!", + "vendor_name": "Microsoft", + "vendor_url": "http://www.microsoft.com/", + "versions": [ + { + "images": { + "hda_disk_image": "MSEdge-Win10-VMWare-disk1.vmdk" + }, + "name": "10 w/ Edge" + }, + { + "images": { + "hda_disk_image": "MSEdge_-_Win10_preview.vmdk" + }, + "name": "10 w/ Edge (Preview)" + }, + { + "images": { + "hda_disk_image": "IE11_-_Win8.1-disk1.vmdk" + }, + "name": "8.1 w/ IE11" + }, + { + "images": { + "hda_disk_image": "IE11_-_Win7-disk1.vmdk" + }, + "name": "7 w/ IE11" + }, + { + "images": { + "hda_disk_image": "IE10_-_Win7-disk1.vmdk" + }, + "name": "7 w/ IE10" + }, + { + "images": { + "hda_disk_image": "IE9_-_Win7-disk1.vmdk" + }, + "name": "7 w/ IE9" + }, + { + "images": { + "hda_disk_image": "IE8_-_Win7-disk1.vmdk" + }, + "name": "7 w/ IE8" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "The Adaptive Security Virtual Appliance is a virtualized network security solution based on the market-leading Cisco ASA 5500-X Series firewalls. It supports both traditional and next-generation software-defined network (SDN) and Cisco Application Centric Infrastructure (ACI) environments to provide policy enforcement and threat inspection across heterogeneous multisite environments.", + "documentation_url": "http://www.cisco.com/c/en/us/support/security/virtual-adaptive-security-appliance-firewall/products-installation-guides-list.html", + "first_port_name": "Management0/0", + "images": [ + { + "download_url": "https://software.cisco.com/download/home/286119613/type/280775065/release/9.9.2", + "filename": "asav992.qcow2", + "filesize": 204865536, + "md5sum": "0cba453dbf70313d8d63a00700618f52", + "version": "9.9.2" + }, + { + "download_url": "https://software.cisco.com/download/home/286119613/type/280775065/release/9.8.3", + "filename": "asav983.qcow2", + "filesize": 199491584, + "md5sum": "f9cf40b2d555a1bea6d36bc83f06ea33", + "version": "9.8.3" + }, + { + "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", + "filename": "asav981-5.qcow2", + "filesize": 193069056, + "md5sum": "77b3ca856dd2df476bcda34e218425ca", + "version": "9.8.1-5" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286119613&flowid=50242&softwareid=280775065&release=9.8.1&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "asav981.qcow2", + "filesize": 193069056, + "md5sum": "8d3612fe22b1a7dec118010e17e29411", + "version": "9.8.1" + }, + { + "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", + "filename": "asav971-8.qcow2", + "filesize": 197066752, + "md5sum": "b2486c8d0f6fda149ce877208b816818", + "version": "9.7.1-8" + }, + { + "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", + "filename": "asav971-4.qcow2", + "filesize": 197066752, + "md5sum": "f9a671d1ceaf983f7241f19df15e787f", + "version": "9.7.1-4" + }, + { + "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", + "filename": "asav971-2.qcow2", + "filesize": 199753728, + "md5sum": "ff036b23f5dbb2bcf1e6530476cc1989", + "version": "9.7.1-2" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "asav971.qcow2", + "filesize": 198443008, + "md5sum": "07eef9b8ca489a8ad37448fadf45a673", + "version": "9.7.1" + }, + { + "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", + "filename": "asav963-8.qcow2", + "filesize": 168427520, + "md5sum": "8b8a45b94a302dae8076e7ec90c7d4c2", + "version": "9.6.3-8" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286119613&flowid=50242&softwareid=280775065&release=9.6.3&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "asav963-1.qcow2", + "filesize": 172294144, + "md5sum": "d6a5c8d7bff5e69c5987ca664a52dbd8", + "version": "9.6.3-1" + }, + { + "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", + "filename": "asav962-13.qcow2", + "filesize": 177668096, + "md5sum": "2a6bec030fcaef31b611051180cc142c", + "version": "9.6.2-13" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "asav962.qcow2", + "filesize": 177274880, + "md5sum": "dfb8110ce38da4588e994865d5a9656a", + "version": "9.6.2" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco ASAv", + "port_name_format": "Gi0/{0}", + "product_name": "ASAv", + "product_url": "http://www.cisco.com/c/en/us/products/security/virtual-adaptive-security-appliance-firewall/index.html", + "qemu": { + "adapter_type": "e1000", + "adapters": 8, + "arch": "x86_64", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "There is no default password and enable password. A default configuration is present. ASAv goes through a double-boot before becoming active. This is normal and expected.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "asav992.qcow2" + }, + "name": "9.9.2" + }, + { + "images": { + "hda_disk_image": "asav983.qcow2" + }, + "name": "9.8.3" + }, + { + "images": { + "hda_disk_image": "asav981-5.qcow2" + }, + "name": "9.8.1-5" + }, + { + "images": { + "hda_disk_image": "asav981.qcow2" + }, + "name": "9.8.1" + }, + { + "images": { + "hda_disk_image": "asav971-8.qcow2" + }, + "name": "9.7.1-8" + }, + { + "images": { + "hda_disk_image": "asav971-4.qcow2" + }, + "name": "9.7.1-4" + }, + { + "images": { + "hda_disk_image": "asav971-2.qcow2" + }, + "name": "9.7.1-2" + }, + { + "images": { + "hda_disk_image": "asav971.qcow2" + }, + "name": "9.7.1" + }, + { + "images": { + "hda_disk_image": "asav963-8.qcow2" + }, + "name": "9.6.3-8" + }, + { + "images": { + "hda_disk_image": "asav963-1.qcow2" + }, + "name": "9.6.3-1" + }, + { + "images": { + "hda_disk_image": "asav962-13.qcow2" + }, + "name": "9.6.2-13" + }, + { + "images": { + "hda_disk_image": "asav962.qcow2" + }, + "name": "9.6.2" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Ubuntu is a Debian-based Linux operating system, with Unity as its default desktop environment. It is based on free software and named after the Southern African philosophy of ubuntu (literally, \"human-ness\"), which often is translated as \"humanity towards others\" or \"the belief in a universal bond of sharing that connects all humanity\".", + "docker": { + "adapters": 1, + "console_type": "telnet", + "image": "gns3/ubuntu:xenial" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Ubuntu Docker Guest", + "product_name": "Ubuntu", + "registry_version": 3, + "status": "stable", + "symbol": "linux_guest.svg", + "vendor_name": "Canonical", + "vendor_url": "http://www.ubuntu.com" + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "ExtremeXOS was designed from the ground up to meet the needs of large cloud and private data centers, service providers, intelligent, converged enterprise edge networks, and everything in between. It provides the high performance and rich features required by these diverse environments.", + "documentation_url": "http://www.extremenetworks.com/support/documentation", + "first_port_name": "Management", + "images": [ + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.6.1.4.iso", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exosvm-22.6.1.4.iso", + "filesize": 53706752, + "md5sum": "66146aba82575b3879431143b6dc8a35", + "version": "22.6.1.4" + }, + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.5.1.7.iso", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exosvm-22.5.1.7.iso", + "filesize": 51779584, + "md5sum": "132ac87de368ab55d1f496f292338cd4", + "version": "22.5.1.7" + }, + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.4.1.4.iso", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exosvm-22.4.1.4.iso", + "filesize": 49993728, + "md5sum": "2134a511084519a5f8ad00a6f7cd71a9", + "version": "22.4.1.4" + }, + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.2.1.5.iso", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exosvm-22.2.1.5.iso", + "filesize": 44578816, + "md5sum": "bf51fd5b3c5e9dab10a616055265bcf2", + "version": "22.2.1.5" + }, + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.1.1.5.iso", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exosvm-22.1.1.5.iso", + "filesize": 44220416, + "md5sum": "df3897ca2d7c7053582587ed120114fa", + "version": "22.1.1.5" + }, + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/vm-21.1.2.14.iso?raw=true", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exosvm-21.1.2.14.iso", + "filesize": 41101312, + "md5sum": "de0752d56e41d92027ce1fccd604b14b", + "version": "21.1.2.14" + }, + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/vm-21.1.1.4.iso?raw=true", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exosvm-21.1.1.4.iso", + "filesize": 41046016, + "md5sum": "4d5db0e01a39b08775ed6a3e2c8bf663", + "version": "21.1.1.4" + }, + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.2.1.6.iso?raw=true", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exospc-16.2.1.6.iso", + "filesize": 36306944, + "md5sum": "b4be339afb02c03dcb4349630c1adb4f", + "version": "16.2.1.6" + }, + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.1.3.6.iso?raw=true", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exospc-16.1.3.6.iso", + "filesize": 35758080, + "md5sum": "4c17b2bf2a4909527f6c866a68ba406e", + "version": "16.1.3.6" + }, + { + "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.1.2.14.iso?raw=true", + "download_url": "https://github.com/extremenetworks/Virtual_EXOS", + "filename": "exospc-16.1.2.14.iso", + "filesize": 35743744, + "md5sum": "140cdc11f426156ffcbde150b2f46768", + "version": "16.1.2.14" + }, + { + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty8G.qcow2", + "filesize": 197120, + "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "EXOS", + "port_name_format": "Port{port1}", + "product_name": "EXOS", + "product_url": "http://www.extremenetworks.com/product/extremexos-network-operating-system", + "qemu": { + "adapter_type": "rtl8139", + "adapters": 13, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "telnet", + "hda_disk_interface": "ide", + "kvm": "require", + "options": "-smp 2 -cpu core2duo", + "ram": 256 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "You can change the console to telnet after install. Default user: admin (no password set)", + "vendor_name": "Extreme Networks", + "vendor_url": "http://www.extremenetworks.com/", + "versions": [ + { + "images": { + "cdrom_image": "exosvm-22.6.1.4.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "22.6.1.4" + }, + { + "images": { + "cdrom_image": "exosvm-22.5.1.7.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "22.5.1.7" + }, + { + "images": { + "cdrom_image": "exosvm-22.4.1.4.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "22.4.1.4" + }, + { + "images": { + "cdrom_image": "exosvm-22.2.1.5.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "22.2.1.5" + }, + { + "images": { + "cdrom_image": "exosvm-22.1.1.5.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "22.1.1.5" + }, + { + "images": { + "cdrom_image": "exosvm-21.1.2.14.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "21.1.2.14" + }, + { + "images": { + "cdrom_image": "exosvm-21.1.1.4.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "21.1.1.4" + }, + { + "images": { + "cdrom_image": "exospc-16.2.1.6.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "16.2.1.6" + }, + { + "images": { + "cdrom_image": "exospc-16.1.3.6.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "16.1.3.6" + }, + { + "images": { + "cdrom_image": "exospc-16.1.2.14.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "16.1.2.14" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Sophos XG Firewall delivers the ultimate enterprise firewall performance, security, and control.\n\nFastpath packet optimization technology with up to 140Gbps throughput\nRevolutionary Security Heartbeat\u2122 for improved Advanced Threat Protection (ATP) and response\nPatented Layer-8 user identity control and visibility\nUnified App, Web, QoS, and IPS Policy simplifies management\nApp risk factor and user threat quotient monitors risk levels", + "documentation_url": "https://www.sophos.com/en-us/support/documentation/sophos-xg-firewall.aspx", + "images": [ + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-17.1.3_MR-3.KVM-250-PRIMARY.qcow2", + "filesize": 298844160, + "md5sum": "f11c4f63656bcdacbd27c44c52416941", + "version": "17.1.3 MR3" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-17.1.3_MR-3.KVM-250-AUXILARY.qcow2", + "filesize": 59441152, + "md5sum": "fbea59f7aa81f305bea78c86f82dc3a6", + "version": "17.1.3 MR3" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_17.0.2_MR-2.KVM-116-PRIMARY.qcow2", + "filesize": 324599808, + "md5sum": "2555fa6dcdcecad02c9f02dcb1c0c5e5", + "version": "17.0.2 MR2" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_17.0.2_MR-2.KVM-116-AUXILARY.qcow2", + "filesize": 59441152, + "md5sum": "c3ef795423dbfc01771348b0daa75125", + "version": "17.0.2 MR2" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_16.05.4_MR-4.KVM-215-PRIMARY.qcow2", + "filesize": 287113216, + "md5sum": "20535c9e624f42e1977f1e407fbc565e", + "version": "16.05.4 MR4" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_16.05.4_MR-4.KVM-215-AUXILARY.qcow2", + "filesize": 59441152, + "md5sum": "cafac2d997a3ead087d5823b86ce6cb4", + "version": "16.05.4 MR4" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_16.05.1_MR-1.KVM-139-PRIMARY.qcow2", + "filesize": 285671424, + "md5sum": "3d81cf163fb0f4c5c9ba26e92a0ddc13", + "version": "16.05.1 MR1" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_16.05.1_MR-1.KVM-139-AUXILARY.qcow2", + "filesize": 59441152, + "md5sum": "499541728460331a6b68b9e60c8207a3", + "version": "16.05.1 MR1" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_16.05.0_RC-1.KVM-098-PRIMARY.qcow2", + "filesize": 285736960, + "md5sum": "1826ca8a34945de5251876dc3fc7fe63", + "version": "16.05.1 RC1" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_16.05.0_RC-1.KVM-098-AUXILARY.qcow2", + "filesize": 59441152, + "md5sum": "a9c60a65c1e7b5be8369e5ceaeb358f9", + "version": "16.05.1 RC1" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_16.01.1.KVM-202-PRIMARY.qcow2", + "filesize": 277479424, + "md5sum": "818d9f973b7a32c50d9b84814c6f1ee3", + "version": "16.01.1" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFOS_16.01.1.KVM-202-AUXILARY.qcow2", + "filesize": 59441152, + "md5sum": "1f6fc0b751aaec9bfd4401b0e0cbc6dc", + "version": "16.01.1" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFMOS_15.01.0.KVM-301-PRIMARY.qcow2", + "filesize": 706412544, + "md5sum": "a2cb14ed93de1550afef49984b11b56f", + "version": "15.01" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SFMOS_15.01.0.KVM-301-AUXILARY.qcow2", + "filesize": 199168, + "md5sum": "43cf82ac1f7b0eb6550f0e203daa6b96", + "version": "15.01" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Sophos XG Firewall", + "product_name": "Sophos XG Firewall", + "product_url": "https://www.sophos.com/en-us/products/next-gen-firewall.aspx", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "require", + "ram": 1024 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Port 0 => You computer for the configurtation\nPort 1 => WAN\n\n1. You need a serial number. You can get a trial from Sophos for free.\nUpon starting for the first time, access the setup screen at https://172.16.16.16 (Note: it may take a few minutes for the necessary services to start before the setup screen is ready).\n3. When you are prompted the default administrator credentials are:\nUsername: admin\nPassword: admin\n\n4. Make sure the device is setup for internet access (required for activation): change the network settings from the Basic Setup screen if necessary.\n5. Enter your serial number (provided below) into the setup screen and click \"Activate Device\".\n6. Then register your device with your MySophos ID by clicking \"Register Device\" and entering your MySophos ID and password that you used to download the software.\\\n7. Once the device is registered, you can initiate License Synchronization and proceed with the rest of the configuration.", + "vendor_name": "Sophos", + "vendor_url": "https://www.sophos.com", + "versions": [ + { + "images": { + "hda_disk_image": "VI-17.1.3_MR-3.KVM-250-PRIMARY.qcow2", + "hdb_disk_image": "VI-17.1.3_MR-3.KVM-250-AUXILARY.qcow2" + }, + "name": "17.1.3 MR3" + }, + { + "images": { + "hda_disk_image": "VI-SFOS_17.0.2_MR-2.KVM-116-PRIMARY.qcow2", + "hdb_disk_image": "VI-SFOS_17.0.2_MR-2.KVM-116-AUXILARY.qcow2" + }, + "name": "17.0.2 MR2" + }, + { + "images": { + "hda_disk_image": "VI-SFOS_16.05.4_MR-4.KVM-215-PRIMARY.qcow2", + "hdb_disk_image": "VI-SFOS_16.05.4_MR-4.KVM-215-AUXILARY.qcow2" + }, + "name": "16.05.4 MR4" + }, + { + "images": { + "hda_disk_image": "VI-SFOS_16.05.1_MR-1.KVM-139-PRIMARY.qcow2", + "hdb_disk_image": "VI-SFOS_16.05.1_MR-1.KVM-139-AUXILARY.qcow2" + }, + "name": "16.05.1 MR1" + }, + { + "images": { + "hda_disk_image": "VI-SFOS_16.05.0_RC-1.KVM-098-PRIMARY.qcow2", + "hdb_disk_image": "VI-SFOS_16.05.0_RC-1.KVM-098-AUXILARY.qcow2" + }, + "name": "16.05.1 MR1" + }, + { + "images": { + "hda_disk_image": "VI-SFOS_16.01.1.KVM-202-PRIMARY.qcow2", + "hdb_disk_image": "VI-SFOS_16.01.1.KVM-202-AUXILARY.qcow2" + }, + "name": "16.01.1" + }, + { + "images": { + "hda_disk_image": "VI-SFMOS_15.01.0.KVM-301-PRIMARY.qcow2", + "hdb_disk_image": "VI-SFMOS_15.01.0.KVM-301-AUXILARY.qcow2" + }, + "name": "15.01" + } + ] + }, + { + "availability": "service-contract", + "builtin": true, + "category": "multilayer_switch", + "description": "The ArubaOS-CX Simulation Software OVA is a virtual platform to enable simulation of the ArubaOS-CX Network Operating System. Simulated networks can be created using many of the protocols in the ArubaOS-CX Operating system like OSPF and BGP. Key features like the Aruba Network Analytics Engine and the REST API can be simulated, providing a lightweight development platform to building the modern network. This software can be easily implemented in the GNS3 simulation software to enable drag and drop network design for building complex simulated topologies.", + "first_port_name": "mgmt", + "images": [ + { + "download_url": "http://support.arubanetworks.com/", + "filename": "arubaoscx-disk-image-genericx86-p4-20180712161119.vmdk", + "filesize": 287734784, + "md5sum": "9146ae0ac650d8206c9600e03753f022", + "version": "10.01.0001" + } + ], + "maintainer": "Tak Mem Loy", + "maintainer_email": "alloytm@gmail.com", + "name": "ArubaOS-CX Simulation Software", + "port_name_format": "1/1/{0}", + "product_name": "ArubaOS-CX Simulation Software", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 8, + "arch": "x86_64", + "console_type": "vnc", + "cpus": 2, + "hda_disk_interface": "ide", + "hdb_disk_interface": "ide", + "hdc_disk_interface": "ide", + "kvm": "require", + "options": "-nographic", + "process_priority": "normal", + "ram": 4096 + }, + "registry_version": 4, + "status": "stable", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "Default username admin with blank password.", + "vendor_name": "HPE Aruba", + "vendor_url": "arubanetworks.com", + "versions": [ + { + "images": { + "hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20180712161119.vmdk" + }, + "name": "10.01.0001" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Today's threats are increasingly sophisticated and often bypass traditional malware security by masking their malicious activity. A sandbox augments your security architecture by validating threats in a separate, secure environment. FortiSandbox offers a powerful combination of advanced detection, automated mitigation, actionable insight, and flexible deployment to stop targeted attacks and subsequent data loss. It's also a key component of our Advanced Threat Protection solution.", + "documentation_url": "http://docs.fortinet.com/fortisandbox/admin-guides", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA_KVM-v300-build0049-FORTINET.out.kvm.qcow2", + "filesize": 156828160, + "md5sum": "3ef1f05124d13e23332b8b90f8f71c2c", + "version": "3.0.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA_KVM-v300-build0029-FORTINET.out.kvm.qcow2", + "filesize": 153158144, + "md5sum": "a2f6c5297a722c5dba40327734a6e0ac", + "version": "3.0.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA_KVM-v200-build0340-FORTINET.out.kvm.qcow2", + "filesize": 117834240, + "md5sum": "527f3225bd3fbd4ba23779cc1987d2ed", + "version": "2.5.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA_KVM-v200-build0329-FORTINET.out.kvm.qcow2", + "filesize": 114491904, + "md5sum": "782ba56a644d78da59b89f4ac91bd319", + "version": "2.5.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA_KVM-v200-build0261-FORTINET.out.kvm.qcow2", + "filesize": 98763264, + "md5sum": "6551ccca8ffe6333742dad54770a01cd", + "version": "2.4.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA_KVM-v200-build0252-FORTINET.out.kvm.qcow2", + "filesize": 99811840, + "md5sum": "47a4489e617f165b92fd8dda68e00bf2", + "version": "2.4.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA_KVM-v200-build0205-FORTINET.out.kvm.qcow2", + "filesize": 94962176, + "md5sum": "1ecb0acf1604bdeee0beb1b75864ca99", + "version": "2.3.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA_KVM-v200-build0195-FORTINET.out.kvm.qcow2", + "filesize": 115868160, + "md5sum": "00147d048c8002c98aa55d73f022204d", + "version": "2.3.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA_VM-v200-build0183-FORTINET.out.kvm.qcow2", + "filesize": 118226944, + "md5sum": "2ff03862e33c8a826a0bce10be12f45e", + "version": "2.3.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FSA-datadrive.qcow2", + "filesize": 200192, + "md5sum": "f2dc0a8fc7591699c364aff400369157", + "version": "2.x" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiSandbox", + "port_name_format": "Port{port1}", + "product_name": "FortiSandbox", + "product_url": "https://www.fortinet.com/products/sandbox/fortisandbox.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 3, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "require", + "options": "-smp 2", + "ram": 8096 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "First boot will take some time without console output. Default username is admin, no password is set.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FSA_KVM-v300-build0049-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + }, + "name": "3.0.3" + }, + { + "images": { + "hda_disk_image": "FSA_KVM-v300-build0029-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + }, + "name": "3.0.1" + }, + { + "images": { + "hda_disk_image": "FSA_KVM-v200-build0340-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + }, + "name": "2.5.2" + }, + { + "images": { + "hda_disk_image": "FSA_KVM-v200-build0329-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + }, + "name": "2.5.1" + }, + { + "images": { + "hda_disk_image": "FSA_KVM-v200-build0261-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + }, + "name": "2.4.1" + }, + { + "images": { + "hda_disk_image": "FSA_KVM-v200-build0252-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + }, + "name": "2.4.0" + }, + { + "images": { + "hda_disk_image": "FSA_KVM-v200-build0205-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + }, + "name": "2.3.3" + }, + { + "images": { + "hda_disk_image": "FSA_KVM-v200-build0195-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + }, + "name": "2.3.2" + }, + { + "images": { + "hda_disk_image": "FSA_VM-v200-build0183-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + }, + "name": "2.3.0" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Sophos Free Home Use Firewall is a fully equipped software version of the Sophos UTM firewall, available at no cost for home users \u2013 no strings attached. It features full Network, Web, Mail and Web Application Security with VPN functionality and protects up to 50 IP addresses. The Sophos UTM Free Home Use firewall contains its own operating system and will overwrite all data on the computer during the installation process. Therefore, a separate, dedicated computer or VM is needed, which will change into a fully functional security appliance.", + "documentation_url": "https://community.sophos.com/products/unified-threat-management/", + "images": [ + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.510-5.1.iso", + "filesize": 871266304, + "md5sum": "ae21f96686f238c25941fd3240c7da5b", + "version": "9.510-5.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.506-2.1.iso", + "filesize": 1006057472, + "md5sum": "6b4374f8c5ee66ccdf9683f7349f59cb", + "version": "9.506-2.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.500-9.1.iso", + "filesize": 981612544, + "md5sum": "8531349cdb7f07c94596b19f8e08081a", + "version": "9.500-9.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.415-1.1.iso", + "filesize": 961087488, + "md5sum": "505004bf5a5d5f2234b2056ec7b553d8", + "version": "9.415-1.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.413-4.1.iso", + "filesize": 965146624, + "md5sum": "decdccf0fbb1c809c0d3ad1dd322ca5d", + "version": "9.413-4.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.411-3.1.iso", + "filesize": 947019776, + "md5sum": "0940197daccb5993a419b667c71fb341", + "version": "9.411-3.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.409-9.1.iso", + "filesize": 910178304, + "md5sum": "71e9261ac77d230f85d8066f8efef710", + "version": "9.409-9.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.408-4.1.iso", + "filesize": 892516352, + "md5sum": "b10aab2d3dd4d7f6424b9c64a075e550", + "version": "9.408-4.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.407-3.1.iso", + "filesize": 879738880, + "md5sum": "19f736d0766a960a1d37edf98daaf01d", + "version": "9.407-3.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.406-3.1.iso", + "filesize": 873408512, + "md5sum": "b79fb0fd04654068897961ab0594297c", + "version": "9.406-3.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.405-5.1.iso", + "filesize": 864020480, + "md5sum": "cc1687ea73dd7363212c0db5ad784bc6", + "version": "9.405-5.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.403-4.1.iso", + "filesize": 850329600, + "md5sum": "631f2a017deb284705d653905de51604", + "version": "9.403-4.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.358-3.1.iso", + "filesize": 868235264, + "md5sum": "883176415be49e12ab63b46ca749c7b2", + "version": "9.358-3.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.357-1.1.iso", + "filesize": 848300032, + "md5sum": "c34061e770f26a994b725b4b92fe56dc", + "version": "9.357-1.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.356-3.1.iso", + "filesize": 820531200, + "md5sum": "bd155ed98a477d1182367b302bb480f3", + "version": "9.356-3.1" + }, + { + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", + "filename": "asg-9.217-3.1.iso", + "filesize": 747606016, + "md5sum": "77bae7dcad422dac428984417573acad", + "version": "9.217-3.1" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Sophos UTM Home Edition", + "port_name_format": "eth{0}", + "product_name": "Sophos UTM Home Edition", + "product_url": "https://www.sophos.com/en-us/products/free-tools/sophos-utm-home-edition.aspx", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "allow", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Connect to VNC console for installation, everything else can be set on the WebUI.", + "vendor_name": "Sophos Ltd.", + "vendor_url": "https://www.sophos.com/", + "versions": [ + { + "images": { + "cdrom_image": "asg-9.510-5.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.510-5.1" + }, + { + "images": { + "cdrom_image": "asg-9.506-2.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.506-2.1" + }, + { + "images": { + "cdrom_image": "asg-9.500-9.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.500-9.1" + }, + { + "images": { + "cdrom_image": "asg-9.415-1.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.415-1.1" + }, + { + "images": { + "cdrom_image": "asg-9.413-4.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.413-4.1" + }, + { + "images": { + "cdrom_image": "asg-9.411-3.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.411-3.1" + }, + { + "images": { + "cdrom_image": "asg-9.409-9.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.409-9.1" + }, + { + "images": { + "cdrom_image": "asg-9.408-4.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.408-4.1" + }, + { + "images": { + "cdrom_image": "asg-9.407-3.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.407-3.1" + }, + { + "images": { + "cdrom_image": "asg-9.406-3.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.406-3.1" + }, + { + "images": { + "cdrom_image": "asg-9.405-5.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.405-5.1" + }, + { + "images": { + "cdrom_image": "asg-9.403-4.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.403-4.1" + }, + { + "images": { + "cdrom_image": "asg-9.358-3.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.358-3.1" + }, + { + "images": { + "cdrom_image": "asg-9.357-1.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.357-1.1" + }, + { + "images": { + "cdrom_image": "asg-9.356-3.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.356-3.1" + }, + { + "images": { + "cdrom_image": "asg-9.217-3.1.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "9.217-3.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, machine learning and much more. This appliance provide python 2.7.", + "docker": { + "adapters": 1, + "console_http_path": "/", + "console_http_port": 8888, + "console_type": "http", + "image": "gns3/jupyter27:v2" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Jupyter 2.7", + "product_name": "Jupyter", + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/docker_guest.svg", + "vendor_name": "Project Jupyter", + "vendor_url": "http://jupyter.org/" + }, + { + "builtin": true, + "category": "guest", + "description": "ipterm is a debian based networking toolbox.\nIt contains the following utilities: net-tools, iproute2, ping, traceroute, curl, host, iperf3, mtr, socat, ssh client, tcpdump and the multicast testing tools msend/mreceive.", + "docker": { + "adapters": 1, + "image": "gns3/ipterm:latest" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "ipterm", + "product_name": "ipterm", + "registry_version": 3, + "status": "stable", + "symbol": "linux_guest.svg", + "usage": "The /root directory is persistent.", + "vendor_name": "ipterm", + "vendor_url": "https://www.debian.org" + }, + { + "builtin": true, + "category": "firewall", + "description": "ClearOS is an operating system for your Server, Network, and Gateway systems. It is designed for homes, small to medium businesses, and distributed environments. ClearOS is commonly known as the Next Generation Small Business Server, while including indispensable Gateway and Networking functionality. It delivers a powerful IT solution with an elegant user interface that is completely web-based. Simply put.. ClearOS is the new way of delivering IT.", + "documentation_url": "https://www.clearos.com/resources/documentation/clearos-7-documentation-overview", + "images": [ + { + "download_url": "https://www.clearos.com/clearfoundation/software/clearos-downloads", + "filename": "ClearOS-7.5-DVD-x86_64.iso", + "filesize": 1146093568, + "md5sum": "1e23c5f73a6c996420d8e0e70b000bf9", + "version": "7.5" + }, + { + "download_url": "https://www.clearos.com/clearfoundation/software/clearos-downloads", + "filename": "ClearOS-7.4-DVD-x86_64.iso", + "filesize": 1029701632, + "md5sum": "826da592f9cd4b59f5fc996ff2d569f1", + "version": "7.4" + }, + { + "download_url": "https://www.clearos.com/clearfoundation/software/clearos-downloads", + "filename": "ClearOS-7.3-DVD-x86_64.iso", + "filesize": 884998144, + "md5sum": "1bae8b2d7abe1bc72665a270f10a5149", + "version": "7.3" + }, + { + "download_url": "https://www.clearos.com/clearfoundation/software/clearos-downloads", + "filename": "ClearOS-7.2-DVD-x86_64.iso", + "filesize": 855638016, + "md5sum": "a094763e6ed5d9b073fd4e651f9a48f1", + "version": "7.2" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "ClearOS CE", + "product_name": "ClearOS CE", + "product_url": "https://www.clearos.com/clearfoundation/software/clearos-7-community", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 3, + "arch": "x86_64", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Follow the installer.", + "vendor_name": "ClearCenter, Corp.", + "vendor_url": "https://www.clearos.com/", + "versions": [ + { + "images": { + "cdrom_image": "ClearOS-7.5-DVD-x86_64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "7.5" + }, + { + "images": { + "cdrom_image": "ClearOS-7.4-DVD-x86_64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "7.4" + }, + { + "images": { + "cdrom_image": "ClearOS-7.3-DVD-x86_64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "7.3" + }, + { + "images": { + "cdrom_image": "ClearOS-7.2-DVD-x86_64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "7.2" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Big Cloud Fabric\u2122 is the industry\u2019s first data center fabric built using whitebox or britebox switches and SDN controller technology. Embracing hyperscale data center design principles, Big Cloud Fabric solution enables rapid innovation, ease of provisioning and management, while reducing overall costs, making it ideal for current and next generation data centers. Big Cloud Fabric is designed from the ground up to satisfy the requirements of physical, virtual, containerized, or a combination of such workloads. Some of the typical OpenStack or VMware data center workloads include NFV, High Performance Computing, Big Data and Software Defined Storage deployments.", + "documentation_url": "http://www.bigswitch.com/support", + "images": [ + { + "download_url": "http://www.bigswitch.com/community-edition", + "filename": "BCF-Controller-BCF-CE-3.5.0-2016-01-22.qcow2", + "filesize": 2860253184, + "md5sum": "d1c2ecf0db8101f6b6d311470697545a", + "version": "3.5.0-2016-01-22" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Big Cloud Fabric", + "product_name": "Big Cloud Fabric", + "product_url": "http://www.bigswitch.com/sdn-products/big-cloud-fabrictm", + "qemu": { + "adapter_type": "e1000", + "adapters": 8, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "ram": 256 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "usage": "Login is admin", + "vendor_name": "Big Switch Networks", + "vendor_url": "http://www.bigswitch.com/", + "versions": [ + { + "images": { + "hda_disk_image": "BCF-Controller-BCF-CE-3.5.0-2016-01-22.qcow2" + }, + "name": "3.5" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "This appliance simulate a domestic modem. It provide an IP via DHCP and will nat all connection to the internet without the need of using a cloud interface in your topologies. IP will be in the subnet 172.16.0.0/16. Multiple internet will have different IP range from 172.16.1.0/24 to 172.16.253.0/24 .\n\nWARNING USE IT ONLY WITH THE GNS3 VM.", + "documentation_url": "http://www.gns3.com", + "images": [ + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/core-linux-6.4-internet-0.1.img", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "core-linux-6.4-internet-0.1.img", + "filesize": 16711680, + "md5sum": "8ebc5a6ec53a1c05b7aa101b5ceefe31", + "version": "0.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Internet", + "product_name": "Internet", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "i386", + "console_type": "telnet", + "kvm": "allow", + "options": "-device e1000,netdev=internet0 -netdev vde,sock=/var/run/vde2/qemu0.ctl,id=internet0", + "ram": 64 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "Just connect stuff to the appliance. Everything is automated.", + "vendor_name": "GNS3", + "vendor_url": "http://www.gns3.com", + "versions": [ + { + "images": { + "hda_disk_image": "core-linux-6.4-internet-0.1.img" + }, + "name": "0.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Surveillance systems can be complicated, expensive, and unreliable. But FortiCamera and FortiRecorder simplify IP video surveillance and there are no license fees. With FortiCams, you can see everything: doors, POS terminals, public areas--whatever you need to keep an eye on. FortiRecorder captures the images for easy monitoring, storage, and retrieval. Just plug in your cameras, connect the FortiRecorder, open a web browser or client application, and you're ready to go. It's easy to navigate and configure with event timelines and profile-driven configuration.", + "documentation_url": "https://docs.fortinet.com/fortirecorder/", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "fortirecorder-FRC_VMKV-64-v26-build0607-FORTINET.out.kvm.qcow2", + "filesize": 63569920, + "md5sum": "ffa5d42119de576631673516f60e028b", + "version": "2.6.3" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiRecorder", + "port_name_format": "Port{port1}", + "product_name": "FortiRecorder", + "product_url": "https://www.fortinet.com/products/network-based-video-security/forticam-fortirecorder.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 10, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "Use HTTPS when connecting to the WebUI.\nDefault username is admin, no password is set.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "fortirecorder-FRC_VMKV-64-v26-build0607-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "2.6.3" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "PacketFence is a fully supported, trusted, Free and Open Source network access control (NAC) solution. Boasting an impressive feature set including a captive-portal for registration and remediation, centralized wired and wireless management, 802.1X support, layer-2 isolation of problematic devices, integration with the Snort IDS and the Nessus vulnerability scanner; PacketFence can be used to effectively secure networks - from small to very large heterogeneous networks.", + "documentation_url": "https://packetfence.org/support/index.html#/documentation", + "images": [ + { + "compression": "bzip2", + "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/8.1.0/PacketFenceZEN_USB-8.1.0.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-8.1.0.img", + "filesize": 3221225472, + "md5sum": "f326f0e70b35d598c8b84ee3fc9c611f", + "version": "8.1.0" + }, + { + "compression": "bzip2", + "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/7.4.0/PacketFenceZEN_USB-7.4.0.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-7.4.0.img", + "filesize": 3221225472, + "md5sum": "83951211540f16dd5813c26955c52429", + "version": "7.4.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/7.3.0/PacketFenceZEN_USB-7.3.0.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-7.3.0.img", + "filesize": 3221225472, + "md5sum": "dfeb8a97bba2e475ce418b02327c0ea1", + "version": "7.3.0" + }, + { + "compression": "bzip2", + "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/7.1.0/PacketFenceZEN_USB-7.1.0.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-7.1.0.img", + "filesize": 3221225472, + "md5sum": "3811099f4e1eba164245e94cfa09d26f", + "version": "7.1.0" + }, + { + "compression": "bzip2", + "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/7.0.0/PacketFenceZEN_USB-7.0.0.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-7.0.0.img", + "filesize": 3221225472, + "md5sum": "f5d7f81b279ad286e09f3ddf29dd06c3", + "version": "7.0.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.5.1/PacketFenceZEN_USB-6.5.1.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-6.5.1.img", + "filesize": 3221225472, + "md5sum": "937c02640bd487889b7071e8f094a62a", + "version": "6.5.1" + }, + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.5.0/PacketFenceZEN_USB-6.5.0.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-6.5.0.img", + "filesize": 3221225472, + "md5sum": "5d5ff015f115e9dbcfd355f1bb22f5d9", + "version": "6.5.0" + }, + { + "compression": "bzip2", + "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.4.0/PacketFenceZEN_USB-6.4.0.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-6.4.0.img", + "filesize": 3221225472, + "md5sum": "7f2bea58421d094152ea71f49cc3084a", + "version": "6.4.0" + }, + { + "compression": "bzip2", + "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.3.0/PacketFenceZEN_USB-6.3.0.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-6.3.0.img", + "filesize": 3221225472, + "md5sum": "94e19349faedf292743fdc0ab48f8466", + "version": "6.3.0" + }, + { + "compression": "bzip2", + "direct_download_url": "http://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.2.1/PacketFenceZEN_USB-6.2.1.tar.bz2/download", + "download_url": "https://packetfence.org/download.html#/zen", + "filename": "PacketFenceZEN_USB-6.2.1.img", + "filesize": 3221225472, + "md5sum": "f212be7c8621b90d973f500f00ef1277", + "version": "6.2.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "PacketFence ZEN", + "product_name": "PacketFence ZEN", + "product_url": "https://packetfence.org/about.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 2, + "arch": "x86_64", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 8192 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Boot the live CD", + "vendor_name": "Inverse inc.", + "vendor_url": "https://packetfence.org/", + "versions": [ + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-8.1.0.img" + }, + "name": "8.1.0" + }, + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-7.4.0.img" + }, + "name": "7.4.0" + }, + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-7.3.0.img" + }, + "name": "7.3.0" + }, + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-7.1.0.img" + }, + "name": "7.1.0" + }, + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-7.0.0.img" + }, + "name": "7.0.0" + }, + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-6.5.1.img" + }, + "name": "6.5.0" + }, + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-6.5.0.img" + }, + "name": "6.5.0" + }, + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-6.4.0.img" + }, + "name": "6.4.0" + }, + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-6.3.0.img" + }, + "name": "6.3.0" + }, + { + "images": { + "hda_disk_image": "PacketFenceZEN_USB-6.2.1.img" + }, + "name": "6.2.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "FortiAuthenticator user identity management appliances strengthen enterprise security by simplifying and centralizing the management and storage of user identity information.", + "documentation_url": "http://docs.fortinet.com/fortiauthenticator/admin-guides", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v5-build0366-FORTINET.out.kvm.qcow2", + "filesize": 72982528, + "md5sum": "c6ae060f8840b467efac6701a7e8e6af", + "version": "5.5.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v5-build0297-FORTINET.out.kvm.qcow2", + "filesize": 72617984, + "md5sum": "e63bcaae040f903f9de315f582702619", + "version": "5.4.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v5-build0163-FORTINET.out.kvm.qcow2", + "filesize": 71565312, + "md5sum": "e746b3c6c29b0356ec6b90ed14d4b098", + "version": "5.2.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v500-build0161-FORTINET.out.kvm.qcow2", + "filesize": 72536064, + "md5sum": "c46ad2de4a20296ebd35b3fcc2d81a1d", + "version": "5.2.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v5-build0155-FORTINET.out.kvm.qcow2", + "filesize": 71782400, + "md5sum": "69b55ce7c8094ccd736bbfe8a3262b31", + "version": "5.2.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v500-build0091-FORTINET.out.kvm.qcow2", + "filesize": 71135232, + "md5sum": "7bdafd32db552954c4c7fe60296fc600", + "version": "5.1.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v500-build0086-FORTINET.out.kvm.qcow2", + "filesize": 71819264, + "md5sum": "960017582fe16e7ce7ab9602600e65fe", + "version": "5.1.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v500-build0083-FORTINET.out.kvm.qcow2", + "filesize": 72495104, + "md5sum": "eec53c2dbe5d00c8ce2a7ca50226325a", + "version": "5.1.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v500-build0012-FORTINET.out.kvm.qcow2", + "filesize": 62771200, + "md5sum": "2af90bdad68a37f38fda39ee04cf2fba", + "version": "5.0.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FAC_VM_KVM-v500-DATADRIVE.qcow2", + "filesize": 258048, + "md5sum": "09bad6cfe6301930adbc829eb8a67149", + "version": "5.x.x" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiAuthenticator", + "port_name_format": "Port{port1}", + "product_name": "FortiAuthenticator", + "product_url": "https://www.fortinet.com/products/identity-access-management/fortiauthenticator.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "Default username is admin, no password is set. First book takes longer.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FAC_VM_KVM-v5-build0366-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + }, + "name": "5.5.0" + }, + { + "images": { + "hda_disk_image": "FAC_VM_KVM-v5-build0297-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + }, + "name": "5.4.1" + }, + { + "images": { + "hda_disk_image": "FAC_VM_KVM-v5-build0163-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + }, + "name": "5.2.2" + }, + { + "images": { + "hda_disk_image": "FAC_VM_KVM-v500-build0161-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + }, + "name": "5.2.1" + }, + { + "images": { + "hda_disk_image": "FAC_VM_KVM-v5-build0155-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + }, + "name": "5.2.0" + }, + { + "images": { + "hda_disk_image": "FAC_VM_KVM-v500-build0091-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + }, + "name": "5.1.2" + }, + { + "images": { + "hda_disk_image": "FAC_VM_KVM-v500-build0086-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + }, + "name": "5.1.1" + }, + { + "images": { + "hda_disk_image": "FAC_VM_KVM-v500-build0083-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + }, + "name": "5.1.0" + }, + { + "images": { + "hda_disk_image": "FAC_VM_KVM-v500-build0012-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + }, + "name": "5.0.0" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "The Cisco WSA was one of the first secure web gateways to combine leading protections to help organizations address the growing challenges of securing and controlling web traffic. It enables simpler, faster deployment with fewer maintenance requirements, reduced latency, and lower operating costs. \u201cSet and forget\u201d technology frees staff after initial automated policy settings go live, and automatic security updates are pushed to network devices every 3 to 5 minutes. Flexible deployment options and integration with your existing security infrastructure help you meet quickly evolving security requirements.", + "documentation_url": "http://www.cisco.com/c/en/us/support/security/web-security-appliance/tsd-products-support-series-home.html", + "images": [ + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284806698&flowid=41610&softwareid=282975114&release=9.0.1&relind=AVAILABLE&rellifecycle=LD&reltype=latest", + "filename": "coeus-9-0-1-162-S000V.qcow2", + "filesize": 4753719296, + "md5sum": "3561a6dd9e1b0481e6e68f7e0235fa9b", + "version": "9.0.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Web Security Virtual Appliance", + "port_name_format": "nic{0}", + "product_name": "Web Security Virtual Appliance", + "product_url": "http://www.cisco.com/c/en/us/products/security/web-security-appliance/index.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 5, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 4096 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Boot takes some time. NIC0 is the management port, it gets its initial address using DHCP. Default credentials: admin / ironport", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "coeus-9-0-1-162-S000V.qcow2" + }, + "name": "9.0.1" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "KEMP Technologies free LoadMaster Application Load Balancer is a fully featured member of our award winning and industry leading Load Balancer family. It can be used without charge in production environments with throughput requirements that don\u2019t exceed 20 Mbps, and for services that do not directly generate revenue. It is an ideal choice for low traffic web sites and applications, DevOps testing environments, technical training environments, and for any other deployments that suit your non-commercial needs.", + "documentation_url": "https://support.kemptechnologies.com/hc/en-us/articles/204427785", + "images": [ + { + "download_url": "http://freeloadbalancer.com/download/", + "filename": "LoadMaster-VLM-7.2.44.0.16685.RELEASE-Linux-KVM-XEN-FREE.disk", + "filesize": 17179869185, + "md5sum": "90d2f84fcabe0ba530c84cf12fab87f1", + "version": "7.2.44.0" + }, + { + "download_url": "http://freeloadbalancer.com/download/", + "filename": "LoadMaster-VLM-7.2.40.0.15707.RELEASE-Linux-KVM-XEN-FREE.disk", + "filesize": 17179869185, + "md5sum": "4284a80141f7974d082a2eed91ec6216", + "version": "7.2.40.0" + }, + { + "download_url": "http://freeloadbalancer.com/download/", + "filename": "LoadMaster-VLM-7.2.38.0.14750.RELEASE-Linux-KVM-XEN.disk", + "filesize": 17179869185, + "md5sum": "f51f17640793b31a7eab70b53f6ae3ae", + "version": "7.2.38.0" + }, + { + "download_url": "http://freeloadbalancer.com/download/", + "filename": "LoadMaster-VLM-7.2.36.2.14271.RELEASE-Linux-KVM-XEN-FREE.disk", + "filesize": 17179869185, + "md5sum": "eebfc96bd6c1c50827d00647206b59dd", + "version": "7.1.36.2" + }, + { + "download_url": "http://freeloadbalancer.com/download/", + "filename": "LoadMaster-VLM-7.1.35.0.13244.RELEASE-Linux-KVM-XEN-FREE.disk", + "filesize": 17179869185, + "md5sum": "f72e8dffa201c8ec92767872593a52a1", + "version": "7.1.35.0" + }, + { + "download_url": "http://freeloadbalancer.com/download/", + "filename": "LoadMaster-VLM-7.1.34.1.12802.RELEASE-Linux-KVM-XEN-FREE.disk", + "filesize": 17179869185, + "md5sum": "157b36233bbd9d9dfa18363958b34fd1", + "version": "7.1.34.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "KEMP Free VLM", + "port_name_format": "eth{0}", + "product_name": "KEMP Free VLM", + "product_url": "http://freeloadbalancer.com/#about", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "allow", + "options": "-smp 2", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "loadbalancer.svg", + "usage": "Credentials: bal / 1fourall", + "vendor_name": "KEMP", + "vendor_url": "http://freeloadbalancer.com/", + "versions": [ + { + "images": { + "hda_disk_image": "LoadMaster-VLM-7.2.44.0.16685.RELEASE-Linux-KVM-XEN-FREE.disk" + }, + "name": "7.2.44.0" + }, + { + "images": { + "hda_disk_image": "LoadMaster-VLM-7.2.40.0.15707.RELEASE-Linux-KVM-XEN-FREE.disk" + }, + "name": "7.2.40.0" + }, + { + "images": { + "hda_disk_image": "LoadMaster-VLM-7.2.38.0.14750.RELEASE-Linux-KVM-XEN.disk" + }, + "name": "7.2.38.0" + }, + { + "images": { + "hda_disk_image": "LoadMaster-VLM-7.2.36.2.14271.RELEASE-Linux-KVM-XEN-FREE.disk" + }, + "name": "7.2.36.2" + }, + { + "images": { + "hda_disk_image": "LoadMaster-VLM-7.1.35.0.13244.RELEASE-Linux-KVM-XEN-FREE.disk" + }, + "name": "7.1.35.0" + }, + { + "images": { + "hda_disk_image": "LoadMaster-VLM-7.1.34.1.12802.RELEASE-Linux-KVM-XEN-FREE.disk" + }, + "name": "7.1.34.1" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "FortiGate Virtual Appliance offers the same level of advanced threat prevention features like the physical appliances in private, hybrid and public cloud deployment.", + "documentation_url": "http://docs.fortinet.com/p/inside-fortios", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v6-build0200-FORTINET.out.kvm.qcow2", + "filesize": 51552256, + "md5sum": "be6f74ea13da09cf0b68e87234e2d8d5", + "version": "6.0.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v6-build0076-FORTINET.out.kvm.qcow2", + "filesize": 46104576, + "md5sum": "161728b413e097954bd640ade89dfeb1", + "version": "6.0.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1653-FORTINET.out.kvm.qcow2", + "filesize": 43180032, + "md5sum": "202e1ed7582b02493be63f14cc48c2cb", + "version": "5.6.7" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1575-FORTINET.out.kvm.qcow2", + "filesize": 41594880, + "md5sum": "c312ea8ec1afffb73858fb1b15c095ef", + "version": "5.6.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1547-FORTINET.out.kvm.qcow2", + "filesize": 40939520, + "md5sum": "a908f8620e8bbccce8794733f3637e13", + "version": "5.6.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1486-FORTINET.out.kvm.qcow2", + "filesize": 39231488, + "md5sum": "afb9f237de2545db8663f4a2c5805355", + "version": "5.6.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1484-FORTINET.out.kvm.qcow2", + "filesize": 39227392, + "md5sum": "6f76d1207b9f6cb724f8034f57711705", + "version": "5.6.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1449-FORTINET.out.kvm.qcow2", + "filesize": 38760448, + "md5sum": "17ee2cc8c76c4928a68a2d016aa83ace", + "version": "5.6.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1220-FORTINET.out.kvm.qcow2", + "filesize": 39043072, + "md5sum": "7444d6c85ef6b937a98163482caa5a90", + "version": "5.4.10" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1183-FORTINET.out.kvm.qcow2", + "filesize": 38608896, + "md5sum": "c1eb02996a0919c934785d5f48df9507", + "version": "5.4.8" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build6446-FORTINET.out.kvm.qcow2", + "filesize": 38715392, + "md5sum": "17d3dfebd4b222569cf10cfab83e0e56", + "version": "5.4.7" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1165-FORTINET.out.kvm.qcow2", + "filesize": 38457344, + "md5sum": "4429f1f0f2cce4a8781354a9eb745c61", + "version": "5.4.6" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1138-FORTINET.out.kvm.qcow2", + "filesize": 38096896, + "md5sum": "66c6f6a4b12f0223dd2997b199067e67", + "version": "5.4.5" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build7605-FORTINET.out.kvm.qcow2", + "filesize": 37761024, + "md5sum": "2602fd0c79dd1a69c14b0b46121c875e", + "version": "5.4.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1111-FORTINET.out.kvm.qcow2", + "filesize": 38141952, + "md5sum": "576f95dd7809dd24440fee147252177f", + "version": "5.4.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1100-FORTINET.out.kvm.qcow2", + "filesize": 37789696, + "md5sum": "9ec360c4ffc0811cdecf3d74b152bc14", + "version": "5.4.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1064-FORTINET.out.kvm.qcow2", + "filesize": 37715968, + "md5sum": "441ca5fae1aff9a42fdcaaf8aceb731c", + "version": "5.4.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build1011-FORTINET.out.kvm.qcow2", + "filesize": 35373056, + "md5sum": "22fc2bdca456dfe3027ad48dff370352", + "version": "5.4.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build0762-FORTINET.out.kvm.qcow2", + "filesize": 38776832, + "md5sum": "78df232e516a863f233de88ffba5bc4b", + "version": "5.2.13" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build0760-FORTINET.out.kvm.qcow2", + "filesize": 38363136, + "md5sum": "2efa0c110abed83b71927145d1e87805", + "version": "5.2.12" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build0754-FORTINET.out.kvm.qcow2", + "filesize": 35069952, + "md5sum": "b6cdab6a8240e89f50c0448cf0b711ea", + "version": "5.2.11" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build0742-FORTINET.out.kvm.qcow2", + "filesize": 34779136, + "md5sum": "21fc2bab23a42faa9dc6dcb1a4b180aa", + "version": "5.2.10" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build0736-FORTINET.out.kvm.qcow2", + "filesize": 34590720, + "md5sum": "89cd0883798beed4841dd300f69e462a", + "version": "5.2.9" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build0727-FORTINET.out.kvm.qcow2", + "filesize": 34508800, + "md5sum": "ae7597450893bc60722ef7a787f0a925", + "version": "5.2.8" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build0718-FORTINET.out.kvm.qcow2", + "filesize": 34439168, + "md5sum": "1c59a521885c465004456f74d003726c", + "version": "5.2.7" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FGT_VM64_KVM-v5-build0701-FORTINET.out.kvm.qcow2", + "filesize": 33902592, + "md5sum": "c4d2cbe51669796e48623e006782f7dc", + "version": "5.2.5" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiGate", + "port_name_format": "Port{port1}", + "product_name": "FortiGate", + "product_url": "http://www.fortinet.com/products/fortigate/virtual-appliances.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 10, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "Default username is admin, no password is set.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v6-build0200-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.3" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v6-build0076-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.0" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1653-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.7" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1575-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.4" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1547-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.3" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1486-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.2" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1484-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.1" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1449-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.0" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1220-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.10" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1183-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.8" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build6446-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.7" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1165-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.6" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1138-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.5" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build7605-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.4" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1111-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.3" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1100-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.2" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1064-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.1" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1011-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.0" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build0762-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.13" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build0760-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.12" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build0754-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.11" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build0742-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.10" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build0736-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.9" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build0727-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.8" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build0718-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.7" + }, + { + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build0701-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.5" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "The Brocade Virtual ADX (vADX\u2122) is a full-fledged Application Delivery Controller (ADC) platform with a virtual footprint that leverages Intel advanced technology to deliver remarkable performance. The software is designed to run on standardsbased hypervisors, hosted on Intel x86 COTS hardware. It offers a complete suite of Layer 4 and Layer 7 server load balancing capabilities and application security services with extensible management via rich SOAP/XML APIs.", + "first_port_name": "mgmt1", + "images": [ + { + "download_url": "http://www1.brocade.com/forms/jsp/virtual-adx-download/index.jsp", + "filename": "SSR03100KVM.qcow2", + "filesize": 3327066112, + "md5sum": "40e5717463fb2f5d1bb7c4de7df15c5c", + "version": "03100" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Brocade Virtual ADX", + "port_name_format": "Port {port1}", + "product_name": "Virtual ADX", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 8, + "arch": "x86_64", + "console_type": "vnc", + "kvm": "require", + "options": "-smp 2", + "ram": 2048 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Login is root, type vadx-console to access to the console", + "vendor_name": "Brocade", + "vendor_url": "https://www.brocade.com", + "versions": [ + { + "images": { + "hda_disk_image": "SSR03100KVM.qcow2" + }, + "name": "03100" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "The pfSense project is a free network firewall distribution, based on the FreeBSD operating system with a custom kernel and including third party free software packages for additional functionality. pfSense software, with the help of the package system, is able to provide the same functionality or more of common commercial firewalls, without any of the artificial limitations. It has successfully replaced every big name commercial firewall you can imagine in numerous installations around the world, including Check Point, Cisco PIX, Cisco ASA, Juniper, Sonicwall, Netgear, Watchguard, Astaro, and more.", + "documentation_url": "https://doc.pfsense.org/index.php/Main_Page", + "images": [ + { + "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads", + "filename": "pfSense-CE-2.4.4-RELEASE-amd64.iso", + "filesize": 685557760, + "md5sum": "71386433238f96fc167d14cec9c708c6", + "version": "2.4.4" + }, + { + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 197120, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "Jose Phillips", + "maintainer_email": "jose@latinol.com", + "name": "pfSense", + "port_name_format": "em{0}", + "product_name": "pfSense", + "qemu": { + "adapter_type": "e1000", + "adapters": 6, + "arch": "x86_64", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "allow", + "process_priority": "normal", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Credentials: admin / pfsense\nTo install pfSense use all the defaults settings.\n\nNote:The default LAN port is em1.", + "vendor_name": "Rubicon Communications, LLC (Netgate)", + "vendor_url": "https://www.pfsense.org", + "versions": [ + { + "images": { + "cdrom_image": "pfSense-CE-2.4.4-RELEASE-amd64.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "2.4.4" + } + ] + }, + { + "availability": "free", + "builtin": true, + "category": "guest", + "description": "openSUSE is a free and Linux-based operating system for PC, Laptop or Server. The openSUSE project is a community program sponsored by Novell. It is a general purpose operating system built on top of the Linux kernel, developed by the community-supported openSUSE Project and sponsored by SUSE and a number of other companies.", + "documentation_url": "https://en.opensuse.org/Main_Page", + "images": [ + { + "download_url": "http://www.osboxes.org/opensuse/", + "filename": "openSUSE_42.3-Leap-VM-64bit.vmdk", + "filesize": 5891293184, + "md5sum": "ab777cf90557460ff35aedfbf2befc5d", + "version": "Leap 42.3" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "openSUSE", + "port_name_format": "eth{0}", + "product_name": "openSUSE", + "product_url": "https://www.opensuse.org/#Leap", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "sata", + "kvm": "require", + "options": "-vga virtio", + "ram": 1024 + }, + "registry_version": 4, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Username: osboxes\nPassword: osboxes.org\n\nroot password: osboxes.org", + "vendor_name": "SUSE LLC.", + "vendor_url": "https://www.opensuse.org/", + "versions": [ + { + "images": { + "hda_disk_image": "openSUSE_42.3-Leap-VM-64bit.vmdk" + }, + "name": "Leap 42.3" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "TacacsGUI Free Access Control Server for Your Network Devices. GUI for powerful daemon. The project of Alexey Mochalin, based on tacacs daemon by Marc Huber", + "documentation_url": "https://tacacsgui.com/documentation/", + "images": [ + { + "download_url": "https://drive.google.com/open?id=1U8tbj14NqEyCmarayhZm54qTyjgsJm4B", + "filename": "tac_plus.qcow2", + "filesize": 160301056, + "md5sum": "6b5e66590051124dae586b8640b2eb11", + "version": "201710201114" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "TacacsGUI", + "port_name_format": "Port{port1}", + "product_name": "TacacsGUI", + "product_url": "https://drive.google.com/open?id=1U8tbj14NqEyCmarayhZm54qTyjgsJm4B", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "ide", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Credentials: SSH ---> username: root ---> password: 1234 MySQL DB: ---> username: root --> password: tacacs Web interface: ---> username: tacgui ---> password: abc123", + "vendor_name": "TacacsGUI", + "vendor_url": "https://tacacsgui.com/", + "versions": [ + { + "images": { + "hda_disk_image": "tac_plus.qcow2" + }, + "name": "201710201114" + } + ] + }, + { + "availability": "service-contract", + "builtin": true, + "category": "multilayer_switch", + "description": "The NX-OSv 9000 is a virtual platform that is designed to simulate the control plane aspects of a network element running Cisco Nexus 9000 software. The NX-OSv 9000 shares the same software image running on Cisco Nexus 9000 hardware platform although no specific hardware emulation is implemented. When the software runs as a virtual machine, line card (LC) ASIC provisioning or any interaction from the control plane to hardware ASIC is handled by the NX-OSv 9000 software data plane.\nThe NX-OSv 9000 for the Cisco Nexus 9000 Series provides a useful tool to enable the devops model and rapidly test changes to the infrastructure or to infrastructure automation tools. This enables network simulations in large scale for customers to validate configuration changes on a simulated network prior to applying them on a production network. Some users have also expressed interest in using the simulation system for feature test ,verification, and automation tooling development and test simualtion prior to deployment. NX-OSv 9000 can be used as a programmability vehicle to validate software defined networks (SDNs) and Network Function Virtualization (NFV) based solutions.", + "documentation_url": "http://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus9000/sw/7-x/nx-osv/configuration/guide/b_NX-OSv_9000/b_NX-OSv_chapter_01.html", + "first_port_name": "mgmt0", + "images": [ + { + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.2%25283%2529", + "filename": "nxosv-final.9.2.3.qcow2", + "filesize": 1357643776, + "md5sum": "74bd9a5b4970e868685f753e48979194", + "version": "9.2.3" + }, + { + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.2%25281%2529", + "filename": "nxosv-final.9.2.2.qcow2", + "filesize": 1344077824, + "md5sum": "2119702c488552fc4d1b4210a04d4f64", + "version": "9.2.2" + }, + { + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.2%25281%2529", + "filename": "nxosv-final.9.2.1.qcow2", + "filesize": 1330315264, + "md5sum": "1d7fa4654602d7ffbf62544edfe71986", + "version": "9.2.1" + }, + { + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/7.0%25283%2529I7%25286%2529", + "filename": "nxosv-final.7.0.3.I7.6.qcow2", + "filesize": 1031995392, + "md5sum": "a122ee954b4c11761abd99291b70544e", + "version": "7.0.3.I7.6" + }, + { + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/7.0%25283%2529I7%25285%2529", + "filename": "nxosv-final.7.0.3.I7.5.qcow2", + "filesize": 1027670016, + "md5sum": "68a4008e189c8a35ccb8ee58db9608bb", + "version": "7.0.3.I7.5" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "nxosv-final.7.0.3.I7.4.qcow2", + "filesize": 985792512, + "md5sum": "1e980c95ca47045ae45ded6e07fabfb8", + "version": "7.0.3.I7.4" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "nxosv-final.7.0.3.I7.3.qcow2", + "filesize": 983629824, + "md5sum": "9d7a20367bf681a239f14097bbce470a", + "version": "7.0.3.I7.3" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "nxosv-final.7.0.3.I7.2.qcow2", + "filesize": 906231808, + "md5sum": "17295efb13e83b24a439148449bfd5ab", + "version": "7.0.3.I7.2" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "nxosv-final.7.0.3.I7.1.qcow2", + "filesize": 903151616, + "md5sum": "3c122f27d0c3684c63657207eadf4d06", + "version": "7.0.3.I7.1" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "nxosv-final.7.0.3.I6.1.qcow2", + "filesize": 780402688, + "md5sum": "18bb991b814a508d1190575f99deed99", + "version": "7.0.3.I6.1" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "nxosv-final.7.0.3.I5.2.qcow2", + "filesize": 777715712, + "md5sum": "c06aaa02f758a64fd8fee9406756f1da", + "version": "7.0.3.I5.2" + }, + { + "download_url": "https://software.cisco.com/download/", + "filename": "nxosv-final.7.0.3.I5.1.qcow2", + "filesize": 784990208, + "md5sum": "201ea658fa4c57452ee4b2aa4f5262a7", + "version": "7.0.3.I5.1" + }, + { + "compression": "zip", + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/OVMF-20160813.fd.zip/download", + "download_url": "", + "filename": "OVMF-20160813.fd", + "filesize": 2097152, + "md5sum": "8ff0ef1ec56345db5b6bda1a8630e3c6", + "version": "16.08.13" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco NX-OSv 9000", + "port_name_format": "Ethernet1/{port1}", + "product_name": "NX-OSv 9000", + "qemu": { + "adapter_type": "e1000", + "adapters": 10, + "arch": "x86_64", + "console_type": "telnet", + "cpus": 2, + "hda_disk_interface": "sata", + "kvm": "require", + "ram": 8096 + }, + "registry_version": 4, + "status": "stable", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "The old (I5) versions might require 8192 MB of RAM; adjust it if necessary.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.9.2.3.qcow2" + }, + "name": "9.2.3" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.9.2.2.qcow2" + }, + "name": "9.2.2" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.9.2.1.qcow2" + }, + "name": "9.2.1" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I7.6.qcow2" + }, + "name": "7.0.3.I7.6" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I7.5.qcow2" + }, + "name": "7.0.3.I7.5" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I7.4.qcow2" + }, + "name": "7.0.3.I7.4" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I7.3.qcow2" + }, + "name": "7.0.3.I7.3" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I7.2.qcow2" + }, + "name": "7.0.3.I7.2" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I7.1.qcow2" + }, + "name": "7.0.3.I7.1" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I6.1.qcow2" + }, + "name": "7.0.3.I6.1" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I5.2.qcow2" + }, + "name": "7.0.3.I5.2" + }, + { + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I5.1.qcow2" + }, + "name": "7.0.3.I5.1" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "The vMX is a full-featured, carrier-grade virtual MX Series 3D Universal Edge Router that extends 15+ years of Juniper Networks edge routing expertise to the virtual realm. This appliance is for the Virtual Control Plane (vCP) VM and is meant to be paired with the Virtual Forwarding Plane (vFP) VM.", + "documentation_url": "http://www.juniper.net/techpubs/", + "first_port_name": "fxp0", + "images": [ + { + "filename": "junos-vmx-x86-64-17.4R1.16.qcow2", + "filesize": 1325400064, + "md5sum": "85239193e852d643dfd9d5c257240bdf", + "version": "17.4R1.16-KVM" + }, + { + "filename": "vmxhdd-17.4R1.16.img", + "filesize": 108986368, + "md5sum": "69e9821ebc59367527336d8bcecd171c", + "version": "17.4R1.16-KVM" + }, + { + "filename": "metadata-usb-re-17.4R1.16.img", + "filesize": 16777216, + "md5sum": "a5b125822b798c7167c35966ea00229a", + "version": "17.4R1.16-KVM" + }, + { + "filename": "junos-vmx-x86-64-17.3R2.10.qcow2", + "filesize": 1298137088, + "md5sum": "11984eb87b471e8cc2677212c4277959", + "version": "17.3R2.10-KVM" + }, + { + "filename": "vmxhdd-17.3R2.10.img", + "filesize": 108986368, + "md5sum": "9d843e5493d5e86d37853a72885d84c8", + "version": "17.3R2.10-KVM" + }, + { + "filename": "metadata-usb-re-17.3R2.10.img", + "filesize": 16777216, + "md5sum": "564ca5b7c03ed39680d2d42464d9489b", + "version": "17.3R2.10-KVM" + }, + { + "filename": "vcp_17.1R1.8-disk1.vmdk", + "filesize": 1065513984, + "md5sum": "2dba6dff363c0619903f85c3dedce8d8", + "version": "17.1R1.8-ESXi" + }, + { + "filename": "vcp_17.1R1.8-disk2.vmdk", + "filesize": 5928448, + "md5sum": "df7016f8b0fd456044425fa92566c129", + "version": "17.1R1.8-ESXi" + }, + { + "filename": "vcp_17.1R1.8-disk3.vmdk", + "filesize": 71680, + "md5sum": "e9460158e6e27f7885981ab562e60944", + "version": "17.1R1.8-ESXi" + }, + { + "filename": "junos-vmx-x86-64-17.1R1.8.qcow2", + "filesize": 1192296448, + "md5sum": "4434e70fedfec2ef205412236ae934a4", + "version": "17.1R1.8-KVM" + }, + { + "filename": "vmxhdd-17.1R1.img", + "filesize": 108986368, + "md5sum": "3634fa16219852d0dba46b2fb77d5969", + "version": "17.1R1.8-KVM" + }, + { + "filename": "metadata-usb-re-17.1R1.img", + "filesize": 16777216, + "md5sum": "e911911dc77e7fef1375e66ae98e41b8", + "version": "17.1R1.8-KVM" + }, + { + "filename": "vcp_16.2R1.6-disk1.vmdk", + "filesize": 1093272576, + "md5sum": "6407f6b448de3b45b86fccb4d586a977", + "version": "16.2R1.6-ESXi" + }, + { + "filename": "vcp_16.2R1.6-disk2.vmdk", + "filesize": 5928960, + "md5sum": "73db51629c009466d39f5d7fdf736224", + "version": "16.2R1.6-ESXi" + }, + { + "filename": "vcp_16.2R1.6-disk3.vmdk", + "filesize": 71680, + "md5sum": "6df61c10f25ea6279562e5a13342100d", + "version": "16.2R1.6-ESXi" + }, + { + "filename": "junos-vmx-x86-64-16.2R1.6.qcow2", + "filesize": 1217462272, + "md5sum": "61497595fb62a9d9805724a3e0a56fa0", + "version": "16.2R1.6-KVM" + }, + { + "filename": "vmxhdd-16.2R1.img", + "filesize": 108986368, + "md5sum": "ce75a16cf130d8744652c8f23d1d13ef", + "version": "16.2R1.6-KVM" + }, + { + "filename": "metadata-usb-re-16.2R1.img", + "filesize": 16777216, + "md5sum": "dded4a98c18ecc79daaa1d11dd0cfb2f", + "version": "16.2R1.6-KVM" + }, + { + "filename": "vcp_16.1R4.7-disk1.vmdk", + "filesize": 987702272, + "md5sum": "e438f48a34d6b8047e36994fb323a97b", + "version": "16.1R4.7-ESXi" + }, + { + "filename": "vcp_16.1R4.7-disk2.vmdk", + "filesize": 5929472, + "md5sum": "fb30d5afd182a03f36daaaf985e0d1ef", + "version": "16.1R4.7-ESXi" + }, + { + "filename": "vcp_16.1R4.7-disk3.vmdk", + "filesize": 71680, + "md5sum": "c185a44561890a4b6e84cea6b86ad92a", + "version": "16.1R4.7-ESXi" + }, + { + "filename": "junos-vmx-x86-64-16.1R4.7.qcow2", + "filesize": 1115815936, + "md5sum": "020db6733c158bd871bf28dcd7d039e9", + "version": "16.1R4.7-KVM" + }, + { + "filename": "vmxhdd-16.1R4.img", + "filesize": 108986368, + "md5sum": "97b86d9d69f9615fb97d50a8d4aecd97", + "version": "16.1R4.7-KVM" + }, + { + "filename": "metadata-usb-re-16.1R4.img", + "filesize": 16777216, + "md5sum": "fb200eec654e14201bfa0720b39a64f0", + "version": "16.1R4.7-KVM" + }, + { + "filename": "vcp_16.1R3.10-disk1.vmdk", + "filesize": 977419776, + "md5sum": "532ab7d63c1873e6e6e9b9b057eb83ec", + "version": "16.1R3.10-ESXi" + }, + { + "filename": "vcp_16.1R3.10-disk2.vmdk", + "filesize": 5928448, + "md5sum": "c563254a38c0d83c4bb9a866cae661f0", + "version": "16.1R3.10-ESXi" + }, + { + "filename": "vcp_16.1R3.10-disk3.vmdk", + "filesize": 71680, + "md5sum": "9c8f3a8f26ff418eb6a5acd4803a3ca2", + "version": "16.1R3.10-ESXi" + }, + { + "filename": "junos-vmx-x86-64-16.1R3.10.qcow2", + "filesize": 1105526784, + "md5sum": "f677c8235f579c54ee746daade5ee443", + "version": "16.1R3.10-KVM" + }, + { + "filename": "vmxhdd-16.1R3.img", + "filesize": 108986368, + "md5sum": "28626ce47bea74b7d92bb4e28fa85c93", + "version": "16.1R3.10-KVM" + }, + { + "filename": "metadata-usb-re-16.1R3.img", + "filesize": 16777216, + "md5sum": "b187253fa654a30a7dd0b331e2c6e6a4", + "version": "16.1R3.10-KVM" + }, + { + "filename": "vcp_16.1R2.11-disk1.vmdk", + "filesize": 970741248, + "md5sum": "20945c0114fa4f88cdbedd0551f62d8f", + "version": "16.1R2.11-ESXi" + }, + { + "filename": "vcp_16.1R2.11-disk2.vmdk", + "filesize": 5930496, + "md5sum": "904acd14a9eef0bdb60f18db63b8a653", + "version": "16.1R2.11-ESXi" + }, + { + "filename": "vcp_16.1R2.11-disk3.vmdk", + "filesize": 71680, + "md5sum": "f6f6c24c0f991faf93c45f1fbc2ed0ae", + "version": "16.1R2.11-ESXi" + }, + { + "filename": "junos-vmx-x86-64-16.1R2.11.qcow2", + "filesize": 1194065920, + "md5sum": "da443543eee6d7305a6851d38d0613ea", + "version": "16.1R2.11-KVM" + }, + { + "filename": "vmxhdd-16.1R2.img", + "filesize": 108986368, + "md5sum": "962c04d00d2b3272f40f3571d1305d6d", + "version": "16.1R2.11-KVM" + }, + { + "filename": "metadata-usb-re-16.1R2.img", + "filesize": 16777216, + "md5sum": "10f219a0b5d23553dbbf3a7ec1358a68", + "version": "16.1R2.11-KVM" + }, + { + "filename": "vcp_16.1R1.7-disk1.vmdk", + "filesize": 1067432448, + "md5sum": "0a97d16b7014be8e3ae270cc2028d10d", + "version": "16.1R1.7-ESXi" + }, + { + "filename": "vcp_16.1R1.7-disk2.vmdk", + "filesize": 5930496, + "md5sum": "e96972233a144b93aa9bcc321b2a215b", + "version": "16.1R1.7-ESXi" + }, + { + "filename": "vcp_16.1R1.7-disk3.vmdk", + "filesize": 71680, + "md5sum": "815af90310e6681204ba511d9659d2ad", + "version": "16.1R1.7-ESXi" + }, + { + "filename": "junos-vmx-x86-64-16.1R1.7.qcow2", + "filesize": 1194065920, + "md5sum": "f7b53cc04672a1abf7c0236a772cea51", + "version": "16.1R1.7-KVM" + }, + { + "filename": "vmxhdd-16.1R1.img", + "filesize": 108986368, + "md5sum": "c239c4de2a4cf902747c8fc300f08493", + "version": "16.1R1.7-KVM" + }, + { + "filename": "metadata-usb-re-16.1R1.img", + "filesize": 16777216, + "md5sum": "47e578bd41890272dcd5aa1e436068d4", + "version": "16.1R1.7-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "jinstall64-vmx-15.1F4.15-domestic.img", + "filesize": 1003945984, + "md5sum": "e6b2e1ad9cba5220aa764ae4dd008952", + "version": "15.1F4.15" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vmxhdd-15.1.img", + "filesize": 108986368, + "md5sum": "c3c7090ed3b1799e3de7579ac887e39d", + "version": "15.1F4.15" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "metadata-usb-15.1.img", + "filesize": 16777216, + "md5sum": "af48f7e03f94ffcfeecd15a59a4f1567", + "version": "15.1F4.15" + }, + { + "filename": "junos-vmx-x86-64-15.1F6.9.qcow2", + "filesize": 994181120, + "md5sum": "595f532b95d6d98590d0375a3d6d14b6", + "version": "15.1F6.9-KVM" + }, + { + "filename": "vmxhdd-15.1F6.9.img", + "filesize": 108986368, + "md5sum": "bae35d0bb72946d1e91ff9c5e7ddbf86", + "version": "15.1F6.9-KVM" + }, + { + "filename": "metadata-usb-re-15.1F6.9.img", + "filesize": 16777216, + "md5sum": "15238c3dbc987d1a641c919efe2731c5", + "version": "15.1F6.9-KVM" + } + ], + "maintainer": "none", + "maintainer_email": "developers@gns3.net", + "name": "Juniper vMX vCP", + "port_name_format": "em{port1}", + "product_name": "Juniper vMX vCP", + "product_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "options": "-nographic -enable-kvm", + "ram": 1024 + }, + "registry_version": 3, + "status": "experimental", + "symbol": "juniper-vmx.svg", + "usage": "Initial username is root, no password.\n\nUSAGE INSTRUCTIONS\n\nConnect the first interface (fxp0) to your admin VLAN. Connect the second interface (em1) directly to the second interface (eth1) of the vFP.", + "vendor_name": "Juniper", + "vendor_url": "https://www.juniper.net/us/en/", + "versions": [ + { + "images": { + "hda_disk_image": "junos-vmx-x86-64-17.4R1.16.qcow2", + "hdb_disk_image": "vmxhdd-17.4R1.16.img", + "hdc_disk_image": "metadata-usb-re-17.4R1.16.img" + }, + "name": "17.4R1.16-KVM" + }, + { + "images": { + "hda_disk_image": "junos-vmx-x86-64-17.3R2.10.qcow2", + "hdb_disk_image": "vmxhdd-17.3R2.10.img", + "hdc_disk_image": "metadata-usb-re-17.3R2.10.img" + }, + "name": "17.3R2.10-KVM" + }, + { + "images": { + "hda_disk_image": "vcp_17.1R1.8-disk1.vmdk", + "hdb_disk_image": "vcp_17.1R1.8-disk2.vmdk", + "hdc_disk_image": "vcp_17.1R1.8-disk3.vmdk" + }, + "name": "17.1R1.8-ESXi" + }, + { + "images": { + "hda_disk_image": "junos-vmx-x86-64-17.1R1.8.qcow2", + "hdb_disk_image": "vmxhdd-17.1R1.img", + "hdc_disk_image": "metadata-usb-re-17.1R1.img" + }, + "name": "17.1R1.8-KVM" + }, + { + "images": { + "hda_disk_image": "vcp_16.2R1.6-disk1.vmdk", + "hdb_disk_image": "vcp_16.2R1.6-disk2.vmdk", + "hdc_disk_image": "vcp_16.2R1.6-disk3.vmdk" + }, + "name": "16.2R1.6-ESXi" + }, + { + "images": { + "hda_disk_image": "junos-vmx-x86-64-16.2R1.6.qcow2", + "hdb_disk_image": "vmxhdd-16.2R1.img", + "hdc_disk_image": "metadata-usb-re-16.2R1.img" + }, + "name": "16.2R1.6-KVM" + }, + { + "images": { + "hda_disk_image": "vcp_16.1R4.7-disk1.vmdk", + "hdb_disk_image": "vcp_16.1R4.7-disk2.vmdk", + "hdc_disk_image": "vcp_16.1R4.7-disk3.vmdk" + }, + "name": "16.1R4.7-ESXi" + }, + { + "images": { + "hda_disk_image": "junos-vmx-x86-64-16.1R4.7.qcow2", + "hdb_disk_image": "vmxhdd-16.1R4.img", + "hdc_disk_image": "metadata-usb-re-16.1R4.img" + }, + "name": "16.1R4.7-KVM" + }, + { + "images": { + "hda_disk_image": "vcp_16.1R3.10-disk1.vmdk", + "hdb_disk_image": "vcp_16.1R3.10-disk2.vmdk", + "hdc_disk_image": "vcp_16.1R3.10-disk3.vmdk" + }, + "name": "16.1R3.10-ESXi" + }, + { + "images": { + "hda_disk_image": "junos-vmx-x86-64-16.1R3.10.qcow2", + "hdb_disk_image": "vmxhdd-16.1R3.img", + "hdc_disk_image": "metadata-usb-re-16.1R3.img" + }, + "name": "16.1R3.10-KVM" + }, + { + "images": { + "hda_disk_image": "vcp_16.1R2.11-disk1.vmdk", + "hdb_disk_image": "vcp_16.1R2.11-disk2.vmdk", + "hdc_disk_image": "vcp_16.1R2.11-disk3.vmdk" + }, + "name": "16.1R2.11-ESXi" + }, + { + "images": { + "hda_disk_image": "junos-vmx-x86-64-16.1R2.11.qcow2", + "hdb_disk_image": "vmxhdd-16.1R2.img", + "hdc_disk_image": "metadata-usb-re-16.1R2.img" + }, + "name": "16.1R2.11-KVM" + }, + { + "images": { + "hda_disk_image": "vcp_16.1R1.7-disk1.vmdk", + "hdb_disk_image": "vcp_16.1R1.7-disk2.vmdk", + "hdc_disk_image": "vcp_16.1R1.7-disk3.vmdk" + }, + "name": "16.1R1.7-ESXi" + }, + { + "images": { + "hda_disk_image": "junos-vmx-x86-64-16.1R1.7.qcow2", + "hdb_disk_image": "vmxhdd-16.1R1.img", + "hdc_disk_image": "metadata-usb-re-16.1R1.img" + }, + "name": "16.1R1.7-KVM" + }, + { + "images": { + "hda_disk_image": "jinstall64-vmx-15.1F4.15-domestic.img", + "hdb_disk_image": "vmxhdd-15.1.img", + "hdc_disk_image": "metadata-usb-15.1.img" + }, + "name": "15.1F4.15" + }, + { + "images": { + "hda_disk_image": "junos-vmx-x86-64-15.1F6.9.qcow2", + "hdb_disk_image": "vmxhdd-15.1F6.9.img", + "hdc_disk_image": "metadata-usb-re-15.1F6.9.img" + }, + "name": "15.1F6.9" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "When you go from managing a few boxes to managing a few dozen, your processes, logistics, and needs all change. BIG-IQ Centralized Management brings all of your devices together, so you can discover, track, upgrade, and deploy more efficiently. You can also monitor key metrics from one location, saving yourself both time and effort.\n\nCentrally manage up to 200 physical, virtual, or virtual clustered multiprocessing (vCMP) based BIG-IP devices. BIG-IQ Centralized Management also handles licensing for up to 5,000 unmanaged devices, so you can spin BIG-IP virtual editions (VEs) up or down as needed.", + "documentation_url": "https://support.f5.com/csp/#/knowledge-center/software/BIG-IQ?module=BIG-IQ%20Centralized%20Management", + "first_port_name": "mgmt", + "images": [ + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/6.0.1/english/v6.0.1.1/&sw=BIG-IQ&pro=big-iq_CM&ver=6.0.1&container=v6.0.1.1&file=BIG-IQ-6.0.1.1.0.0.9.qcow2.zip", + "filename": "BIG-IQ-6.0.1.1.0.0.9.qcow2", + "filesize": 3895787520, + "md5sum": "3ae32308fe39d5db555f7f1cdcc734dd", + "version": "6.0.1.1" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.4.0/english/virtual-edition_base-plus-hf2/&sw=BIG-IQ&pro=big-iq_CM&ver=5.4.0&container=Virtual-Edition_Base-Plus-HF2&file=BIG-IQ-5.4.0.2.24.7467.qcow2.zip", + "filename": "BIG-IQ-5.4.0.2.24.7467.qcow2", + "filesize": 3480748032, + "md5sum": "e3e6389438ba1e1676f507658f767e95", + "version": "5.4.0.2" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.4.0/english/v5.4.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.4.0&container=v5.4.0&file=BIG-IQ-5.4.0.0.0.7437.qcow2.zip", + "filename": "BIG-IQ-5.4.0.0.0.7437.qcow2", + "filesize": 3300917248, + "md5sum": "068b1f4d21048b9b2a082c0c27ef4d53", + "version": "5.4.0" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.3.0/english/v5.3.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.3.0&container=v5.3.0&file=BIG-IQ-5.3.0.0.0.1119.qcow2.zip", + "filename": "BIG-IQ-5.3.0.0.0.1119.qcow2", + "filesize": 3269263360, + "md5sum": "75f06ba59f858c3828d47dcf8caf3775", + "version": "5.3.0" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.2.0/english/v5.2.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.2.0&container=v5.2.0&file=BIG-IQ-5.2.0.0.0.5741.qcow2.zip", + "filename": "BIG-IQ-5.2.0.0.0.5741.qcow2", + "filesize": 3256352768, + "md5sum": "c40d9724fb6c15ef0ee949437a9558db", + "version": "5.2.0" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.1.0/english/v5.1.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.1.0&container=v5.1.0&file=BIG-IQ-5.1.0.0.0.631.qcow2.zip", + "filename": "BIG-IQ-5.1.0.0.0.631.qcow2", + "filesize": 2335440896, + "md5sum": "f8f52d9ef56c6bdd0a0604f1b50b81c6", + "version": "5.1.0" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.0.0/english/v5.0.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.0.0&container=v5.0.0&file=BIG-IQ-5.0.0.0.0.3026.qcow2.zip", + "filename": "BIG-IQ-5.0.0.0.0.3026.qcow2", + "filesize": 2301820928, + "md5sum": "072194d6eb052ee083cf8cef9e7a87d6", + "version": "5.0.0" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.0.0/english/v5.0.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.0.0&container=v5.0.0&file=BIG-IQ-5.0.0.0.0.3026.qcow2.zip", + "filename": "BIG-IQ-5.x.DATASTOR.LTM.qcow2", + "filesize": 393216, + "md5sum": "c7f82b8834436eb67b7d619767ac7476", + "version": "5.x" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 198656, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "F5 BIG-IQ CM", + "port_name_format": "1.{port1}", + "product_name": "F5 BIG-IQ CM", + "product_url": "https://f5.com/products/big-iq-centralized-management", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "hdd_disk_interface": "virtio", + "kvm": "require", + "options": "-smp 2 -cpu host", + "ram": 4096 + }, + "registry_version": 3, + "status": "stable", + "symbol": "mgmt_station.svg", + "usage": "Console credentials: root/default\nWebUI credentials: admin/admin\nThe boot process might take a few minutes without providing any output to the console. Please be patient (or set console to vnc to see tty outputs).", + "vendor_name": "F5", + "vendor_url": "http://www.f5.com/", + "versions": [ + { + "images": { + "hda_disk_image": "BIG-IQ-6.0.1.1.0.0.9.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "6.0.1.1" + }, + { + "images": { + "hda_disk_image": "BIG-IQ-5.4.0.2.24.7467.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "5.4.0.2" + }, + { + "images": { + "hda_disk_image": "BIG-IQ-5.4.0.0.0.7437.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "5.4.0" + }, + { + "images": { + "hda_disk_image": "BIG-IQ-5.3.0.0.0.1119.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "5.3.0" + }, + { + "images": { + "hda_disk_image": "BIG-IQ-5.2.0.0.0.5741.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "5.2.0" + }, + { + "images": { + "hda_disk_image": "BIG-IQ-5.1.0.0.0.631.qcow2", + "hdb_disk_image": "empty100G.qcow2", + "hdd_disk_image": "BIG-IQ-5.x.DATASTOR.LTM.qcow2" + }, + "name": "5.1.0" + }, + { + "images": { + "hda_disk_image": "BIG-IQ-5.0.0.0.0.3026.qcow2", + "hdb_disk_image": "empty100G.qcow2", + "hdd_disk_image": "BIG-IQ-5.x.DATASTOR.LTM.qcow2" + }, + "name": "5.0.0" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Security Onion is a Linux distro for intrusion detection, network security monitoring, and log management. It\u2019s based on Ubuntu and contains Snort, Suricata, Bro, OSSEC, Sguil, Squert, ELSA, Xplico, NetworkMiner, and many other security tools. The easy-to-use Setup wizard allows you to build an army of distributed sensors for your enterprise in minutes!", + "documentation_url": "https://github.com/Security-Onion-Solutions/security-onion/wiki", + "images": [ + { + "direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v16.04.5.3_20181010/securityonion-16.04.5.3.iso", + "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/", + "filename": "securityonion-16.04.5.3.iso", + "filesize": 1895825408, + "md5sum": "886b369548c9c3841bc820cc3ab02bd9", + "version": "16.04.5.3" + }, + { + "direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.4.iso", + "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/", + "filename": "securityonion-14.04.5.4.iso", + "filesize": 1874853888, + "md5sum": "9c7cab756b675beb10de4274a3ad3bc6", + "version": "14.04.5.4" + }, + { + "direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.3.iso", + "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/", + "filename": "securityonion-14.04.5.3.iso", + "filesize": 1889533952, + "md5sum": "fb80ccb2d3c0f3f511823fa5858f87d1", + "version": "14.04.5.3" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%30disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "Brent Stewart", + "maintainer_email": "brent@stewart.tc", + "name": "Security Onion", + "product_name": "Security Onion", + "product_url": "https://securityonion.net/", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "i386", + "console_type": "telnet", + "kvm": "allow", + "ram": 3072 + }, + "registry_version": 3, + "status": "stable", + "symbol": "securityonion-logo.png", + "usage": "Your default account will have sudo priviledges. Squil and Squert username and password are configured in the Setup wizard. MySQL root is set to null. For more info see https://github.com/Security-Onion-Solutions/security-onion/wiki/Passwords.", + "vendor_name": "Security Onion Solutions, LLC", + "vendor_url": "https://securityonion.net/", + "versions": [ + { + "images": { + "cdrom_image": "securityonion-16.04.5.3.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "16.04.5.3" + }, + { + "images": { + "cdrom_image": "securityonion-14.04.5.4.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "14.04.5.4" + }, + { + "images": { + "cdrom_image": "securityonion-14.04.5.3.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "14.04.5.3" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "FortiManager Security Management appliances allow you to centrally manage any number of Fortinet Network Security devices, from several to thousands, including FortiGate, FortiWiFi, and FortiCarrier.", + "documentation_url": "http://docs.fortinet.com/p/inside-fortios", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2", + "filesize": 115703808, + "md5sum": "5f34d52d9289b0be2a4c04943446ea39", + "version": "6.0.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v6-build0205-FORTINET.out.kvm.qcow2", + "filesize": 116981760, + "md5sum": "8f748649c537d9b5466b24c5b4e62017", + "version": "6.0.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v6-build0092-FORTINET.out.kvm.qcow2", + "filesize": 119066624, + "md5sum": "73bfe1bc70124521a524d857646b9c2e", + "version": "6.0.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build1631-FORTINET.out.kvm.qcow2", + "filesize": 106946560, + "md5sum": "c81cc247e8eb03249b475fe0e847653e", + "version": "5.6.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build1619-FORTINET.out.kvm.qcow2", + "filesize": 106831872, + "md5sum": "8cc553842564d232af295d6a0c784c1f", + "version": "5.6.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build1557-FORTINET.out.kvm.qcow2", + "filesize": 108363776, + "md5sum": "f8bd600796f894f4ca1ea2d6b4066d3d", + "version": "5.6.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build1225-FORTINET.out.kvm.qcow2", + "filesize": 89911296, + "md5sum": "53bc6e320fe7bde5d2b636bde95a910c", + "version": "5.4.4" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build1187-FORTINET.out.kvm.qcow2", + "filesize": 87425024, + "md5sum": "53602c776d215d98e32163a10804fc49", + "version": "5.4.3" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build1151-FORTINET.out.kvm.qcow2", + "filesize": 86437888, + "md5sum": "8e131ad40009c740f3efdee6dc3a0ac3", + "version": "5.4.2" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build1082-FORTINET.out.kvm.qcow2", + "filesize": 83124224, + "md5sum": "fc1815410f3f0536e2e3a9c1c5c07f41", + "version": "5.4.1" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build1019-FORTINET.out.kvm.qcow2", + "filesize": 77541376, + "md5sum": "1cfb22671cb372d8bf3e47b9c3c55ded", + "version": "5.4.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build0786-FORTINET.out.kvm.qcow2", + "filesize": 64962560, + "md5sum": "377fe38bf07bc2435608e5b65f780f07", + "version": "5.2.10" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build0780-FORTINET.out.kvm.qcow2", + "filesize": 65007616, + "md5sum": "04268e779d3d5e6c928c6fd638423c52", + "version": "5.2.9" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build0777-FORTINET.out.kvm.qcow2", + "filesize": 65011712, + "md5sum": "6dbf148ace9bf309ad383757afd75fad", + "version": "5.2.8" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FMG_VM64_KVM-v5-build0757-FORTINET.out.kvm.qcow2", + "filesize": 65056768, + "md5sum": "d37dbaa49d7522324681eeba19f7699b", + "version": "5.2.7" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiManager", + "port_name_format": "Port{port1}", + "product_name": "FortiManager", + "product_url": "http://www.fortinet.com/products/fortimanager/virtual-security-management.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "Default username is admin, no password is set.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.3" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v6-build0205-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.2" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v6-build0092-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "6.0.0" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build1631-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.2" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build1619-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.1" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build1557-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.6.0" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build1225-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.4" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build1187-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.3" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build1151-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.2" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build1082-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.1" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build1019-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.4.0" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build0786-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.10" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build0780-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.9" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build0777-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.8" + }, + { + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build0757-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + }, + "name": "5.2.7" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "A Free firewall that includes its own security-hardened GNU/Linux operating system and an easy-to-use web interface.", + "documentation_url": "https://sourceforge.net/projects/smoothwall/files/SmoothWall%20Manuals/", + "images": [ + { + "direct_download_url": "http://sourceforge.net/projects/smoothwall/files/SmoothWall/3.1/Express-3.1-x86_64.iso/download", + "download_url": "http://www.smoothwall.org/download/", + "filename": "Express-3.1-x86_64.iso", + "filesize": 214206464, + "md5sum": "cfaf7f11901a164cd00c07518c7311ba", + "version": "3.1" + }, + { + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty8G.qcow2", + "filesize": 197120, + "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Smoothwall Express", + "port_name_format": "eth{0}", + "product_name": "Smoothwall Express", + "product_url": "http://www.smoothwall.org/about/", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "dc", + "console_type": "vnc", + "hda_disk_interface": "ide", + "kvm": "allow", + "ram": 256 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "WebUI can be accessed at https://GREEN_IP:441/ after installation. GREEN interface is used for the LAN, RED for the WAN connections. ORANGE and PURPLE can be used for DMZ.", + "vendor_name": "Smoothwall Ltd.", + "vendor_url": "http://www.smoothwall.org/", + "versions": [ + { + "images": { + "cdrom_image": "Express-3.1-x86_64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "3.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "ntopng is the next generation version of the original ntop, a network traffic probe that shows the network usage, similar to what the popular top Unix command does. ntopng is based on libpcap and it has been written in a portable way in order to virtually run on every Unix platform, MacOSX and on Windows as well. ntopng users can use a a web browser to navigate through ntop (that acts as a web server) traffic information and get a dump of the network status. In the latter case, ntopng can be seen as a simple RMON-like agent with an embedded web interface.", + "docker": { + "adapters": 1, + "console_http_path": "/", + "console_http_port": 3000, + "console_type": "http", + "image": "lucaderi/ntopng-docker:latest" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "ntopng", + "product_name": "ntopng", + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/docker_guest.svg", + "usage": "In the web interface login as admin/admin", + "vendor_name": "ntop", + "vendor_url": "http://www.ntop.org/" + }, + { + "builtin": true, + "category": "router", + "description": "Cloud Hosted Router (CHR) is a RouterOS version meant for running as a virtual machine. It supports x86 64-bit architecture and can be used on most of popular hypervisors such as VMWare, Hyper-V, VirtualBox, KVM and others. CHR has full RouterOS features enabled by default but has a different licensing model than other RouterOS versions.", + "documentation_url": "http://wiki.mikrotik.com/wiki/Manual:CHR", + "images": [ + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.43.8/chr-6.43.8.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.43.8.img", + "filesize": 134217728, + "md5sum": "9437133fc7e77779dc3ff62b98f30dc2", + "version": "6.43.8" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.42.9/chr-6.42.9.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.42.9.img", + "filesize": 134217728, + "md5sum": "1f856978cfc3ceb4b5e18e4e079f2e32", + "version": "6.42.9" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.42/chr-6.42.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.42.img", + "filesize": 134217728, + "md5sum": "279bb518497b40f41c8585128916a2fb", + "version": "6.42" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.41.4/chr-6.41.4.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.41.4.img", + "filesize": 134217728, + "md5sum": "63b555b2b7f0d78b79edb92f7e7d2ed7", + "version": "6.41.4" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.40.7/chr-6.40.7.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.40.7.img", + "filesize": 134217728, + "md5sum": "424b897d631c4cac4324ca310e81b494", + "version": "6.40.7" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.40.5/chr-6.40.5.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.40.5.img", + "filesize": 134217728, + "md5sum": "5d3bef219a859d417fea704ae7109eb7", + "version": "6.40.5" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.40.3/chr-6.40.3.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.40.3.img", + "filesize": 134217728, + "md5sum": "1861df67e9bbf17433f11f33f7dedd1e", + "version": "6.40.3" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.39.2/chr-6.39.2.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.39.2.img", + "filesize": 134217728, + "md5sum": "ecb37373dedfba04267a999d23b8e203", + "version": "6.39.2" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.39.1/chr-6.39.1.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.39.1.img", + "filesize": 134217728, + "md5sum": "c53293bc41f76d85a8642005fd1cbd54", + "version": "6.39.1" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.39/chr-6.39.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.39.img", + "filesize": 134217728, + "md5sum": "7e77c8ac4c9aeaf88f6ff15897f33163", + "version": "6.39" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.38.7/chr-6.38.7.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.38.7.img", + "filesize": 134217728, + "md5sum": "69a51c96b1247bbaf1253d2873617122", + "version": "6.38.7" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.38.5/chr-6.38.5.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.38.5.img", + "filesize": 134217728, + "md5sum": "8147f42ea1ee96f580a35a298b7f9354", + "version": "6.38.5" + }, + { + "compression": "zip", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.38.1/chr-6.38.1.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.38.1.img", + "filesize": 134217728, + "md5sum": "753ed7c86e0f54fd9e18d044db64538d", + "version": "6.38.1" + }, + { + "compression": "zip", + "direct_download_url": "http://download2.mikrotik.com/routeros/6.38/chr-6.38.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.38.img", + "filesize": 134217728, + "md5sum": "37e2165112f8a9beccac06a9a6009000", + "version": "6.38" + }, + { + "compression": "zip", + "direct_download_url": "http://download2.mikrotik.com/routeros/6.37.3/chr-6.37.3.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.37.3.img", + "filesize": 134217728, + "md5sum": "bda87db475f80debdf3181accf6b78e2", + "version": "6.37.3" + }, + { + "compression": "zip", + "direct_download_url": "http://download2.mikrotik.com/routeros/6.37.1/chr-6.37.1.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.37.1.img", + "filesize": 134217728, + "md5sum": "713b14a5aba9f967f7bdd9029c8d85b6", + "version": "6.37.1" + }, + { + "compression": "zip", + "direct_download_url": "http://download2.mikrotik.com/routeros/6.36.4/chr-6.36.4.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.36.4.img", + "filesize": 134217728, + "md5sum": "09527bde50697711926c08d545940c1e", + "version": "6.36.4" + }, + { + "direct_download_url": "http://download2.mikrotik.com/routeros/6.34.2/chr-6.34.2.vmdk", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.34.2.vmdk", + "filesize": 30277632, + "md5sum": "0360f121b76a8b491a05dc37640ca319", + "version": "6.34.2 (.vmdk)" + }, + { + "direct_download_url": "http://download2.mikrotik.com/routeros/6.34.2/chr-6.34.2.vdi", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.34.2.vdi", + "filesize": 30409728, + "md5sum": "e7e4021aeeee2eaabd024d48702bb2e1", + "version": "6.34.2 (.vdi)" + }, + { + "compression": "zip", + "direct_download_url": "http://download2.mikrotik.com/routeros/6.34.2/chr-6.34.2.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.34.2.img", + "filesize": 134217728, + "md5sum": "984d4d11c2ff209fcdc21ac42895edbe", + "version": "6.34.2 (.img)" + }, + { + "direct_download_url": "http://download2.mikrotik.com/routeros/6.34/chr-6.34.vmdk", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.34.vmdk", + "filesize": 30277632, + "md5sum": "c5e6d192ae19d263a9a313d4b4bee7e4", + "version": "6.34 (.vmdk)" + }, + { + "direct_download_url": "http://download2.mikrotik.com/routeros/6.34/chr-6.34.vdi", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.34.vdi", + "filesize": 30409728, + "md5sum": "34b161f83a792c744c76a529afc094a8", + "version": "6.34 (.vdi)" + }, + { + "compression": "zip", + "direct_download_url": "http://download2.mikrotik.com/routeros/6.34/chr-6.34.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.34.img", + "filesize": 134217728, + "md5sum": "32ffde7fb934c7bfee555c899ccd77b6", + "version": "6.34 (.img)" + }, + { + "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.5/chr-6.33.5.vmdk", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.33.5.vmdk", + "filesize": 23920640, + "md5sum": "cd284e28aa02ae59f55ed8f43ff27fbf", + "version": "6.33.5 (.vmdk)" + }, + { + "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.5/chr-6.33.5.vdi", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.33.5.vdi", + "filesize": 24118272, + "md5sum": "fa84e63a558e7c61d7d338386cfd08c9", + "version": "6.33.5 (.vdi)" + }, + { + "compression": "zip", + "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.5/chr-6.33.5.img.zip", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.33.5.img", + "filesize": 67108864, + "md5sum": "210cc8ad06f25c9f27b6b99f6e00bd91", + "version": "6.33.5 (.img)" + }, + { + "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.3/chr-6.33.3.vmdk", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.33.3.vmdk", + "filesize": 23920640, + "md5sum": "08532a5af1a830182d65c416eab2b089", + "version": "6.33.3 (.vmdk)" + }, + { + "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.2/chr-6.33.2.vmdk", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.33.2.vmdk", + "filesize": 23920640, + "md5sum": "6291893c2c9626603c6d38d23390a8be", + "version": "6.33.2 (.vmdk)" + }, + { + "direct_download_url": "http://download2.mikrotik.com/routeros/6.33/chr-6.33.vmdk", + "download_url": "http://www.mikrotik.com/download", + "filename": "chr-6.33.vmdk", + "filesize": 23920640, + "md5sum": "63bee5405fa1e209388adc6b5f78bb70", + "version": "6.33 (.vmdk)" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "MikroTik CHR", + "port_name_format": "ether{port1}", + "product_name": "MikroTik Cloud Hosted Router", + "product_url": "http://www.mikrotik.com/download", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "allow", + "options": "-nographic", + "ram": 128 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "If you'd like a different sized main disk, resize the image before booting the VM for the first time.\n\nOn first boot, RouterOS is actually being installed, formatting the whole main virtual disk, before finally rebooting. That whole process may take a minute or so.\n\nThe console will become available after the installation is complete. Most Telnet/SSH clients (certainly SuperPutty) will keep retrying to connect, thus letting you know when installation is done.\n\nFrom that point on, everything about RouterOS is also true about Cloud Hosted Router, including the default credentials: Username \"admin\" and an empty password.\n\nThe primary differences between RouterOS and CHR are in support for virtual devices (this appliance comes with them being selected), and in the different license model, for which you can read more about at http://wiki.mikrotik.com/wiki/Manual:CHR.", + "vendor_name": "MikroTik", + "vendor_url": "http://mikrotik.com/", + "versions": [ + { + "images": { + "hda_disk_image": "chr-6.43.8.img" + }, + "name": "6.43.8" + }, + { + "images": { + "hda_disk_image": "chr-6.42.9.img" + }, + "name": "6.42.9" + }, + { + "images": { + "hda_disk_image": "chr-6.41.4.img" + }, + "name": "6.41.4" + }, + { + "images": { + "hda_disk_image": "chr-6.40.7.img" + }, + "name": "6.40.7" + }, + { + "images": { + "hda_disk_image": "chr-6.40.5.img" + }, + "name": "6.40.5" + }, + { + "images": { + "hda_disk_image": "chr-6.40.3.img" + }, + "name": "6.40.3" + }, + { + "images": { + "hda_disk_image": "chr-6.39.2.img" + }, + "name": "6.39.2" + }, + { + "images": { + "hda_disk_image": "chr-6.39.1.img" + }, + "name": "6.39.1" + }, + { + "images": { + "hda_disk_image": "chr-6.39.img" + }, + "name": "6.39" + }, + { + "images": { + "hda_disk_image": "chr-6.38.7.img" + }, + "name": "6.38.7" + }, + { + "images": { + "hda_disk_image": "chr-6.38.5.img" + }, + "name": "6.38.5" + }, + { + "images": { + "hda_disk_image": "chr-6.38.1.img" + }, + "name": "6.38.1" + }, + { + "images": { + "hda_disk_image": "chr-6.38.img" + }, + "name": "6.38" + }, + { + "images": { + "hda_disk_image": "chr-6.37.3.img" + }, + "name": "6.37.3" + }, + { + "images": { + "hda_disk_image": "chr-6.37.1.img" + }, + "name": "6.37.1" + }, + { + "images": { + "hda_disk_image": "chr-6.36.4.img" + }, + "name": "6.36.4" + }, + { + "images": { + "hda_disk_image": "chr-6.34.2.vmdk" + }, + "name": "6.34.2 (.vmdk)" + }, + { + "images": { + "hda_disk_image": "chr-6.34.2.vdi" + }, + "name": "6.34.2 (.vdi)" + }, + { + "images": { + "hda_disk_image": "chr-6.34.2.img" + }, + "name": "6.34.2 (.img)" + }, + { + "images": { + "hda_disk_image": "chr-6.34.vmdk" + }, + "name": "6.34 (.vmdk)" + }, + { + "images": { + "hda_disk_image": "chr-6.34.vdi" + }, + "name": "6.34 (.vdi)" + }, + { + "images": { + "hda_disk_image": "chr-6.34.img" + }, + "name": "6.34 (.img)" + }, + { + "images": { + "hda_disk_image": "chr-6.33.5.vmdk" + }, + "name": "6.33.5 (.vmdk)" + }, + { + "images": { + "hda_disk_image": "chr-6.33.5.vdi" + }, + "name": "6.33.5 (.vdi)" + }, + { + "images": { + "hda_disk_image": "chr-6.33.5.img" + }, + "name": "6.33.5 (.img)" + }, + { + "images": { + "hda_disk_image": "chr-6.33.3.vmdk" + }, + "name": "6.33.3 (.vmdk)" + }, + { + "images": { + "hda_disk_image": "chr-6.33.2.vmdk" + }, + "name": "6.33.2 (.vmdk)" + }, + { + "images": { + "hda_disk_image": "chr-6.33.vmdk" + }, + "name": "6.33 (.vmdk)" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Monitoring a distributed network across multiple locations can be a challenge. That\u2019s where Sophos iView can help. It provides you with an intelligent, uninterrupted view of your network from a single pane of glass. If you have multiple appliances, need consolidated reporting, or could just use help with log management or compliance, Sophos iView is the ideal solution.", + "documentation_url": "https://www.sophos.com/en-us/support/documentation/sophos-iview.aspx", + "images": [ + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SIVOS_03.01.2.KVM-009-PRIMARY.qcow2", + "filesize": 644218880, + "md5sum": "62551f70f71e08283d3a23929321eba9", + "version": "3.1.2" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SIVOS_02.00.0_MR-2.KVM-776-PRIMARY.qcow2", + "filesize": 493289472, + "md5sum": "d78c6f0c42186a4c606d7e57f2f3a6d7", + "version": "2.0.0 MR2" + }, + { + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", + "filename": "VI-SIVOS-AUXILARY.qcow2", + "filesize": 204800, + "md5sum": "a52d8cedb1ccd4b5b9f2723dfb41588b", + "version": "2.0.0 MR2" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Sophos iView", + "product_name": "Sophos iView", + "product_url": "https://www.sophos.com/en-us/products/next-gen-firewall.aspx", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "require", + "ram": 4096 + }, + "registry_version": 3, + "status": "experimental", + "symbol": "mgmt_station.svg", + "usage": "Default CLI password: admin\nDefault WebUI address: http://172.16.16.18\nDefault WebUI credentials: admin / admin", + "vendor_name": "Sophos", + "vendor_url": "https://www.sophos.com", + "versions": [ + { + "images": { + "hda_disk_image": "VI-SIVOS_03.01.2.KVM-009-PRIMARY.qcow2", + "hdb_disk_image": "VI-SIVOS-AUXILARY.qcow2" + }, + "name": "3.1.2" + }, + { + "images": { + "hda_disk_image": "VI-SIVOS_02.00.0_MR-2.KVM-776-PRIMARY.qcow2", + "hdb_disk_image": "VI-SIVOS-AUXILARY.qcow2" + }, + "name": "2.0.0 MR2" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco Virtual IOS allows user to run IOS on a standard computer.", + "images": [ + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Qemu Appliances/IOSv_startup_config.img/download", + "download_url": "https://sourceforge.net/projects/gns-3/files", + "filename": "IOSv_startup_config.img", + "filesize": 1048576, + "md5sum": "bc605651c4688276f81fd59dcf5cc786", + "version": "1" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "vios-adventerprisek9-m.vmdk.SPA.156-2.T", + "filesize": 128450560, + "md5sum": "83707e3cc93646da58ee6563a68002b5", + "version": "15.6(2)T" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "vios-adventerprisek9-m.vmdk.SPA.156-1.T", + "filesize": 128122880, + "md5sum": "e7cb1bbd0c59280dd946feefa68fa270", + "version": "15.6(1)T" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "vios-adventerprisek9-m.vmdk.SPA.155-3.M", + "filesize": 127926272, + "md5sum": "79f613ac3b179d5a64520730925130b2", + "version": "15.5(3)M" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco IOSv", + "port_name_format": "Gi0/{0}", + "product_name": "IOSv", + "product_url": "http://virl.cisco.com/", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "arch": "x86_64", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "require", + "ram": 512 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "There is no default password and enable password. There is no default configuration present.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "vios-adventerprisek9-m.vmdk.SPA.156-2.T", + "hdb_disk_image": "IOSv_startup_config.img" + }, + "name": "15.6(2)T" + }, + { + "images": { + "hda_disk_image": "vios-adventerprisek9-m.vmdk.SPA.156-1.T", + "hdb_disk_image": "IOSv_startup_config.img" + }, + "name": "15.6(1)T" + }, + { + "images": { + "hda_disk_image": "vios-adventerprisek9-m.vmdk.SPA.155-3.M", + "hdb_disk_image": "IOSv_startup_config.img" + }, + "name": "15.5(3)M" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco IOS on UNIX Layer 3 image.", + "images": [ + { + "filename": "i86bi-linux-l3-adventerprisek9-ms.155-2.T.bin", + "filesize": 172982492, + "md5sum": "45e99761a95cbd3ee3924ecf0f3d89e5", + "version": "155-2T" + }, + { + "filename": "i86bi-linux-l3-adventerprisek9-15.4.1T.bin", + "filesize": 152677848, + "md5sum": "2eabae17778316c49cbc80e8e81262f9", + "version": "15.4.1T" + } + ], + "iou": { + "ethernet_adapters": 2, + "nvram": 128, + "ram": 256, + "serial_adapters": 2, + "startup_config": "iou_l3_base_startup-config.txt" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco IOU L3", + "product_name": "Cisco IOU L3", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "images": { + "image": "i86bi-linux-l3-adventerprisek9-ms.155-2.T.bin" + }, + "name": "155-2T" + }, + { + "images": { + "image": "i86bi-linux-l3-adventerprisek9-15.4.1T.bin" + }, + "name": "15.4.1T" + } + ] + }, + { + "availability": "free", + "builtin": true, + "category": "guest", + "description": "Mininet creates a realistic virtual network, running real kernel, switch and application code, on a single machine (VM, cloud or native), in seconds, with a single command.", + "documentation_url": "http://mininet.org/walkthrough/", + "first_port_name": "eth0", + "images": [ + { + "compression": "zip", + "direct_download_url": "https://github.com/mininet/mininet/releases/download/2.2.2/mininet-2.2.2-170321-ubuntu-14.04.4-server-amd64.zip", + "download_url": "https://github.com/mininet/mininet/releases/", + "filename": "mininet-vm-x86_64.vmdk", + "filesize": 2047868928, + "md5sum": "a683441642300bdaf37b8e614de85342", + "version": "2.2.2" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Mininet", + "port_name_format": "eth{0}", + "product_name": "Mininet", + "product_url": "http://mininet.org/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "arch": "x86_64", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "allow", + "ram": 2048 + }, + "registry_version": 4, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Username: mininet\nPassword: mininet", + "vendor_name": "Mininet Team", + "vendor_url": "http://mininet.org/", + "versions": [ + { + "images": { + "hda_disk_image": "mininet-vm-x86_64.vmdk" + }, + "name": "2.2.2" + } + ] + }, + { + "availability": "free", + "builtin": true, + "category": "router", + "description": "Vector Packet Processing (VPP) platform", + "documentation_url": "https://fd.io/resources/", + "images": [ + { + "direct_download_url": "https://sigaba.net/vpp/vpp_public-18.10-07.qcow2", + "filename": "vpp_public-18.10-07.qcow2", + "filesize": 2065825792, + "md5sum": "3e962985e5bbda0de4dc7893e60f6366", + "version": "0.7" + } + ], + "maintainer": "Virginijus Magelinskas", + "maintainer_email": "virginijus.m@gmail.com", + "name": "VPP", + "port_name_format": "eth{0}", + "product_name": "VPP", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 5, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "ide", + "kvm": "require", + "options": "-nographic -cpu host -smp 2", + "ram": 4096 + }, + "registry_version": 4, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "usage": "Login: root , pass: vpp. This appliance requires >2 vCPUs and 4GB of RAM to run", + "vendor_name": "FD.IO VPP router", + "vendor_url": "https://fd.io/", + "versions": [ + { + "images": { + "hda_disk_image": "vpp_public-18.10-07.qcow2" + }, + "name": "18.10-07" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Micro Core Linux is a smaller variant of Tiny Core without a graphical desktop.\n\nThis is complete Linux system needing few resources to run.", + "documentation_url": "http://wiki.tinycorelinux.net/", + "images": [ + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-microcore-6.4.img", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "linux-microcore-6.4.img", + "filesize": 16580608, + "md5sum": "877419f975c4891c019947ceead5c696", + "version": "6.4" + }, + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-microcore-4.0.2-clean.img", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "linux-microcore-4.0.2-clean.img", + "filesize": 26411008, + "md5sum": "e13d0d1c0b3999ae2386bba70417930c", + "version": "4.0.2" + }, + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-microcore-3.4.1.img", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "linux-microcore-3.4.1.img", + "filesize": 24969216, + "md5sum": "fa2ec4b1fffad67d8103c3391bbf9df2", + "version": "3.4.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Micro Core Linux", + "product_name": "Micro Core Linux", + "product_url": "http://distro.ibiblio.org/tinycorelinux", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "i386", + "console_type": "telnet", + "kvm": "allow", + "ram": 64 + }, + "registry_version": 3, + "status": "stable", + "symbol": "linux_guest.svg", + "usage": "For version >= 6.4, login/password is gns3. For older version it is tc. Note that sudo works without any password", + "vendor_name": "Team Tiny Core", + "vendor_url": "http://distro.ibiblio.org/tinycorelinux", + "versions": [ + { + "images": { + "hda_disk_image": "linux-microcore-6.4.img" + }, + "name": "6.4" + }, + { + "images": { + "hda_disk_image": "linux-microcore-4.0.2-clean.img" + }, + "name": "4.0.2" + }, + { + "images": { + "hda_disk_image": "linux-microcore-3.4.1.img" + }, + "name": "3.4.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "From the creators of BackTrack comes Kali Linux, the most advanced and versatile penetration testing platform ever created. We have a set of amazing features lined up in our security distribution geared at streamlining the penetration testing experience. This version has no GUI.Include packages:\n* nmap\n* metasploit\n* sqlmap\n* hydra\n* telnet client\n* dnsutils (dig)", + "docker": { + "adapters": 2, + "image": "gns3/kalilinux:v2" + }, + "documentation_url": "https://www.kali.org/kali-linux-documentation/", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Kali Linux CLI", + "product_name": "Kali Linux", + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/docker_guest.svg", + "vendor_name": "Kali Linux", + "vendor_url": "https://www.kali.org/" + }, + { + "builtin": true, + "category": "firewall", + "description": "OPNsense is an open source, easy-to-use and easy-to-build FreeBSD based firewall and routing platform. OPNsense includes most of the features available in expensive commercial firewalls, and more in many cases. It brings the rich feature set of commercial offerings with the benefits of open and verifiable sources.\n\nOPNsense started as a fork of pfSense\u00ae and m0n0wall in 2014, with its first official release in January 2015. The project has evolved very quickly while still retaining familiar aspects of both m0n0wall and pfSense. A strong focus on security and code quality drives the development of the project.", + "documentation_url": "https://wiki.opnsense.org/", + "images": [ + { + "download_url": "https://opnsense.c0urier.net/releases/18.1/", + "filename": "OPNsense-18.1.6-OpenSSL-nano-amd64.img", + "filesize": 272003136, + "md5sum": "042f328380ad0c8008759c43435e8843", + "version": "18.1.6" + }, + { + "download_url": "https://opnsense.c0urier.net/releases/17.7/", + "filename": "OPNsense-17.7.5-OpenSSL-nano-amd64.img", + "filesize": 237038601, + "md5sum": "6ec5b7f99cc727f904bbf2aaadcab0b8", + "version": "17.7.5" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "OPNsense", + "port_name_format": "em{0}", + "product_name": "OPNsense", + "product_url": "https://opnsense.org/about/about-opnsense/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Default credentials: root / opnsense\nDefault IP address: 192.168.1.1", + "vendor_name": "Deciso B.V.", + "vendor_url": "https://opnsense.org/", + "versions": [ + { + "images": { + "hda_disk_image": "OPNsense-18.1.6-OpenSSL-nano-amd64.img" + }, + "name": "18.1.6" + }, + { + "images": { + "hda_disk_image": "OPNsense-17.7.5-OpenSSL-nano-amd64.img" + }, + "name": "17.7.5" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "This appliance provides DNS using dnsmasq with the local domain set to \"lab\".", + "docker": { + "adapters": 1, + "console_type": "telnet", + "image": "adosztal/dns:latest" + }, + "maintainer": "Andras Dosztal", + "maintainer_email": "developers@gns3.net", + "name": "DNS", + "product_name": "DNS", + "registry_version": 3, + "status": "stable", + "symbol": "linux_guest.svg", + "usage": "You can add records by adding entries to the /etc/hosts file in the following format:\n%IP_ADDRESS% %HOSTNAME%.lab %HOSTNAME%\n\nExample:\n192.168.123.10 router1.lab router1", + "vendor_name": "Ubuntu", + "vendor_url": "https://www.ubuntu.com/" + }, + { + "builtin": true, + "category": "firewall", + "description": "Untangle\u2019s NG Firewall enables you to quickly and easily create the network policies that deliver the perfect balance between security and productivity. Untangle combines Unified Threat Management (UTM)\u2014to address all of the key network threats\u2014with policy management tools that enable you to define access and control by individuals, groups or company-wide. And with industry-leading reports, you\u2019ll have complete visibility into and control over everything that\u2019s happening on your network.", + "documentation_url": "http://wiki.untangle.com/index.php/Main_Page", + "images": [ + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1410_x64.iso", + "filesize": 682622976, + "md5sum": "49bb09e4796f225f482ca1d9c93de66b", + "version": "14.1.0" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1401_x64.iso", + "filesize": 680525824, + "md5sum": "d9c01afd8bf4b5dfdc40c22aa3b2fd98", + "version": "14.0.1" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1321_x64.iso", + "filesize": 627048448, + "md5sum": "4ce49535372f85565922c7e90bc11ba3", + "version": "13.2.1" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1320_x64.iso", + "filesize": 768000000, + "md5sum": "0ce2293acec0f37f1339e703653727f8", + "version": "13.2.0" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1310_x64.iso", + "filesize": 588251136, + "md5sum": "dc35aa96e954992e53a8cb244a932ae6", + "version": "13.1.0" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1300_x64.iso", + "filesize": 576716800, + "md5sum": "74dcb5c8e0fb400dbd3a9582fc472033", + "version": "13.0.0" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1221_x64.iso", + "filesize": 580911104, + "md5sum": "6735942441d487d339b92c1499b0052b", + "version": "12.2.1" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1220_x64.iso", + "filesize": 585105408, + "md5sum": "56947f059774f2f0015b6326cf5c63ac", + "version": "12.2.0" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1212_x64.iso", + "filesize": 575668224, + "md5sum": "2f48873316725b1f709015dfeb73d666", + "version": "12.1.2" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1211_x64.iso", + "filesize": 574619648, + "md5sum": "c7f38df4cbba72fa472a49454e476522", + "version": "12.1.1" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1210_x64.iso", + "filesize": 573571072, + "md5sum": "d511cbbd34aac7678c34a111c791806f", + "version": "12.1.0" + }, + { + "download_url": "https://www.untangle.com/get-untangle/", + "filename": "untangle_1201_x64.iso", + "filesize": 611319808, + "md5sum": "905171d04d2f029b193fe76b02ef9e11", + "version": "12.0.1" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Untangle NG", + "port_name_format": "eth{0}", + "product_name": "Untangle NG", + "product_url": "https://www.untangle.com/untangle-ng-firewall/", + "qemu": { + "adapter_type": "e1000", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "dc", + "console_type": "vnc", + "hda_disk_interface": "ide", + "kvm": "allow", + "ram": 1024 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Run the graphical or text based installer using VNC. The installer warns about insufficient memory but the provided 1G is enough, the installation will be successful.", + "vendor_name": "Untangle", + "vendor_url": "https://www.untangle.com/", + "versions": [ + { + "images": { + "cdrom_image": "untangle_1410_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "14.1.0" + }, + { + "images": { + "cdrom_image": "untangle_1401_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "14.0.1" + }, + { + "images": { + "cdrom_image": "untangle_1321_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "13.2.1" + }, + { + "images": { + "cdrom_image": "untangle_1320_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "13.2.0" + }, + { + "images": { + "cdrom_image": "untangle_1310_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "13.1.0" + }, + { + "images": { + "cdrom_image": "untangle_1300_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "13.0.0" + }, + { + "images": { + "cdrom_image": "untangle_1221_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "12.2.1" + }, + { + "images": { + "cdrom_image": "untangle_1220_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "12.2.0" + }, + { + "images": { + "cdrom_image": "untangle_1212_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "12.1.2" + }, + { + "images": { + "cdrom_image": "untangle_1211_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "12.1.1" + }, + { + "images": { + "cdrom_image": "untangle_1210_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "12.1.0" + }, + { + "images": { + "cdrom_image": "untangle_1201_x64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "12.0.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": " Parrot is a GNU/Linux distribution based on Debian Testing and designed with Security, Development and Privacy in mind. It includes a full portable laboratory for security and digital forensics experts, but it also includes all you need to develop your own software or protect your privacy while surfing the net.", + "documentation_url": "https://docs.parrotsec.org/doku.php", + "images": [ + { + "direct_download_url": "https://www.parrotsec.org/download-full.fx", + "download_url": "https://www.parrotsec.org/download.fx", + "filename": "Parrot-security-3.11_amd64.iso", + "filesize": 3788668928, + "md5sum": "71c94474fb474f682da0844d95f0040b", + "version": "Security Build 3.11" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%30disk/", + "filename": "empty30G.qcow2", + "filesize": 197120, + "md5sum": "3411a599e822f2ac6be560a26405821a", + "version": "1.0" + } + ], + "maintainer": "Brent Stewart", + "maintainer_email": "brent@stewart.tc", + "name": "ParrotOS", + "product_name": "ParrotOS", + "product_url": "https://parrotsec.org/", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "console_type": "vnc", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "parrotlogo.png", + "usage": "Passwords are set during installation.", + "vendor_name": "Parrot Project", + "vendor_url": "https://parrotsec.org/", + "versions": [ + { + "images": { + "cdrom_image": "Parrot-security-3.11_amd64.iso", + "hda_disk_image": "empty30G.qcow2" + }, + "name": "Security Build 3.11" + } + ] + }, + { + "availability": "service-contract", + "builtin": true, + "category": "firewall", + "description": "Cisco Firepower Next-Generation IPS (NGIPS) threat appliances combine superior visibility, embedded security intelligence, automated analysis, and industry-leading threat effectiveness.", + "documentation_url": "http://www.cisco.com/c/en/us/support/security/ngips-virtual-appliance/tsd-products-support-series-home.html", + "first_port_name": "eth0 (Mgmt)", + "images": [ + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286259690&softwareid=286271056&release=6.0.0.0&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "Cisco_Firepower_NGIPSv_VMware-6.0.0-1005-disk1.vmdk", + "filesize": 804301312, + "md5sum": "72ed34d39c58a9d5ad1c6197d1ff9a62", + "version": "6.0.0 (1005) vmdk" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286259690&softwareid=286271056&release=6.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "Cisco_Firepower_NGIPSv_VMware-6.1.0-330-disk1.vmdk", + "filesize": 860411392, + "md5sum": "7a771cc8c37a0371285f24c25f9886f0", + "version": "6.1.0 (330) vmdk" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=286259690&softwareid=286271056&release=6.2.0&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "Cisco_Firepower_NGIPSv_VMware-6.2.0-362-disk1.vmdk", + "filesize": 877626368, + "md5sum": "46f629149e11ac5c224bae0486c7e406", + "version": "6.2.0 (362) vmdk" + } + ], + "maintainer": "Community", + "maintainer_email": "", + "name": "Cisco NGIPSv", + "port_name_format": "eth{port1}", + "product_name": "Cisco Firepower NGIPS Virtual", + "product_url": "http://www.cisco.com/c/en/us/support/security/ngips-virtual-appliance/tsd-products-support-series-home.html", + "qemu": { + "adapter_type": "vmxnet3", + "adapters": 10, + "arch": "x86_64", + "console_type": "telnet", + "cpus": 4, + "hda_disk_interface": "scsi", + "kvm": "require", + "ram": 8192 + }, + "registry_version": 4, + "status": "experimental", + "symbol": ":/symbols/classic/firewall.svg", + "usage": "Default username/password: admin/Admin123.", + "vendor_name": "Cisco Systems", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "Cisco_Firepower_NGIPSv_VMware-6.2.0-362-disk1.vmdk" + }, + "name": "6.2.0 (362) vmdk" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_NGIPSv_VMware-6.1.0-330-disk1.vmdk" + }, + "name": "6.1.0 (330) vmdk" + }, + { + "images": { + "hda_disk_image": "Cisco_Firepower_NGIPSv_VMware-6.0.0-1005-disk1.vmdk" + }, + "name": "6.0.0 (1005) vmdk" + } + ] + }, + { + "builtin": true, + "category": "firewall", + "description": "Trend Micro InterScan Web Security Virtual Appliance is a secure web gateway that combines application control with zero-day exploit detection, advanced anti-malware and ransomware scanning, real-time web reputation, and flexible URL filtering to provide superior Internet threat protection.", + "documentation_url": "https://success.trendmicro.com/product-support/interscan-web-security-virtual-appliance", + "images": [ + { + "direct_download_url": "http://files.trendmicro.com/products/iwsva/IWSVA-6.5-1200-x86_64.iso", + "download_url": "http://downloadcenter.trendmicro.com/index.php?regs=NABU&clk=latest&clkval=4599&lang_loc=1", + "filename": "IWSVA-6.5-1200-x86_64.iso", + "filesize": 1004965888, + "md5sum": "7eb0d2a44e20b69ae0c3ce73d6cc1182", + "version": "6.5" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 198656, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "IWS VA", + "port_name_format": "eth{0}", + "product_name": "IWS VA", + "product_url": "http://www.trendmicro.com/enterprise/network-security/interscan-web-security/virtual-appliance/index.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 4096 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/firewall.svg", + "vendor_name": "Trend Micro Inc.", + "vendor_url": "http://www.trendmicro.com/", + "versions": [ + { + "images": { + "cdrom_image": "IWSVA-6.5-1200-x86_64.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "6.5" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "FortiADC Manager allows you to use a web- based user interface to configure remote FortiADC devices. It allows you to simplify and speed up the FortiADC deployment and update process by maintaining configuration templates and policy packages that you can modify and apply as needed.", + "documentation_url": "https://docs.fortinet.com/fortiadc-manager/", + "images": [ + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FADCManager-KVM-V500-build0020-FORTINET.out.kvm-boot.qcow2", + "filesize": 70057984, + "md5sum": "a79d04040848b704ce4efe925518fd3f", + "version": "5.2.0" + }, + { + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", + "filename": "FADCManager-KVM-v500-data.qcow2", + "filesize": 30998528, + "md5sum": "b7500835594e62d8acb1c6ec43d597c1", + "version": "5.x" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiADC Manager", + "port_name_format": "Port{port1}", + "product_name": "FortiADC Manager", + "product_url": "https://www.fortinet.com/products/application-delivery-controller/fortiadc.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 10, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "allow", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "Default username is admin, no password is set.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FADCManager-KVM-V500-build0020-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FADCManager-KVM-v500-data.qcow2" + }, + "name": "5.2.0" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "The OpenBSD project produces a FREE, multi-platform 4.4BSD-based UNIX-like operating system. Our efforts emphasize portability, standardization, correctness, proactive security and integrated cryptography. As an example of the effect OpenBSD has, the popular OpenSSH software comes from OpenBSD.", + "documentation_url": "http://www.openbsd.org/faq/index.html", + "first_port_name": "fxp0", + "images": [ + { + "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/openbsd-5.8.qcow2", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "openbsd-5.8.qcow2", + "filesize": 517275648, + "md5sum": "b2488d81bbe1328ae3d6072ccd7e0bc2", + "version": "5.8" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "OpenBSD", + "port_name_format": "em{0}", + "product_name": "OpenBSD", + "qemu": { + "adapter_type": "e1000", + "adapters": 8, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "allow", + "ram": 256 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "User root, password gns3", + "vendor_name": "OpenBSD", + "vendor_url": "http://www.openbsd.org", + "versions": [ + { + "images": { + "hda_disk_image": "openbsd-5.8.qcow2" + }, + "name": "5.8" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "The BIG-IP family of products offers the application intelligence that network managers need to ensure applications are fast, secure, and available. All BIG-IP products share a common underlying architecture, F5's Traffic Management Operating System (TMOS), which provides unified intelligence, flexibility, and programmability. Together, BIG-IP's powerful platforms, advanced modules, and centralized management system make up the most comprehensive set of application delivery tools in the industry. BIG-IP Virtual Edition (VE) is a version of the BIG-IP system that runs as a virtual machine in specifically-supported hypervisors. BIG-IP VE emulates a hardware-based BIG-IP system running a VE-compatible version of BIG-IP software.", + "documentation_url": "https://support.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/bigip-ve-kvm-setup-11-3-0.html", + "images": [ + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v14.x/14.0.0/english/14.0.0.3_virtual-edition/&sw=BIG-IP&pro=big-ip_v14.x&ver=14.0.0&container=14.0.0.3_Virtual-Edition&file=BIGIP-14.0.0.3-0.0.4.ALL.qcow2.zip", + "filename": "BIGIP-14.0.0.3-0.0.4.qcow2", + "filesize": 4550164480, + "md5sum": "dc80a7e436ff93e2f4092eece18d369b", + "version": "14.0.0 HF3" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v13.x/13.1.0/english/13.1.0.5_virtual-edition/&sw=BIG-IP&pro=big-ip_v13.x&ver=13.1.0&container=13.1.0.5_Virtual-Edition&file=BIGIP-13.1.0.5-0.0.5.ALL.qcow2.zip", + "filename": "BIGIP-13.1.0.5-0.0.5.qcow2", + "filesize": 4402446336, + "md5sum": "567b70fe36af0f5364883e97e2c08807", + "version": "13.1.0 HF5" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v13.x/13.1.0/english/13.1.0.2_virtual-edition/&sw=BIG-IP&pro=big-ip_v13.x&ver=13.1.0&container=13.1.0.2_Virtual-Edition&file=BIGIP-13.1.0.2.0.0.6.ALL.qcow2.zip", + "filename": "BIGIP-13.1.0.2.0.0.6.qcow2", + "filesize": 4363649024, + "md5sum": "d29eb861d8906fc36f88d9861a0055f4", + "version": "13.1.0 HF2" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v13.x/13.1.0/english/13.1.0.1_virtual-edition/&sw=BIG-IP&pro=big-ip_v13.x&ver=13.1.0&container=13.1.0.1_Virtual-Edition&file=BIGIP-13.1.0.1.0.0.8.ALL.qcow2.zip", + "filename": "BIGIP-13.1.0.1.0.0.8.qcow2", + "filesize": 4352966656, + "md5sum": "70f92192e66a82cb8f47bdae0cb267d8", + "version": "13.1.0 HF1" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v13.x/13.0.0/english/virtual-edition_base-plus-hf2/&sw=BIG-IP&pro=big-ip_v13.x&ver=13.0.0&container=Virtual-Edition_Base-Plus-HF2&file=BIGIP-13.0.0.2.0.1671.LTM.qcow2.zip", + "filename": "BIGIP-13.0.0.2.0.1671.qcow2", + "filesize": 4435476480, + "md5sum": "62d27f37c66118710c69c07a2ee78d67", + "version": "13.0.0 HF2" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v13.x/13.0.0/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v13.x&ver=13.0.0&container=Virtual-Edition&file=BIGIP-13.0.0.0.0.1645.ALL.qcow2.zip", + "filename": "BIGIP-13.0.0.0.0.1645.qcow2", + "filesize": 3833135104, + "md5sum": "4ec417477c44cdf84edc825a631990e3", + "version": "13.0.0" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.3/english/12.1.3.4_virtual-edition/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.3&container=12.1.3.4_Virtual-Edition&file=BIGIP-12.1.3.4-0.0.2.ALL.qcow2.zip", + "filename": "BIGIP-12.1.3.4-0.0.2.qcow2", + "filesize": 3383164928, + "md5sum": "b2ec82816480c18af1d45ee833744ee8", + "version": "12.1.3 HF4" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.2/english/virtual-edition_base-plus-hf1/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.2&container=Virtual-Edition_Base-Plus-HF1&file=BIGIP-12.1.2.1.0.271.LTM.qcow2.zip", + "filename": "BIGIP-12.1.2.1.0.271.LTM.qcow2", + "filesize": 3764846592, + "md5sum": "b34301c3945b7ddb88f41195efef1104", + "version": "12.1.2 HF1" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.2/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.2&container=Virtual-Edition&file=BIGIP-12.1.2.0.0.249.LTM.qcow2.zip", + "filename": "BIGIP-12.1.2.0.0.249.qcow2", + "filesize": 3196649472, + "md5sum": "f3aa2d51d82fa3f5a4fa10005a378e16", + "version": "12.1.2" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.1/english/virtual-edition_base-plus-hf2/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.1&container=Virtual-Edition_Base-Plus-HF2&file=BIGIP-12.1.1.2.0.204.LTM.qcow2.zip", + "filename": "BIGIP-12.1.1.2.0.204.qcow2", + "filesize": 3563716608, + "md5sum": "74d4d21db3579efb9011a1829a2124b7", + "version": "12.1.1 HF2" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.0/english/virtual-edition_base-plus-hf1/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.0&container=Virtual-Edition_Base-Plus-HF1&file=BIGIP-12.1.0.1.0.1447.ALL.qcow2.zip", + "filename": "BIGIP-12.1.0.1.0.1447.qcow2", + "filesize": 3503226880, + "md5sum": "15725ba2c72a0fe932985e695f0f3f1f", + "version": "12.1.0 HF1" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.0.0/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.0.0&container=Virtual-Edition&file=BIGIP-12.0.0.0.0.606.ALL.qcow2.zip", + "filename": "BIGIP-12.0.0.0.0.606.qcow2", + "filesize": 3152609280, + "md5sum": "8f578d697554841f003afd1e2965df7e", + "version": "12.0.0" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v11.x/11.6.1/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v11.x&ver=11.6.1&container=Virtual-Edition&file=BIGIP-11.6.1.0.0.317.ALL.qcow2.zip", + "filename": "BIGIP-11.6.1.0.0.317.qcow2", + "filesize": 2824273920, + "md5sum": "01a2939840d81458bfef0a5c53fb74be", + "version": "11.6.1" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v11.x/11.6.0/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v11.x&ver=11.6.0&container=Virtual-Edition&file=BIGIP-11.6.0.0.0.401.ALL.qcow2.zip", + "filename": "BIGIP-11.6.0.0.0.401.qcow2", + "filesize": 2851733504, + "md5sum": "87723dc8c9713a36bde9a650b94205e3", + "version": "11.6.0" + }, + { + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v11.x/11.3.0/english/virtual-edition-trial/&sw=BIG-IP&pro=big-ip_v11.x&ver=11.3.0&container=Virtual-Edition-Trial&file=BIGIP-11.3.0.39.0.qcow2.zip", + "filename": "BIGIP-11.3.0.39.0.qcow2", + "filesize": 1842020352, + "md5sum": "f3dec4565484fe81233077ab2ce426ae", + "version": "11.3.0" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 198656, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "F5 BIG-IP LTM VE", + "port_name_format": "1.{port1}", + "product_name": "F5 BIG-IP LTM VE", + "product_url": "https://f5.com/products/modules/local-traffic-manager", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 8, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "require", + "options": "-smp 2 -cpu host", + "ram": 4096 + }, + "registry_version": 3, + "status": "stable", + "symbol": "loadbalancer.svg", + "usage": "Console credentials: root/default. WebUI credentials: admin/admin. The boot process might take a few minutes without providing any output to the console. Please be patient (or set console to vnc to see tty outputs).\n\nIn case the 'localhost emerg logger: Re-starting chmand' log appears on the console, you can find the solution here: https://devcentral.f5.com/questions/big-ip-ltm-ve-on-kvm", + "vendor_name": "F5", + "vendor_url": "http://www.f5.com/", + "versions": [ + { + "images": { + "hda_disk_image": "BIGIP-14.0.0.3-0.0.4.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "14.0.0 HF3" + }, + { + "images": { + "hda_disk_image": "BIGIP-13.1.0.5-0.0.5.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "13.1.0 HF5" + }, + { + "images": { + "hda_disk_image": "BIGIP-13.1.0.2.0.0.6.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "13.1.0 HF2" + }, + { + "images": { + "hda_disk_image": "BIGIP-13.1.0.1.0.0.8.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "13.1.0 HF1" + }, + { + "images": { + "hda_disk_image": "BIGIP-13.0.0.2.0.1671.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "13.0.0 HF2" + }, + { + "images": { + "hda_disk_image": "BIGIP-13.0.0.0.0.1645.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "13.0.0" + }, + { + "images": { + "hda_disk_image": "BIGIP-12.1.3.4-0.0.2.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "12.1.3 HF4" + }, + { + "images": { + "hda_disk_image": "BIGIP-12.1.2.1.0.271.LTM.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "12.1.2 HF1" + }, + { + "images": { + "hda_disk_image": "BIGIP-12.1.2.0.0.249.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "12.1.2" + }, + { + "images": { + "hda_disk_image": "BIGIP-12.1.1.2.0.204.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "12.1.1 HF2" + }, + { + "images": { + "hda_disk_image": "BIGIP-12.1.0.1.0.1447.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "12.1.0 HF1" + }, + { + "images": { + "hda_disk_image": "BIGIP-12.0.0.0.0.606.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "12.0.0" + }, + { + "images": { + "hda_disk_image": "BIGIP-11.6.1.0.0.317.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "11.6.1" + }, + { + "images": { + "hda_disk_image": "BIGIP-11.6.0.0.0.401.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "11.6.0" + }, + { + "images": { + "hda_disk_image": "BIGIP-11.3.0.39.0.qcow2", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "11.3.0" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "Arista EOS\u00ae is the core of Arista cloud networking solutions for next-generation data centers and cloud networks. Cloud architectures built with Arista EOS scale to tens of thousands of compute and storage nodes with management and provisioning capabilities that work at scale. Through its programmability, EOS enables a set of software applications that deliver workflow automation, high availability, unprecedented network visibility and analytics and rapid integration with a wide range of third-party applications for virtualization, management, automation and orchestration services.\n\nArista Extensible Operating System (EOS) is a fully programmable and highly modular, Linux-based network operation system, using familiar industry standard CLI and runs a single binary software image across the Arista switching family. Architected for resiliency and programmability, EOS has a unique multi-process state sharing architecture that separates state information and packet forwarding from protocol processing and application logic.", + "documentation_url": "https://www.arista.com/assets/data/docs/Manuals/EOS-4.17.2F-Manual.pdf", + "first_port_name": "Management1", + "images": [ + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.21.1.1F.vmdk", + "filesize": 358809600, + "md5sum": "02bfb7e53781fd44ff02357f201586d9", + "version": "4.21.1.1F" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.20.11M.vmdk", + "filesize": 658178048, + "md5sum": "19e482a193f237c157ce35c389ca9417", + "version": "4.20.11M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.20.1F.vmdk", + "filesize": 662044672, + "md5sum": "aadb6f3dbff28317f68cb4c4502d0db8", + "version": "4.20.1F" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.18.5M.vmdk", + "filesize": 623116288, + "md5sum": "b1ee6268dbaf2b2276fd7a5286c7ce2b", + "version": "4.18.5M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.18.1F.vmdk", + "filesize": 620625920, + "md5sum": "9648c63185f3b793b47528a858ca4364", + "version": "4.18.1F" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.17.8M.vmdk", + "filesize": 608829440, + "md5sum": "afc79a06f930ea2cc0ae3e03cbfd3f23", + "version": "4.17.8M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.17.2F.vmdk", + "filesize": 609615872, + "md5sum": "3b4845edfa77cf9aaeb9c0a005d3e277", + "version": "4.17.2F" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.16.13M.vmdk", + "filesize": 521404416, + "md5sum": "4d0facf90140fc3aab031f0f8f88a32f", + "version": "4.16.13M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.16.6M.vmdk", + "filesize": 519962624, + "md5sum": "b3f7b7cee17f2e66bb38b453a4939fef", + "version": "4.16.6M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.15.10M.vmdk", + "filesize": 517079040, + "md5sum": "98e08281a9c48ddf6f3c5d62a124a20f", + "version": "4.15.10M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.15.5M.vmdk", + "filesize": 516030464, + "md5sum": "cd74bb69c7ee905ac3d33c4d109f3ab7", + "version": "4.15.5M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.14.14M.vmdk", + "filesize": 422641664, + "md5sum": "d81ba0522f4d7838d96f7985e41cdc47", + "version": "4.14.14M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.13.16M.vmdk", + "filesize": 404684800, + "md5sum": "5763b2c043830c341c8b1009f4ea9a49", + "version": "4.13.16M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "vEOS-lab-4.13.8M.vmdk", + "filesize": 409010176, + "md5sum": "a47145b9e6e7a24171c0850f8755535e", + "version": "4.13.8M" + }, + { + "download_url": "https://www.arista.com/en/support/software-download", + "filename": "Aboot-veos-serial-8.0.0.iso", + "filesize": 5242880, + "md5sum": "488ad1c435d18c69bb8d69c7806457c9", + "version": "8.0.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Arista vEOS", + "port_name_format": "Ethernet{port1}", + "product_name": "vEOS", + "product_url": "https://eos.arista.com/", + "qemu": { + "adapter_type": "e1000", + "adapters": 13, + "arch": "x86_64", + "boot_priority": "d", + "console_type": "telnet", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "The login is admin, with no password by default", + "vendor_name": "Arista", + "vendor_url": "http://www.arista.com/", + "versions": [ + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.21.1.1F.vmdk" + }, + "name": "4.21.1.1F" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.20.11M.vmdk" + }, + "name": "4.20.11M" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.20.1F.vmdk" + }, + "name": "4.20.1F" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.18.5M.vmdk" + }, + "name": "4.18.5M" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.18.1F.vmdk" + }, + "name": "4.18.1F" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.17.8M.vmdk" + }, + "name": "4.17.8M" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.17.2F.vmdk" + }, + "name": "4.17.2F" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.16.13M.vmdk" + }, + "name": "4.16.13M" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.16.6M.vmdk" + }, + "name": "4.16.6M" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.15.10M.vmdk" + }, + "name": "4.15.10M" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.15.5M.vmdk" + }, + "name": "4.15.5M" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.14.14M.vmdk" + }, + "name": "4.14.14M" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.13.16M.vmdk" + }, + "name": "4.13.16M" + }, + { + "images": { + "cdrom_image": "Aboot-veos-serial-8.0.0.iso", + "hda_disk_image": "vEOS-lab-4.13.8M.vmdk" + }, + "name": "4.13.8M" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "The CloudRouter Project is a collaborative open source project focused on developing a powerful, easy to use router designed for the cloud.\nCompute resources are rapidly migrating from physical infrastructure to a combination of physical, virtual and cloud environments. A similar transition is emerging in the networking space, with network control logic shifting from proprietary hardware-based platforms to open source software-based platforms. CloudRouter is a software-based router distribution designed to run on physical, virtual and cloud environments, supporting software-defined networking infrastructure. It includes the features of traditional hardware routers, as well as support for emerging technologies such as containers and software-defined interconnection. CloudRouter aims to facilitate migration to the cloud without giving up control over network routing and governance.", + "documentation_url": "https://cloudrouter.atlassian.net/wiki/display/CPD/CloudRouter+Project+Information", + "images": [ + { + "compression": "xz", + "direct_download_url": "https://repo.cloudrouter.org/4/centos/7/images/cloudrouter-centos-cloud-full.raw.xz", + "download_url": "https://cloudrouter.atlassian.net/wiki/display/CPD/CloudRouter+Downloads", + "filename": "cloudrouter-centos-cloud-full.raw", + "filesize": 10737418240, + "md5sum": "d148288ecc0806e08f8347ef0ad755e8", + "version": "4.0 Full" + }, + { + "compression": "xz", + "direct_download_url": "https://repo.cloudrouter.org/4/centos/7/images/cloudrouter-centos-cloud-minimal.raw.xz", + "download_url": "https://cloudrouter.atlassian.net/wiki/display/CPD/CloudRouter+Downloads", + "filename": "cloudrouter-centos-cloud-minimal.raw", + "filesize": 10737418240, + "md5sum": "8d982a37a49bc446a0edc59cefcadcdb", + "version": "4.0 Minimal" + }, + { + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/cloudrouter-init-gns3.iso/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", + "filename": "cloudrouter-init-gns3.iso", + "filesize": 374784, + "md5sum": "8cfb7e338bf241cc64abc084243e9be1", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "CloudRouter", + "port_name_format": "eth{0}", + "product_name": "CloudRouter", + "product_url": "https://cloudrouter.org/about/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 16, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "Default credentials: cloudrouter / gns3", + "vendor_name": "CloudRouter Community", + "vendor_url": "https://cloudrouter.org/", + "versions": [ + { + "images": { + "cdrom_image": "cloudrouter-init-gns3.iso", + "hda_disk_image": "cloudrouter-centos-cloud-full.raw" + }, + "name": "4.0 Full" + }, + { + "images": { + "cdrom_image": "cloudrouter-init-gns3.iso", + "hda_disk_image": "cloudrouter-centos-cloud-minimal.raw" + }, + "name": "4.0 Minimal" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Breaches to network security continue to occur across all industry verticals, even to the most respected brands. The time it takes to discover, isolate, and remediate the incident continues to be measured in hundreds of days-having material impacts on security and compliance standards. It is no wonder that many organizations are struggling. As recent surveys have shown, enterprises have an average of 32 different vendors' devices in their network, with no automated ability to cross-correlate the data that each is collecting. It is also easy to see why organizations are strapped for the cyber security personnel they need to manage all the data in these complex environments.\n\nFrom its inception, FortiSIEM was built to reduce complexity in managing network and security operations. FortiSIEM provides organizations of all sizes with a comprehensive, holistic, and scalable solution for managing security, performance, and compliance from IoT to the cloud.", + "documentation_url": "http://docs.fortinet.com/fortisiem/admin-guides", + "images": [ + { + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html", + "filename": "FortiSIEM-VA-5.1.0.1336.qcow2", + "filesize": 10376904704, + "md5sum": "753685ee68287c7a56f9da53566ac522", + "version": "5.1.0" + }, + { + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html", + "filename": "FortiSIEM-VA-5.1.0.1336-1.qcow2", + "filesize": 46858240, + "md5sum": "6ffb7e16d89a6731fc077982cb012ee2", + "version": "5.1.0" + }, + { + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html", + "filename": "FortiSIEM-VA-5.1.0.1336-2.qcow2", + "filesize": 46858240, + "md5sum": "8185e537ce222c2e8407e9bf08e604bb", + "version": "5.1.0" + }, + { + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release500.html", + "filename": "FortiSIEM-VA-5.0.0.1201.qcow2", + "filesize": 10029432832, + "md5sum": "1f2f0b1d84e89495fc5b5ca722cb5710", + "version": "5.0.0" + }, + { + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release500.html", + "filename": "FortiSIEM-VA-5.0.0.1201-1.qcow2", + "filesize": 46858240, + "md5sum": "88e96259f44a82b7c545b82925880513", + "version": "5.0.0" + }, + { + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release500.html", + "filename": "FortiSIEM-VA-5.0.0.1201-2.qcow2", + "filesize": 46858240, + "md5sum": "58d61498e1adc1df062fc12113d42d86", + "version": "5.0.0" + }, + { + "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", + "filename": "FortiSIEM-VA-KVM-4.10.0.1102.qcow2", + "filesize": 8622505984, + "md5sum": "636d94c78ea02e5a39eadb9d44210dfb", + "version": "4.10.0" + }, + { + "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", + "filename": "FortiSIEM-VA-KVM-4.10.0.1102-1.qcow2", + "filesize": 46858240, + "md5sum": "52fee02e94fd220275b613a4ec5b46eb", + "version": "4.10.0" + }, + { + "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", + "filename": "FortiSIEM-VA-KVM-4.10.0.1102-2.qcow2", + "filesize": 46858240, + "md5sum": "088a34864e30abdb95385b089574baba", + "version": "4.10.0" + }, + { + "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", + "filename": "FortiSIEM-VA-KVM-4.9.0.1041.qcow2", + "filesize": 8484487168, + "md5sum": "c2db828b6985297b33833f376c5106b0", + "version": "4.9.0" + }, + { + "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", + "filename": "FortiSIEM-VA-KVM-4.9.0.1041-1.qcow2", + "filesize": 46858240, + "md5sum": "b3f0cd44995f37648aa429303eeeb455", + "version": "4.9.0" + }, + { + "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", + "filename": "FortiSIEM-VA-KVM-4.9.0.1041-2.qcow2", + "filesize": 46858240, + "md5sum": "70a8abb4253d5bb724ded3b33a8385c4", + "version": "4.9.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FortiSIEM", + "port_name_format": "Port{port1}", + "product_name": "FortiSIEM", + "product_url": "https://www.fortinet.com/products/siem/fortisiem.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "hdc_disk_interface": "virtio", + "kvm": "require", + "options": "-smp 4", + "ram": 16384 + }, + "registry_version": 3, + "status": "stable", + "symbol": "fortinet.svg", + "usage": "This is the Super/Worker component. Default credentials:\n- admin / admin*1\n - root / ProspectHills\n\nIf you get a 503 error on the WebUI, run /opt/phoenix/deployment/jumpbox/phinitsuper as root.\n\nMake sure that Super, Worker(s), Collector(s) and Report Server can connect to FortiSIEM hosted CentOS repo on https port 443 under the URLs below. Otherwise, some packages may not install and 5.0.0 binaries will not run.\n- https://os-pkgs-cdn.fortisiem.fortinet.com/centos6/\n- https://os-pkgs.fortisiem.fortinet.com/centos6/", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "versions": [ + { + "images": { + "hda_disk_image": "FortiSIEM-VA-5.1.0.1336.qcow2", + "hdb_disk_image": "FortiSIEM-VA-5.1.0.1336-1.qcow2", + "hdc_disk_image": "FortiSIEM-VA-5.1.0.1336-2.qcow2" + }, + "name": "5.1.0" + }, + { + "images": { + "hda_disk_image": "FortiSIEM-VA-5.0.0.1201.qcow2", + "hdb_disk_image": "FortiSIEM-VA-5.0.0.1201-1.qcow2", + "hdc_disk_image": "FortiSIEM-VA-5.0.0.1201-2.qcow2" + }, + "name": "5.0.0" + }, + { + "images": { + "hda_disk_image": "FortiSIEM-VA-KVM-4.10.0.1102.qcow2", + "hdb_disk_image": "FortiSIEM-VA-KVM-4.10.0.1102-1.qcow2", + "hdc_disk_image": "FortiSIEM-VA-KVM-4.10.0.1102-2.qcow2" + }, + "name": "4.10.0" + }, + { + "images": { + "hda_disk_image": "FortiSIEM-VA-KVM-4.9.0.1041.qcow2", + "hdb_disk_image": "FortiSIEM-VA-KVM-4.9.0.1041-1.qcow2", + "hdc_disk_image": "FortiSIEM-VA-KVM-4.9.0.1041-2.qcow2" + }, + "name": "4.9.0" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. This is a version of the appliance with a management interface on eth0.", + "docker": { + "adapters": 16, + "environment": "MANAGEMENT_INTERFACE=1", + "image": "gns3/openvswitch:latest" + }, + "documentation_url": "http://openvswitch.org/support/", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Open vSwitch management", + "product_name": "Open vSwitch", + "registry_version": 3, + "status": "stable", + "symbol": "mgmt_station_docker.svg", + "usage": "The eth0 is the management interface. By default all other interfaces are connected to the br0", + "vendor_name": "Open vSwitch", + "vendor_url": "http://openvswitch.org/" + }, + { + "builtin": true, + "category": "guest", + "description": "Stay connected to your customers and colleagues without being chained to your desk.\nKerio Operator is a VoIP based phone system that provides powerful yet affordable enterprise-class voice and video communication capabilities for small and mid-sized businesses globally.", + "documentation_url": "http://kb.kerio.com/product/kerio-operator/", + "images": [ + { + "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.6.4-9320/kerio-operator-appliance-2.6.4-9320-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-operator", + "filename": "kerio-operator-appliance-2.6.4-9320-vmware-disk1.vmdk", + "filesize": 307840512, + "md5sum": "3823565dbc96069dc556158ebbbfb977", + "version": "2.6.4" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.6.2-9085/kerio-operator-appliance-2.6.2-9085-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-operator", + "filename": "kerio-operator-appliance-2.6.2-9085-vmware-disk1.vmdk", + "filesize": 306665472, + "md5sum": "abdfa7697e568b5d9a6396e11292e52a", + "version": "2.6.2" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.6.0-8413/kerio-operator-appliance-2.6.0-8413-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-operator", + "filename": "kerio-operator-appliance-2.6.0-8413-vmware-disk1.vmdk", + "filesize": 291227136, + "md5sum": "3eddbb73d685ac4666841f5df2c6bec9", + "version": "2.6.0" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.5.5-8309/kerio-operator-appliance-2.5.5-8309-p2-vmware-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-operator", + "filename": "kerio-operator-appliance-2.5.5-8309-p2-vmware-disk1.vmdk", + "filesize": 291217408, + "md5sum": "dc0b4d0b264eb39c8c73289b6c8de749", + "version": "2.5.5p2" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.5.4-6916/kerio-operator-appliance-2.5.4-6916-p1-vmware.vmdk", + "download_url": "http://www.kerio.com/support/kerio-operator", + "filename": "kerio-operator-appliance-2.5.4-6916-p1-vmware.vmdk", + "filesize": 276318720, + "md5sum": "6737b36bd36635b8a5ba21816938f0d6", + "version": "2.5.4p1" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.5.3-6630/kerio-operator-appliance-2.5.3-6630-vmware.vmdk", + "download_url": "http://www.kerio.com/support/kerio-operator", + "filename": "kerio-operator-appliance-2.5.3-6630-vmware.vmdk", + "filesize": 276422144, + "md5sum": "ae9f45606900dba05f353a94d4fc14fc", + "version": "2.5.3" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.5.2-6404/kerio-operator-appliance-2.5.2-6404-vmware.vmdk", + "download_url": "http://www.kerio.com/support/kerio-operator", + "filename": "kerio-operator-appliance-2.5.2-6404-vmware.vmdk", + "filesize": 561512448, + "md5sum": "0279baebe587b17f32bfc3302df9352c", + "version": "2.5.2" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Kerio Operator", + "port_name_format": "eth{0}", + "product_name": "Kerio Operator", + "product_url": "http://www.kerio.com/products/kerio-operator", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Default credentials: root (no password set)", + "vendor_name": "Kerio Technologies Inc.", + "vendor_url": "http://www.kerio.com", + "versions": [ + { + "images": { + "hda_disk_image": "kerio-operator-appliance-2.6.4-9320-vmware-disk1.vmdk" + }, + "name": "2.6.4" + }, + { + "images": { + "hda_disk_image": "kerio-operator-appliance-2.6.2-9085-vmware-disk1.vmdk" + }, + "name": "2.6.2" + }, + { + "images": { + "hda_disk_image": "kerio-operator-appliance-2.6.0-8413-vmware-disk1.vmdk" + }, + "name": "2.6.0" + }, + { + "images": { + "hda_disk_image": "kerio-operator-appliance-2.5.5-8309-p2-vmware-disk1.vmdk" + }, + "name": "2.5.5p2" + }, + { + "images": { + "hda_disk_image": "kerio-operator-appliance-2.5.4-6916-p1-vmware.vmdk" + }, + "name": "2.5.4p1" + }, + { + "images": { + "hda_disk_image": "kerio-operator-appliance-2.5.3-6630-vmware.vmdk" + }, + "name": "2.5.3" + }, + { + "images": { + "hda_disk_image": "kerio-operator-appliance-2.5.2-6404-vmware.vmdk" + }, + "name": "2.5.2" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "The vQFX10000 makes it easy for you to try out our physical QFX10000 high-performance data center switch without the wait for physical delivery. Although the virtual version has limited performance relative to the physical switch, it lets you quickly emulate the same features for the control plane of the physical switch, or both its control and data planes.", + "documentation_url": "http://www.juniper.net/techpubs/", + "images": [ + { + "download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", + "filename": "cosim_20180212.qcow2", + "filesize": 1911291904, + "md5sum": "0372e9c1b7df3608099186ab8cbbf2ad", + "version": "17.4R1" + }, + { + "download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", + "filename": "vqfx10k-pfe-20160609-2.vmdk", + "filesize": 584086528, + "md5sum": "faa6905fd8e935c6e97859191143e8c3", + "version": "15.1X53-D60" + } + ], + "maintainer": "none", + "maintainer_email": "developers@gns3.net", + "name": "Juniper vQFX PFE", + "port_name_format": "em{0}", + "product_name": "Juniper vQFX PFE", + "product_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "x86_64", + "console_type": "vnc", + "kvm": "require", + "options": "-nographic", + "ram": 2048 + }, + "registry_version": 3, + "status": "experimental", + "symbol": "juniper-vqfx.svg", + "usage": "\n\nUSAGE INSTRUCTIONS\n\nConnect the first interface (em0) to your admin VLAN. Connect the second interface (em1) directly to the second interface (em1) of the RE. The switch ports do not connect here, but on the RE", + "vendor_name": "Juniper", + "vendor_url": "https://www.juniper.net/us/en/", + "versions": [ + { + "images": { + "hda_disk_image": "cosim_20180212.qcow2" + }, + "name": "17.4R1" + }, + { + "images": { + "hda_disk_image": "vqfx10k-pfe-20160609-2.vmdk" + }, + "name": "15.1X53-D60" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Riverbed SteelHead delivers not only best-in-class optimization \u2013 but essential visibility and control as companies transition to the Hybrid WAN. SteelHead CX for Virtual is available as a virtual solution on most major hypervisors including VMware vSphere, Microsoft Hyper-V and KVM. It accelerates the performance of all applications including on-premises, cloud, and SaaS across the hybrid enterprise for organizations that want to deliver the best end user experience \u2013 while leveraging the scalability and cost benefits of virtualization.\n\nSteelHead CX for Virtual uniquely delivers the best application performance along with application, network and end user visibility, and simplified control management of users, applications and networks based on business requirements and decisions.", + "documentation_url": "https://support.riverbed.com/content/support/software/steelhead/cx-appliance.html", + "images": [ + { + "download_url": "http://www.riverbed.com/products/steelhead/Free-90-day-Evaluation-SteelHead-CX-Virtual-Edition.html", + "filename": "mgmt-9.2.0.img", + "filesize": 2555772928, + "md5sum": "ca20a76b2556c0cd313d0b0de528e94d", + "version": "9.2.0" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 198656, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "SteelHead CX 555V", + "product_name": "SteelHead CX 555V", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "You don't need to run the installer script when using GNS3 VM. Uncompress the downloaded archive using this command: tar xzSf \nDefault credentials: admin / password", + "vendor_name": "Riverbed Technology", + "vendor_url": "http://www.riverbed.com", + "versions": [ + { + "images": { + "hda_disk_image": "mgmt-9.2.0.img", + "hdb_disk_image": "empty100G.qcow2" + }, + "name": "9.2.0" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "FreeBSD is an advanced computer operating system used to power modern servers, desktops, and embedded platforms. A large community has continually developed it for more than thirty years. Its advanced networking, security, and storage features have made FreeBSD the platform of choice for many of the busiest web sites and most pervasive embedded networking and storage devices.", + "documentation_url": "https://www.freebsd.org/docs.html", + "images": [ + { + "compression": "xz", + "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/12.0-RELEASE/amd64/Latest/FreeBSD-12.0-RELEASE-amd64.qcow2.xz", + "download_url": "https://www.freebsd.org/where.html", + "filename": "FreeBSD-12.0-RELEASE-amd64.qcow2", + "filesize": 2644836352, + "md5sum": "4d2126ba79dad224628be6f25a908bd8", + "version": "12.0" + }, + { + "compression": "xz", + "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/11.2-RELEASE/amd64/Latest/FreeBSD-11.2-RELEASE-amd64.qcow2.xz", + "download_url": "https://www.freebsd.org/where.html", + "filename": "FreeBSD-11.2-RELEASE-amd64.qcow2", + "filesize": 1630076928, + "md5sum": "44d37e65be4bb4054f067911c84d074a", + "version": "11.2" + }, + { + "compression": "xz", + "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/11.1-RELEASE/amd64/Latest/FreeBSD-11.1-RELEASE-amd64.qcow2.xz", + "download_url": "https://www.freebsd.org/where.html", + "filename": "FreeBSD-11.1-RELEASE-amd64.qcow2", + "filesize": 1533345792, + "md5sum": "d78b2a7d05ec62f799e14ded4817ea69", + "version": "11.1" + }, + { + "compression": "xz", + "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/11.0-RELEASE/amd64/Latest/FreeBSD-11.0-RELEASE-amd64.qcow2.xz", + "download_url": "https://www.freebsd.org/where.html", + "filename": "FreeBSD-11.0-RELEASE-amd64.qcow2", + "filesize": 1384382464, + "md5sum": "1b04999198f492afd6dc4935b8c7cc22", + "version": "11.0" + }, + { + "compression": "xz", + "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/10.4-RELEASE/amd64/Latest/FreeBSD-10.4-RELEASE-amd64.qcow2.xz", + "download_url": "https://www.freebsd.org/where.html", + "filename": "FreeBSD-10.4-RELEASE-amd64.qcow2", + "filesize": 1013448704, + "md5sum": "ad498873733c57d1f6d890d587a11e3c", + "version": "10.4" + }, + { + "compression": "xz", + "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/10.3-RELEASE/amd64/Latest/FreeBSD-10.3-RELEASE-amd64.qcow2.xz", + "download_url": "https://www.freebsd.org/where.html", + "filename": "FreeBSD-10.3-RELEASE-amd64.qcow2", + "filesize": 974651392, + "md5sum": "1a00cebef520dfac8d2bda10ea16a951", + "version": "10.3" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "FreeBSD", + "port_name_format": "em{0}", + "product_name": "FreeBSD", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 256 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "User: root, not password is set.", + "vendor_name": "FreeBSD", + "vendor_url": "http://www.freebsd.org", + "versions": [ + { + "images": { + "hda_disk_image": "FreeBSD-12.0-RELEASE-amd64.qcow2" + }, + "name": "12.0" + }, + { + "images": { + "hda_disk_image": "FreeBSD-11.2-RELEASE-amd64.qcow2" + }, + "name": "11.2" + }, + { + "images": { + "hda_disk_image": "FreeBSD-11.1-RELEASE-amd64.qcow2" + }, + "name": "11.1" + }, + { + "images": { + "hda_disk_image": "FreeBSD-11.0-RELEASE-amd64.qcow2" + }, + "name": "11.0" + }, + { + "images": { + "hda_disk_image": "FreeBSD-10.4-RELEASE-amd64.qcow2" + }, + "name": "10.4" + }, + { + "images": { + "hda_disk_image": "FreeBSD-10.3-RELEASE-amd64.qcow2" + }, + "name": "10.3" + } + ] + }, + { + "builtin": true, + "category": "multilayer_switch", + "description": "NXOSv is a reference platform for an implementation of the Cisco Nexus operating system, based on the Nexus 7000-series platforms, running as a full virtual machine on a hypervisor. This includes NXAPI and MPLS LDP support.", + "first_port_name": "mgmt0", + "images": [ + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "titanium-final.7.3.0.D1.1.qcow2", + "filesize": 214368256, + "md5sum": "b4cd6edf15ab4c6bce53c3f6c1e3a742", + "version": "7.3.0" + }, + { + "download_url": "https://virl.mediuscorp.com/my-account/", + "filename": "titanium-d1.7.2.0.D1.1.vmdk", + "filesize": 361103360, + "md5sum": "0ee38c7d717840cb4ca822f4870671d0", + "version": "7.2.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco NX-OSv", + "port_name_format": "Ethernet2/{port1}", + "product_name": "NX-OSv", + "product_url": "http://virl.cisco.com/", + "qemu": { + "adapter_type": "e1000", + "adapters": 16, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "ram": 3072 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/multilayer_switch.svg", + "usage": "The default username/password is admin/admin. A default configuration is present.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "hda_disk_image": "titanium-final.7.3.0.D1.1.qcow2" + }, + "name": "7.3.0" + }, + { + "images": { + "hda_disk_image": "titanium-d1.7.2.0.D1.1.vmdk" + }, + "name": "7.2.0" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "Cisco 3660 Router", + "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", + "dynamips": { + "chassis": "3660", + "nvram": 256, + "platform": "c3600", + "ram": 192, + "startup_config": "ios_base_startup-config.txt" + }, + "images": [ + { + "filename": "c3660-a3jk9s-mz.124-15.T14.image", + "filesize": 90181268, + "md5sum": "daed99f508fd42dbaacf711e560643ed", + "version": "124-15.T14" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco 3660", + "product_name": "3660", + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/router.svg", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com", + "versions": [ + { + "idlepc": "0x6076e0b4", + "images": { + "image": "c3660-a3jk9s-mz.124-15.T14.image" + }, + "name": "124-15.T14" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "LEDE is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers). Unlike many other distributions for these routers, OpenWrt is built from the ground up to be a full-featured, easily modifiable operating system for your router. In practice, this means that you can have all the features you need with none of the bloat, powered by a Linux kernel that's more recent than most other distributions.", + "documentation_url": "http://wiki.openwrt.org/doc/", + "images": [ + { + "direct_download_url": "https://downloads.lede-project.org/releases/17.01.4/targets/x86/generic/lede-17.01.4-x86-generic-combined-squashfs.img", + "download_url": "https://downloads.lede-project.org/releases/17.01.4/targets/x86/generic/", + "filename": "lede-17.01.4-x86-generic-combined-squashfs.img", + "filesize": 19779546, + "md5sum": "ae5d8d3fcab109565fe337d28e51c4b4", + "version": "17.01.4" + }, + { + "direct_download_url": "https://downloads.lede-project.org/releases/17.01.3/targets/x86/generic/lede-17.01.3-x86-generic-combined-squashfs.img", + "download_url": "https://downloads.lede-project.org/releases/17.01.3/targets/x86/generic/", + "filename": "lede-17.01.3-x86-generic-combined-squashfs.img", + "filesize": 19775618, + "md5sum": "d315fc638160a9aec0966d58828bfccf", + "version": "17.01.3" + }, + { + "direct_download_url": "https://downloads.lede-project.org/releases/17.01.2/targets/x86/generic/lede-17.01.2-x86-generic-combined-squashfs.img", + "download_url": "https://downloads.lede-project.org/releases/17.01.2/targets/x86/generic/", + "filename": "lede-17.01.2-x86-generic-combined-squashfs.img", + "filesize": 19774794, + "md5sum": "a466e493ef12935dad5e0c622b1a7859", + "version": "17.01.2" + }, + { + "direct_download_url": "https://downloads.lede-project.org/releases/17.01.1/targets/x86/generic/lede-17.01.1-x86-generic-combined-squashfs.img", + "download_url": "https://downloads.lede-project.org/releases/17.01.1/targets/x86/generic/", + "filename": "lede-17.01.1-x86-generic-combined-squashfs.img", + "filesize": 19771166, + "md5sum": "b050e734c605a34a429389c752ae7c30", + "version": "17.01.1" + }, + { + "direct_download_url": "https://downloads.lede-project.org/releases/17.01.0/targets/x86/generic/lede-17.01.0-r3205-59508e3-x86-generic-combined-squashfs.img", + "download_url": "https://downloads.lede-project.org/releases/17.01.0/targets/x86/generic/", + "filename": "lede-17.01.0-r3205-59508e3-x86-generic-combined-squashfs.img", + "filesize": 19755118, + "md5sum": "3c5e068d50a377d4e26b548ab1ca7b1e", + "version": "17.01.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "LEDE", + "product_name": "LEDE", + "product_url": "https://lede-project.org/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 2, + "arch": "i386", + "console_type": "telnet", + "kvm": "allow", + "ram": 64 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "Ethernet0 is the LAN link, Ethernet1 the WAN link.", + "vendor_name": "LEDE Project", + "vendor_url": "https://lede-project.org/", + "versions": [ + { + "images": { + "hda_disk_image": "lede-17.01.4-x86-generic-combined-squashfs.img" + }, + "name": "lede 17.01.4" + }, + { + "images": { + "hda_disk_image": "lede-17.01.3-x86-generic-combined-squashfs.img" + }, + "name": "lede 17.01.3" + }, + { + "images": { + "hda_disk_image": "lede-17.01.2-x86-generic-combined-squashfs.img" + }, + "name": "lede 17.01.2" + }, + { + "images": { + "hda_disk_image": "lede-17.01.1-x86-generic-combined-squashfs.img" + }, + "name": "lede 17.01.1" + }, + { + "images": { + "hda_disk_image": "lede-17.01.0-r3205-59508e3-x86-generic-combined-squashfs.img" + }, + "name": "lede 17.01.0" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "The Virtual Wireless Controller can cost-effectively manage, secure, and optimize the performance of local and branch wireless networks. Ideal for small and medium-sized businesses, the Virtual Wireless Controller facilitates server consolidation and improves business continuity in the face of outages.", + "documentation_url": "http://www.cisco.com/c/en/us/products/wireless/wireless-lan-controller/index.html", + "first_port_name": "ServicePort", + "images": [ + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=7.3.101.0", + "filename": "Cisco-vWLC-AIR-CTVM-7-3-101-0-file1.iso", + "filesize": 157900800, + "md5sum": "6bf17dceaf46e57aab0fb0d43eb6ea06", + "version": "7.3.101.0" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=7.6.110.0", + "filename": "AIR-CTVM-7-6-110-0-file1.iso", + "filesize": 185561088, + "md5sum": "7acbd88120f008a25d849b72b7207e92", + "version": "7.6.110.0" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=8.1.120.0", + "filename": "AIR-CTVM-k9-8-1-120.0.iso", + "filesize": 302104576, + "md5sum": "477363f88f07f64499bb4ab80ffa9d2f", + "version": "8.1.120.0" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=8.2.141.0", + "filename": "MFG_CTVM_8_2_141_0.iso", + "filesize": 351156224, + "md5sum": "29483229ce7844df55a90564b077c958", + "version": "8.2.141.0" + }, + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=8.3.102.0", + "filename": "MFG_CTVM_8_3_102_0.iso", + "filesize": 365996032, + "md5sum": "7f6b7968b5bed04b5ecc119b6ba4e41c", + "version": "8.3.102.0" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty8G.qcow2", + "filesize": 197120, + "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco vWLC", + "port_name_format": "Management{port1}", + "product_name": "Virtual Wireless LAN Controller", + "product_url": "http://www.cisco.com/c/en/us/support/wireless/virtual-wireless-controller/tsd-products-support-series-home.html", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "vnc", + "hda_disk_interface": "ide", + "kvm": "require", + "options": "", + "ram": 2048 + }, + "registry_version": 3, + "status": "experimental", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Starting vWLC will start an installation of vWLC onto a blank 8GB Drive.", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "cdrom_image": "AIR-CTVM-k9-8-1-120.0.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "8.1.120.0" + }, + { + "images": { + "cdrom_image": "MFG_CTVM_8_2_141_0.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "8.2.141.0" + }, + { + "images": { + "cdrom_image": "MFG_CTVM_8_3_102_0.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "8.3.102.0" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "This appliance provides RADIUS and TACACS+ services with preconfigured users and groups.", + "docker": { + "adapters": 1, + "console_type": "telnet", + "image": "adosztal/aaa:latest" + }, + "maintainer": "Andras Dosztal", + "maintainer_email": "developers@gns3.net", + "name": "AAA", + "product_name": "AAA", + "registry_version": 3, + "status": "stable", + "symbol": "linux_guest.svg", + "usage": "RADIUS users:\n- alice\n- bob\n\nTACACS+ users:\n- gns3 (role: admin)\n- readonly\n\nAll users, as well as the RADIUS/TACACS+ clients have the password 'gns3' set.", + "vendor_name": "Ubuntu", + "vendor_url": "https://www.ubuntu.com/" + }, + { + "builtin": true, + "category": "guest", + "description": "This container provides the popular tools used for network automation: Netmiko, NAPALM, Pyntc, and Ansible.", + "docker": { + "adapters": 1, + "console_type": "telnet", + "image": "adosztal/network_automation:latest" + }, + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Network Automation", + "product_name": "Network Automation", + "registry_version": 3, + "status": "stable", + "symbol": "linux_guest.svg", + "vendor_name": "GNS3", + "vendor_url": "http://www.gns3.com" + }, + { + "builtin": true, + "category": "router", + "description": "OpenWrt is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers). Unlike many other distributions for these routers, OpenWrt is built from the ground up to be a full-featured, easily modifiable operating system for your router. In practice, this means that you can have all the features you need with none of the bloat, powered by a Linux kernel that's more recent than most other distributions.", + "documentation_url": "http://wiki.openwrt.org/doc/", + "images": [ + { + "compression": "gzip", + "direct_download_url": "https://downloads.openwrt.org/releases/18.06.2/targets/x86/64/openwrt-18.06.2-x86-64-combined-ext4.img.gz", + "download_url": "https://downloads.openwrt.org/releases/18.06.2/targets/x86/64/", + "filename": "openwrt-18.06.2-x86-64-combined-ext4.img", + "filesize": 285736960, + "md5sum": "d112cd432bf51e2ddadbf9513f272fd9", + "version": "18.06.2" + }, + { + "compression": "gzip", + "direct_download_url": "https://downloads.openwrt.org/releases/18.06.1/targets/x86/64/openwrt-18.06.1-x86-64-combined-ext4.img.gz", + "download_url": "https://downloads.openwrt.org/releases/18.06.1/targets/x86/64/", + "filename": "openwrt-18.06.1-x86-64-combined-ext4.img", + "filesize": 285736960, + "md5sum": "3e2da47c5c2496b6df364a60ded8f40a", + "version": "18.06.1" + }, + { + "compression": "gzip", + "direct_download_url": "https://downloads.openwrt.org/releases/17.01.6/targets/x86/64/lede-17.01.6-x86-64-combined-ext4.img.gz", + "download_url": "https://downloads.openwrt.org/releases/17.01.6/targets/x86/64/", + "filename": "lede-17.01.6-x86-64-combined-ext4.img", + "filesize": 285736960, + "md5sum": "015c0d5038ddd469fbdabce7eb5265dc", + "version": "17.01.6" + }, + { + "compression": "gzip", + "direct_download_url": "http://archive.openwrt.org/chaos_calmer/15.05.1/x86/64/openwrt-15.05.1-x86-64-combined-ext4.img.gz", + "download_url": "http://archive.openwrt.org/chaos_calmer/15.05.1/x86/64/", + "filename": "openwrt-15.05.1-x86-64-combined-ext4.img", + "filesize": 55050240, + "md5sum": "307d8cdb11faeb1b5e27fe55078bd152", + "version": "15.05.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "OpenWrt", + "product_name": "OpenWrt", + "product_url": "http://openwrt.org", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "allow", + "ram": 64 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "Ethernet0 is the LAN link, Ethernet1 the WAN link, Ethernet2 and Ethernet3 are optional links.", + "vendor_name": "OpenWrt", + "vendor_url": "http://openwrt.org", + "versions": [ + { + "images": { + "hda_disk_image": "openwrt-18.06.2-x86-64-combined-ext4.img" + }, + "name": "openwrt 18.06.2" + }, + { + "images": { + "hda_disk_image": "openwrt-18.06.1-x86-64-combined-ext4.img" + }, + "name": "openwrt 18.06.1" + }, + { + "images": { + "hda_disk_image": "lede-17.01.6-x86-64-combined-ext4.img" + }, + "name": "openwrt/lede 17.01.6" + }, + { + "images": { + "hda_disk_image": "openwrt-15.05.1-x86-64-combined-ext4.img" + }, + "name": "openwrt 15.05.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Cisco Data Center Network Manager (DCNM) 10 unifies and automates Cisco Nexus and Cisco MDS 9000 Family multitenant infrastructure for data center management across Cisco Nexus 5000, 6000, 7000, and 9000 Series Switches in NX\u2011OS mode using Cisco NX-OS Software as well as across Cisco MDS 9100 and 9300 Series Multilayer Fabric Switches, 9200 Series Multiservice Switches, and 9500 and 9700 Series Multilayer Directors. Data Center Network Manager 10 lets you manage very large numbers of devices while providing ready-to-use management and automation capabilities plus Virtual Extensible LAN (VXLAN) overlay visibility into Cisco Nexus LAN fabrics.", + "documentation_url": "http://www.cisco.com/c/en/us/support/cloud-systems-management/data-center-network-manager-10/model.html", + "images": [ + { + "download_url": "https://software.cisco.com/download/release.html?mdfid=281722751&softwareid=282088134&release=10.1(1)&relind=AVAILABLE&rellifecycle=&reltype=latest", + "filename": "dcnm-va.10.1.1.iso", + "filesize": 2927532032, + "md5sum": "4eca14506decaf166251c64e67adb110", + "version": "10.1.1" + }, + { + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty100G.qcow2", + "filesize": 198656, + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Cisco DCNM", + "port_name_format": "eth{0}", + "product_name": "DCNM", + "product_url": "http://www.cisco.com/c/en/us/products/cloud-systems-management/prime-data-center-network-manager/index.html", + "qemu": { + "adapter_type": "e1000", + "adapters": 2, + "arch": "x86_64", + "console_type": "vnc", + "hda_disk_interface": "ide", + "kvm": "require", + "options": "-smp 2", + "ram": 8192 + }, + "registry_version": 3, + "status": "stable", + "symbol": "mgmt_station.svg", + "usage": "Default credentials: root / cisco123", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "versions": [ + { + "images": { + "cdrom_image": "dcnm-va.10.1.1.iso", + "hda_disk_image": "empty100G.qcow2" + }, + "name": "10.1.1" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "With proven ultra-high performance and scalability, the Brocade vRouter is the networking industry leader in software innovation. The Brocade vRouter has set a the benchmark for all software-based routers, while offering easy scalability, a broad set of capabilities, and the peace of mind that comes with rock solid reliability.", + "documentation_url": "http://www.brocade.com/en/products-services/software-networking/network-functions-virtualization/vrouter.html", + "images": [ + { + "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", + "filename": "vyatta-vrouter-17.1.1_B_amd64.iso", + "filesize": 347078656, + "md5sum": "914c9ca9d51a33fc54f718020f862df2", + "version": "17.1.1" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", + "filename": "vyatta-vrouter-17.1.0_B_amd64.iso", + "filesize": 346030080, + "md5sum": "ff524e06fda6d982b9b66f25940fe63b", + "version": "17.1.0" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", + "filename": "vyatta-vrouter-5.2R2_B_amd64.iso", + "filesize": 344981504, + "md5sum": "6b7dcc152a18187ad151483c139fb82c", + "version": "5.2R2" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", + "filename": "vyatta-vrouter-5.1R1_B_amd64.iso", + "filesize": 344981504, + "md5sum": "e374b8bae9eecd52ee841f5e262b3a16", + "version": "5.1R1" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", + "filename": "livecd-VR5600_5.0R2_B_amd64.iso", + "filesize": 340787200, + "md5sum": "ce47dba6f89ef1175ef8850110521104", + "version": "5.0R2" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", + "filename": "livecd-VR5600_4.2R1_B_amd64.iso", + "filesize": 326107136, + "md5sum": "5e3023c64dc409ae01d5bcb1b6732593", + "version": "4.2R1" + }, + { + "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", + "filename": "vyatta-livecd_3.5R3T60_amd64.iso", + "filesize": 288358400, + "md5sum": "90360273f818a3dba83fa93ef6da938b", + "version": "3.5R3" + }, + { + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "filename": "empty8G.qcow2", + "filesize": 197120, + "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", + "version": "1.0" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "vRouter", + "port_name_format": "eth{0}", + "product_name": "vRouter", + "product_url": "http://www.brocade.com/en/products-services/software-networking/network-functions-virtualization/vrouter.html", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 8, + "arch": "x86_64", + "boot_priority": "cd", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "options": "-smp 4 -cpu host", + "ram": 4096 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/router.svg", + "usage": "60 days evaluation. The Brocade vRouter must be on-line and have public connectivity in order to communicate with the Brocade licensing server for automated license key generation. Please note that the evaluation software will only run for 24 hours after installation without the activation code being entered into the system. You must enter your activation code in order to retrieve your licensing key after you install the Brocade vRouter software. Default credentials: vyatta / vyatta", + "vendor_name": "Brocade", + "vendor_url": "http://www.brocade.com/", + "versions": [ + { + "images": { + "cdrom_image": "vyatta-vrouter-17.1.1_B_amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "17.1.1" + }, + { + "images": { + "cdrom_image": "vyatta-vrouter-17.1.0_B_amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "17.1.0" + }, + { + "images": { + "cdrom_image": "vyatta-vrouter-5.2R2_B_amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "5.2R2" + }, + { + "images": { + "cdrom_image": "vyatta-vrouter-5.1R1_B_amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "5.1R1" + }, + { + "images": { + "cdrom_image": "livecd-VR5600_5.0R2_B_amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "5.0R2" + }, + { + "images": { + "cdrom_image": "livecd-VR5600_4.2R1_B_amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "4.2R1" + }, + { + "images": { + "cdrom_image": "vyatta-livecd_3.5R3T60_amd64.iso", + "hda_disk_image": "empty8G.qcow2" + }, + "name": "3.5R3" + } + ] + }, + { + "builtin": true, + "category": "router", + "description": "The vMX is a full-featured, carrier-grade virtual MX Series 3D Universal Edge Router that extends 15+ years of Juniper Networks edge routing expertise to the virtual realm. This appliance is for the Virtual Forwarding Plane (vFP) VM and is meant to be paired with the Virtual Control Plane (vCP) VM.", + "documentation_url": "http://www.juniper.net/techpubs/", + "first_port_name": "Eth0", + "images": [ + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-20171213.img", + "filesize": 2313158656, + "md5sum": "848a6256da7296e8fede368a258c68e4", + "version": "17.4R1.16-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-20180126.img", + "filesize": 2313158656, + "md5sum": "02d6b719053485c52a511fe6f5a598e3", + "version": "17.3R2.10-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vfpc_17.1R1.8-disk1.vmdk", + "filesize": 102820352, + "md5sum": "169dd487b8547d58b12b2918a5667360", + "version": "17.1R1.8-ESXi" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-20170216.img", + "filesize": 2313158656, + "md5sum": "e838b8dd116a8b388d8dfd99575e7e98", + "version": "17.1R1.8-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vfpc_16.2R1.6-disk1.vmdk", + "filesize": 102430208, + "md5sum": "abb15d485cd195b9a693a2f3f091564a", + "version": "16.2R1.6-ESXi" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-20161025.img", + "filesize": 2313158656, + "md5sum": "3105a5af7d859fc24b686e71113413a9", + "version": "16.2R1.6-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vfpc_16.1R4.7-disk1.vmdk", + "filesize": 102431232, + "md5sum": "c381a23038dc5d4f939b7b5c3d074ce2", + "version": "16.1R4.7-ESXi" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-20170211.img", + "filesize": 2313158656, + "md5sum": "cdec45ecca1cd9bfefe318b066bd500b", + "version": "16.1R4.7-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vfpc_16.1R3.10-disk1.vmdk", + "filesize": 102437376, + "md5sum": "03b9d23c0223d8078fa3830c23fcf144", + "version": "16.1R3.10-ESXi" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-20161019.img", + "filesize": 2313158656, + "md5sum": "0fbba19da959c3e76b438128b28726f7", + "version": "16.1R3.10-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vfpc_16.1R2.11-disk1.vmdk", + "filesize": 102431232, + "md5sum": "1a90e5dc0c02c8336b9084cbdf17f635", + "version": "16.1R2.11-ESXi" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-20160902.img", + "filesize": 2313158656, + "md5sum": "09ee97c6c18b392b1b72f5e3e4743c2d", + "version": "16.1R2.11-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vfpc_16.1R1.7-disk1.vmdk", + "filesize": 63884800, + "md5sum": "8475d8b065768f585659a49c50f1d7e1", + "version": "16.1R1.7-ESXi" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-20160617.img", + "filesize": 2313158656, + "md5sum": "5ccf252002184a21413cad23fd239c3f", + "version": "16.1R1.7-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-15.1F6.9.img", + "filesize": 2313158656, + "md5sum": "7328501fdfa9b160955bc136664f1e86", + "version": "15.1F6.9-KVM" + }, + { + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "filename": "vFPC-20151203.img", + "filesize": 2313158656, + "md5sum": "b3faa91b4d20836a9a6dd6bad2629dd1", + "version": "15.1F4.15" + } + ], + "maintainer": "none", + "maintainer_email": "developers@gns3.net", + "name": "Juniper vMX vFP", + "port_name_format": "Eth{port1}", + "product_name": "Juniper vMX vFP", + "product_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 12, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require", + "options": "-nographic -enable-kvm -smp cpus=3", + "ram": 4096 + }, + "registry_version": 3, + "status": "experimental", + "symbol": "juniper-vmx.svg", + "usage": "Initial username is root, password is root.\n", + "vendor_name": "Juniper", + "vendor_url": "https://www.juniper.net/us/en/", + "versions": [ + { + "images": { + "hda_disk_image": "vFPC-20171213.img" + }, + "name": "17.4R1.16-KVM" + }, + { + "images": { + "hda_disk_image": "vFPC-20180126.img" + }, + "name": "17.3R2.10-KVM" + }, + { + "images": { + "hda_disk_image": "vfpc_17.1R1.8-disk1.vmdk" + }, + "name": "17.1R1.8-ESXi" + }, + { + "images": { + "hda_disk_image": "vFPC-20170216.img" + }, + "name": "17.1R1.8-KVM" + }, + { + "images": { + "hda_disk_image": "vfpc_16.2R1.6-disk1.vmdk" + }, + "name": "16.2R1.6-ESXi" + }, + { + "images": { + "hda_disk_image": "vFPC-20161025.img" + }, + "name": "16.2R1.6-KVM" + }, + { + "images": { + "hda_disk_image": "vfpc_16.1R4.7-disk1.vmdk" + }, + "name": "16.1R4.7-ESXi" + }, + { + "images": { + "hda_disk_image": "vFPC-20170211.img" + }, + "name": "16.1R4.7-KVM" + }, + { + "images": { + "hda_disk_image": "vfpc_16.1R3.10-disk1.vmdk" + }, + "name": "16.1R3.10-ESXi" + }, + { + "images": { + "hda_disk_image": "vFPC-20161019.img" + }, + "name": "16.1R3.10-KVM" + }, + { + "images": { + "hda_disk_image": "vfpc_16.1R2.11-disk1.vmdk" + }, + "name": "16.1R2.11-ESXi" + }, + { + "images": { + "hda_disk_image": "vFPC-20160902.img" + }, + "name": "16.1R2.11-KVM" + }, + { + "images": { + "hda_disk_image": "vfpc_16.1R1.7-disk1.vmdk" + }, + "name": "16.1R1.7-ESXi" + }, + { + "images": { + "hda_disk_image": "vFPC-20160617.img" + }, + "name": "16.1R1.7-KVM" + }, + { + "images": { + "hda_disk_image": "vFPC-15.1F6.9.img" + }, + "name": "15.1F6.9-KVM" + }, + { + "images": { + "hda_disk_image": "vFPC-20151203.img" + }, + "name": "15.1F4.15" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "Kerio Connect makes email, calendars, contacts and task management easy and affordable. With Kerio Connect, you have immediate, secure access to your communications anytime, anywhere, on any device \u2014 without complexity or expensive overhead.", + "documentation_url": "http://kb.kerio.com/product/kerio-connect/", + "images": [ + { + "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.7-4225/kerio-connect-appliance-9.2.7-4225-p3-vmware-amd64-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-connect", + "filename": "kerio-connect-appliance-9.2.7-4225-p3-vmware-amd64-disk1.vmdk", + "filesize": 914165248, + "md5sum": "12950c8244300f1d86c85c109f0b3413", + "version": "9.2.7p3" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.6-3851/kerio-connect-appliance-9.2.6-3851-p1-vmware-amd64-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-connect", + "filename": "kerio-connect-appliance-9.2.6-3851-p1-vmware-amd64-disk1.vmdk", + "filesize": 625852004, + "md5sum": "c6ed064114c6fd70608b7951b707528c", + "version": "9.2.6p1" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.5-3336/kerio-connect-appliance-9.2.5-3336-p3-vmware-amd64-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-connect", + "filename": "kerio-connect-appliance-9.2.5-3336-p3-vmware-amd64-disk1.vmdk", + "filesize": 824496128, + "md5sum": "f2a202f29e71dc6e8bebce4c05a9e44d", + "version": "9.2.5p3" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.4-3252/kerio-connect-appliance-9.2.4-3252-vmware-amd64-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-connect", + "filename": "kerio-connect-appliance-9.2.4-3252-vmware-amd64-disk1.vmdk", + "filesize": 720217088, + "md5sum": "c585587a8de878d3940e42cf389b0f06", + "version": "9.2.4" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.3-2929/kerio-connect-appliance-9.2.3-2929-vmware-amd64-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-connect", + "filename": "kerio-connect-appliance-9.2.3-2929-vmware-amd64-disk1.vmdk", + "filesize": 676196352, + "md5sum": "29ecf7ac72b32e576e1556af9a741ab2", + "version": "9.2.3" + }, + { + "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.2-2831/kerio-connect-appliance-9.2.2-2831-p1-vmware-amd64-disk1.vmdk", + "download_url": "http://www.kerio.com/support/kerio-connect", + "filename": "kerio-connect-appliance-9.2.2-2831-p1-vmware-amd64-disk1.vmdk", + "filesize": 673714688, + "md5sum": "586ab9830602746e6a3438afaa6ee9b8", + "version": "9.2.2p1" + }, + { + "compression": "zip", + "direct_download_url": "http://download.kerio.com/dwn/kerio-connect-appliance-vmware-amd64.zip", + "download_url": "http://www.kerio.com/support/kerio-connect", + "filename": "kerio-connect-appliance-9.2.1-vmware-disk1.vmdk", + "filesize": 1851523072, + "md5sum": "f1d60094c237f55e6737b0da9b5912ce", + "version": "9.2.1" + } + ], + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "name": "Kerio Connect", + "port_name_format": "eth{0}", + "product_name": "Kerio Connect", + "product_url": "http://www.kerio.com/products/kerio-connect", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "arch": "x86_64", + "boot_priority": "c", + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "require", + "ram": 2048 + }, + "registry_version": 3, + "status": "stable", + "symbol": ":/symbols/classic/qemu_guest.svg", + "usage": "Default ucredentials: root / kerio", + "vendor_name": "Kerio Technologies Inc.", + "vendor_url": "http://www.kerio.com", + "versions": [ + { + "images": { + "hda_disk_image": "kerio-connect-appliance-9.2.7-4225-p3-vmware-amd64-disk1.vmdk" + }, + "name": "9.2.7p3" + }, + { + "images": { + "hda_disk_image": "kerio-connect-appliance-9.2.6-3851-p1-vmware-amd64-disk1.vmdk" + }, + "name": "9.2.6p1" + }, + { + "images": { + "hda_disk_image": "kerio-connect-appliance-9.2.5-3336-p3-vmware-amd64-disk1.vmdk" + }, + "name": "9.2.5p3" + }, + { + "images": { + "hda_disk_image": "kerio-connect-appliance-9.2.4-3252-vmware-amd64-disk1.vmdk" + }, + "name": "9.2.4" + }, + { + "images": { + "hda_disk_image": "kerio-connect-appliance-9.2.3-2929-vmware-amd64-disk1.vmdk" + }, + "name": "9.2.3" + }, + { + "images": { + "hda_disk_image": "kerio-connect-appliance-9.2.2-2831-p1-vmware-amd64-disk1.vmdk" + }, + "name": "9.2.2p1" + }, + { + "images": { + "hda_disk_image": "kerio-connect-appliance-9.2.1-vmware-disk1.vmdk" + }, + "name": "9.2.1" + } + ] + }, + { + "builtin": true, + "category": "guest", + "description": "This appliance contains server side software for secondary management of network devices:\n- www (nginx) \n- ftp (vsftpd)\n- tftp (tftpd)\n- syslog (rsyslog)\n- dhcp (isc-dhcpd)\n- snmp server (snmpd + snmptrapd)", + "docker": { + "adapters": 1, + "console_type": "telnet", + "image": "adosztal/net_toolbox:latest" + }, + "maintainer": "Andras Dosztal", + "maintainer_email": "developers@gns3.net", + "name": "Toolbox", + "product_name": "Networkers' toolbox", + "registry_version": 3, + "status": "stable", + "symbol": "linux_guest.svg", + "usage": "Root password: gns3", + "vendor_name": "Ubuntu", + "vendor_url": "https://www.ubuntu.com/" } ] diff --git a/docs/api/examples/controller_get_appliancestemplates.txt b/docs/api/examples/controller_get_appliancestemplates.txt deleted file mode 100644 index 21fc2b2c..00000000 --- a/docs/api/examples/controller_get_appliancestemplates.txt +++ /dev/null @@ -1,10595 +0,0 @@ -curl -i -X GET 'http://localhost:3080/v2/appliances/templates' - -GET /v2/appliances/templates HTTP/1.1 - - - -HTTP/1.1 200 -Connection: close -Content-Length: 470863 -Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:12 GMT -Server: Python/3.6 GNS3/2.1.2dev1 -X-Route: /v2/appliances/templates - -[ - { - "builtin": true, - "category": "router", - "description": "vThunder, part of A10 Networks' award-winning A10 Thunder and AX Series Application Delivery Controller (ADC) family, is designed to meet the growing needs of organizations that require a flexible and easy-to-deploy application delivery and server load balancer solution running within a virtualized infrastructure.", - "documentation_url": "https://www.a10networks.com/support", - "first_port_name": "mgmt", - "images": [ - { - "download_url": "https://www.a10networks.com/vthunder-embed", - "filename": "vThunder_410_P9.qcow2", - "filesize": 6311706624, - "md5sum": "6ef0f69ba7a099a7f43b5815c2abc691", - "version": "4.1.0.P9" - }, - { - "download_url": "https://www.a10networks.com/vthunder-embed", - "filename": "vThunder_410_P3.qcow2", - "filesize": 6098780160, - "md5sum": "daacefa4e0eb1cad9b253926624be4b9", - "version": "4.1.0.P3" - }, - { - "download_url": "https://www.a10networks.com/vthunder-embed", - "filename": "vth401.GA.12G_Disk.qcow2", - "filesize": 4768464896, - "md5sum": "311806ad414403359216da6119ddb823", - "version": "4.0.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "A10 vThunder", - "port_name_format": "ethernet {port1}", - "product_name": "A10 vThunder", - "product_url": "https://www.a10networks.com/products/thunder-series-appliances/vthunder-virtualized-application_delivery_controller/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 4096 - }, - "registry_version": 3, - "status": "stable", - "symbol": "loadbalancer.svg", - "usage": "Default credentials:\n- CLI: admin / a10.\n- Enable mode: \n\nDefault management IP: 172.31.31.31/24", - "vendor_name": "A10", - "vendor_url": "https://www.a10networks.com/", - "versions": [ - { - "images": { - "hda_disk_image": "vThunder_410_P9.qcow2" - }, - "name": "4.1.0.P9" - }, - { - "images": { - "hda_disk_image": "vThunder_410_P3.qcow2" - }, - "name": "4.1.0.P3" - }, - { - "images": { - "hda_disk_image": "vth401.GA.12G_Disk.qcow2" - }, - "name": "4.0.1" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "The Alcatel-Lucent 7750 Service Router (SR) portfolio is a suite of multiservice edge routing platforms that deliver high performance, service richness, and creates exceptional value for networking in the cloud era. It is designed for the concurrent delivery of advanced residential, business and wireless broadband IP services, and provides cloud, data center and branch office connectivity for enterprise networking on a common IP edge routing platform.", - "documentation_url": "https://www.alcatel-lucent.com/support", - "first_port_name": "A/1", - "images": [ - { - "compression": "zip", - "download_url": "https://www.alcatel-lucent.com/support", - "filename": "TiMOS-SR-13.0.R4-vm.qcow2", - "filesize": 368508928, - "md5sum": "d7a3609e506acdcb55f6db5328dba8ed", - "version": "13.0.R4" - }, - { - "compression": "zip", - "download_url": "https://www.alcatel-lucent.com/support", - "filename": "TiMOS-SR-12.0.R6-vm.qcow2", - "filesize": 221511680, - "md5sum": "7d84d97a5664af2e3546bfa832fc1848", - "version": "12.0.R6" - }, - { - "compression": "zip", - "download_url": "https://www.alcatel-lucent.com/support", - "filename": "TiMOS-SR-12.0.R18.qcow2", - "filesize": 223870976, - "md5sum": "d0bba5feaaf09fd02185f25898a6afc7", - "version": "12.0.R18" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Alcatel 7750", - "port_name_format": "1/1/{port1}", - "product_name": "Alcatel 7750", - "product_url": "https://www.alcatel-lucent.com/products/7750-service-router", - "qemu": { - "adapter_type": "e1000", - "adapters": 6, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "options": "", - "ram": 2048 - }, - "registry_version": 3, - "status": "experimental", - "usage": "Login is admin and password is admin", - "vendor_name": "Alcatel", - "vendor_url": "https://www.alcatel-lucent.com/", - "versions": [ - { - "images": { - "hda_disk_image": "TiMOS-SR-13.0.R4-vm.qcow2" - }, - "name": "13.0.R4" - }, - { - "images": { - "hda_disk_image": "TiMOS-SR-12.0.R6-vm.qcow2" - }, - "name": "12.0.R6" - }, - { - "images": { - "hda_disk_image": "TiMOS-SR-12.0.R18.qcow2" - }, - "name": "12.0.R18" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox.", - "docker": { - "adapters": 1, - "console_type": "telnet", - "image": "alpine" - }, - "documentation_url": "http://wiki.alpinelinux.org", - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Alpine Linux", - "product_name": "Alpine Linux", - "registry_version": 3, - "status": "stable", - "symbol": "linux_guest.svg", - "vendor_name": "Alpine Linux Development Team", - "vendor_url": "http://alpinelinux.org" - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "Arista EOS\u00ae is the core of Arista cloud networking solutions for next-generation data centers and cloud networks. Cloud architectures built with Arista EOS scale to tens of thousands of compute and storage nodes with management and provisioning capabilities that work at scale. Through its programmability, EOS enables a set of software applications that deliver workflow automation, high availability, unprecedented network visibility and analytics and rapid integration with a wide range of third-party applications for virtualization, management, automation and orchestration services.\n\nArista Extensible Operating System (EOS) is a fully programmable and highly modular, Linux-based network operation system, using familiar industry standard CLI and runs a single binary software image across the Arista switching family. Architected for resiliency and programmability, EOS has a unique multi-process state sharing architecture that separates state information and packet forwarding from protocol processing and application logic.", - "documentation_url": "https://www.arista.com/assets/data/docs/Manuals/EOS-4.17.2F-Manual.pdf", - "first_port_name": "Management1", - "images": [ - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "vEOS-lab-4.20.1F.vmdk", - "filesize": 662044672, - "md5sum": "aadb6f3dbff28317f68cb4c4502d0db8", - "version": "4.20.1F" - }, - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "vEOS-lab-4.18.5M.vmdk", - "filesize": 623116288, - "md5sum": "b1ee6268dbaf2b2276fd7a5286c7ce2b", - "version": "4.18.5M" - }, - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "vEOS-lab-4.18.1F.vmdk", - "filesize": 620625920, - "md5sum": "9648c63185f3b793b47528a858ca4364", - "version": "4.18.1F" - }, - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "vEOS-lab-4.17.2F.vmdk", - "filesize": 609615872, - "md5sum": "3b4845edfa77cf9aaeb9c0a005d3e277", - "version": "4.17.2F" - }, - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "vEOS-lab-4.16.6M.vmdk", - "filesize": 519962624, - "md5sum": "b3f7b7cee17f2e66bb38b453a4939fef", - "version": "4.16.6M" - }, - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "vEOS-lab-4.15.5M.vmdk", - "filesize": 516030464, - "md5sum": "cd74bb69c7ee905ac3d33c4d109f3ab7", - "version": "4.15.5M" - }, - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "vEOS-lab-4.14.14M.vmdk", - "filesize": 422641664, - "md5sum": "d81ba0522f4d7838d96f7985e41cdc47", - "version": "4.14.14M" - }, - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "vEOS-lab-4.13.16M.vmdk", - "filesize": 404684800, - "md5sum": "5763b2c043830c341c8b1009f4ea9a49", - "version": "4.13.16M" - }, - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "vEOS-lab-4.13.8M.vmdk", - "filesize": 409010176, - "md5sum": "a47145b9e6e7a24171c0850f8755535e", - "version": "4.13.8M" - }, - { - "download_url": "https://www.arista.com/en/support/software-download", - "filename": "Aboot-veos-serial-8.0.0.iso", - "filesize": 5242880, - "md5sum": "488ad1c435d18c69bb8d69c7806457c9", - "version": "8.0.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Arista vEOS", - "port_name_format": "Ethernet{port1}", - "product_name": "vEOS", - "product_url": "https://eos.arista.com/", - "qemu": { - "adapter_type": "e1000", - "adapters": 13, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "experimental", - "symbol": ":/symbols/multilayer_switch.svg", - "usage": "The login is admin, with no password by default", - "vendor_name": "Arista", - "vendor_url": "http://www.arista.com/", - "versions": [ - { - "images": { - "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", - "hdb_disk_image": "vEOS-lab-4.20.1F.vmdk" - }, - "name": "4.20.1F" - }, - { - "images": { - "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", - "hdb_disk_image": "vEOS-lab-4.18.5M.vmdk" - }, - "name": "4.18.5M" - }, - { - "images": { - "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", - "hdb_disk_image": "vEOS-lab-4.18.1F.vmdk" - }, - "name": "4.18.1F" - }, - { - "images": { - "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", - "hdb_disk_image": "vEOS-lab-4.17.2F.vmdk" - }, - "name": "4.17.2F" - }, - { - "images": { - "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", - "hdb_disk_image": "vEOS-lab-4.16.6M.vmdk" - }, - "name": "4.16.6M" - }, - { - "images": { - "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", - "hdb_disk_image": "vEOS-lab-4.15.5M.vmdk" - }, - "name": "4.15.5M" - }, - { - "images": { - "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", - "hdb_disk_image": "vEOS-lab-4.14.14M.vmdk" - }, - "name": "4.14.14M" - }, - { - "images": { - "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", - "hdb_disk_image": "vEOS-lab-4.13.16M.vmdk" - }, - "name": "4.13.16M" - }, - { - "images": { - "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", - "hdb_disk_image": "vEOS-lab-4.13.8M.vmdk" - }, - "name": "4.13.8M" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "AsteriskNOW makes it easy to create custom telephony solutions by automatically installing the 'plumbing'. It's a complete Linux distribution with Asterisk, the DAHDI driver framework, and, the FreePBX administrative GUI. Much of the complexity of Asterisk and Linux is handled by the installer, the yum package management utility and the administrative GUI. With AsteriskNOW, application developers and integrators can concentrate on building solutions, not maintaining the plumbing.", - "documentation_url": "https://wiki.asterisk.org/wiki/display/AST/Installing+AsteriskNOW", - "images": [ - { - "direct_download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/AsteriskNow-1013-current-64.iso", - "download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/", - "filename": "AsteriskNow-1013-current-64.iso", - "filesize": 1343909888, - "md5sum": "1badc6d68b59b57406e1b9ae69acf2e2", - "version": "10.13" - }, - { - "direct_download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/AsteriskNOW-612-current-64.iso", - "download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/", - "filename": "AsteriskNOW-612-current-64.iso", - "filesize": 1135714304, - "md5sum": "cc31e6d9b88d49e8eb182f1e2fb85479", - "version": "6.12" - }, - { - "direct_download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/AsteriskNOW-5211-current-64.iso", - "download_url": "http://downloads.asterisk.org/pub/telephony/asterisk-now/", - "filename": "AsteriskNOW-5211-current-64.iso", - "filesize": 1124741120, - "md5sum": "aef2b0fffd637b9c666e8ce904bbd714", - "version": "5.211" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "AsteriskNOW", - "port_name_format": "eth{0}", - "product_name": "AsteriskNOW", - "product_url": "http://www.asterisk.org/downloads/asterisknow", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 1, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "allow", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "usage": "Select 'No RAID' option when installing the appliance using the VNC console. Installing the freepbx package takes a lot of time (15+ minutes).", - "vendor_name": "Digium", - "vendor_url": "http://www.asterisk.org/", - "versions": [ - { - "images": { - "cdrom_image": "AsteriskNow-1013-current-64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "10.13" - }, - { - "images": { - "cdrom_image": "AsteriskNOW-612-current-64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "6.12" - }, - { - "images": { - "cdrom_image": "AsteriskNOW-5211-current-64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "5.211" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Big Cloud Fabric\u2122 is the industry\u2019s first data center fabric built using whitebox or britebox switches and SDN controller technology. Embracing hyperscale data center design principles, Big Cloud Fabric solution enables rapid innovation, ease of provisioning and management, while reducing overall costs, making it ideal for current and next generation data centers. Big Cloud Fabric is designed from the ground up to satisfy the requirements of physical, virtual, containerized, or a combination of such workloads. Some of the typical OpenStack or VMware data center workloads include NFV, High Performance Computing, Big Data and Software Defined Storage deployments.", - "documentation_url": "http://www.bigswitch.com/support", - "images": [ - { - "download_url": "http://www.bigswitch.com/community-edition", - "filename": "BCF-Controller-BCF-CE-3.5.0-2016-01-22.qcow2", - "filesize": 2860253184, - "md5sum": "d1c2ecf0db8101f6b6d311470697545a", - "version": "3.5.0-2016-01-22" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Big Cloud Fabric", - "product_name": "Big Cloud Fabric", - "product_url": "http://www.bigswitch.com/sdn-products/big-cloud-fabrictm", - "qemu": { - "adapter_type": "e1000", - "adapters": 8, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "ram": 256 - }, - "registry_version": 3, - "status": "experimental", - "usage": "Login is admin", - "vendor_name": "Big Switch Networks", - "vendor_url": "http://www.bigswitch.com/", - "versions": [ - { - "images": { - "hda_disk_image": "BCF-Controller-BCF-CE-3.5.0-2016-01-22.qcow2" - }, - "name": "3.5" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "The BIRD project aims to develop a fully functional dynamic IP routing daemon primarily targeted on (but not limited to) Linux, FreeBSD and other UNIX-like systems and distributed under the GNU General Public License.", - "documentation_url": "http://bird.network.cz/?get_doc&f=bird.html", - "images": [ - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/bird-tinycore64-1.5.0.img", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "bird-tinycore64-1.5.0.img", - "filesize": 22413312, - "md5sum": "08d50ba2b1b262e2e03e4babf90abf69", - "version": "1.5.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "BIRD", - "product_name": "BIRD internet routing daemon", - "qemu": { - "adapter_type": "e1000", - "adapters": 4, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "allow", - "ram": 128 - }, - "registry_version": 3, - "status": "stable", - "usage": "Configure interfaces in /opt/bootlocal.sh, BIRD configuration is done in /usr/local/etc/bird", - "vendor_name": "CZ.NIC Labs", - "vendor_url": "http://bird.network.cz/", - "versions": [ - { - "images": { - "hda_disk_image": "bird-tinycore64-1.5.0.img" - }, - "name": "1.5.0" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "The Brocade Virtual ADX (vADX\u2122) is a full-fledged Application Delivery Controller (ADC) platform with a virtual footprint that leverages Intel advanced technology to deliver remarkable performance. The software is designed to run on standardsbased hypervisors, hosted on Intel x86 COTS hardware. It offers a complete suite of Layer 4 and Layer 7 server load balancing capabilities and application security services with extensible management via rich SOAP/XML APIs.", - "first_port_name": "mgmt1", - "images": [ - { - "download_url": "http://www1.brocade.com/forms/jsp/virtual-adx-download/index.jsp", - "filename": "SSR03100KVM.qcow2", - "filesize": 3327066112, - "md5sum": "40e5717463fb2f5d1bb7c4de7df15c5c", - "version": "03100" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Brocade Virtual ADX", - "port_name_format": "Port {port1}", - "product_name": "Virtual ADX", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 8, - "arch": "x86_64", - "console_type": "vnc", - "kvm": "require", - "options": "-smp 2", - "ram": 2048 - }, - "registry_version": 3, - "status": "experimental", - "usage": "Login is root, type vadx-console to access to the console", - "vendor_name": "Brocade", - "vendor_url": "https://www.brocade.com", - "versions": [ - { - "images": { - "hda_disk_image": "SSR03100KVM.qcow2" - }, - "name": "03100" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "With proven ultra-high performance and scalability, the Brocade vRouter is the networking industry leader in software innovation. The Brocade vRouter has set a the benchmark for all software-based routers, while offering easy scalability, a broad set of capabilities, and the peace of mind that comes with rock solid reliability.", - "documentation_url": "http://www.brocade.com/en/products-services/software-networking/network-functions-virtualization/vrouter.html", - "images": [ - { - "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", - "filename": "vyatta-vrouter-17.1.1_B_amd64.iso", - "filesize": 347078656, - "md5sum": "914c9ca9d51a33fc54f718020f862df2", - "version": "17.1.1" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", - "filename": "vyatta-vrouter-17.1.0_B_amd64.iso", - "filesize": 346030080, - "md5sum": "ff524e06fda6d982b9b66f25940fe63b", - "version": "17.1.0" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", - "filename": "vyatta-vrouter-5.2R2_B_amd64.iso", - "filesize": 344981504, - "md5sum": "6b7dcc152a18187ad151483c139fb82c", - "version": "5.2R2" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", - "filename": "vyatta-vrouter-5.1R1_B_amd64.iso", - "filesize": 344981504, - "md5sum": "e374b8bae9eecd52ee841f5e262b3a16", - "version": "5.1R1" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", - "filename": "livecd-VR5600_5.0R2_B_amd64.iso", - "filesize": 340787200, - "md5sum": "ce47dba6f89ef1175ef8850110521104", - "version": "5.0R2" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", - "filename": "livecd-VR5600_4.2R1_B_amd64.iso", - "filesize": 326107136, - "md5sum": "5e3023c64dc409ae01d5bcb1b6732593", - "version": "4.2R1" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/vrouter/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-Vrouter&intcmp=lp_en_softevaluations_vrouter_bn_00001", - "filename": "vyatta-livecd_3.5R3T60_amd64.iso", - "filesize": 288358400, - "md5sum": "90360273f818a3dba83fa93ef6da938b", - "version": "3.5R3" - }, - { - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty8G.qcow2", - "filesize": 197120, - "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "vRouter", - "port_name_format": "eth{0}", - "product_name": "vRouter", - "product_url": "http://www.brocade.com/en/products-services/software-networking/network-functions-virtualization/vrouter.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 8, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "options": "-smp 4 -cpu host", - "ram": 4096 - }, - "registry_version": 3, - "status": "stable", - "usage": "60 days evaluation. The Brocade vRouter must be on-line and have public connectivity in order to communicate with the Brocade licensing server for automated license key generation. Please note that the evaluation software will only run for 24 hours after installation without the activation code being entered into the system. You must enter your activation code in order to retrieve your licensing key after you install the Brocade vRouter software. Default credentials: vyatta / vyatta", - "vendor_name": "Brocade", - "vendor_url": "http://www.brocade.com/", - "versions": [ - { - "images": { - "cdrom_image": "vyatta-vrouter-17.1.1_B_amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "17.1.1" - }, - { - "images": { - "cdrom_image": "vyatta-vrouter-17.1.0_B_amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "17.1.0" - }, - { - "images": { - "cdrom_image": "vyatta-vrouter-5.2R2_B_amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "5.2R2" - }, - { - "images": { - "cdrom_image": "vyatta-vrouter-5.1R1_B_amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "5.1R1" - }, - { - "images": { - "cdrom_image": "livecd-VR5600_5.0R2_B_amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "5.0R2" - }, - { - "images": { - "cdrom_image": "livecd-VR5600_4.2R1_B_amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "4.2R1" - }, - { - "images": { - "cdrom_image": "vyatta-livecd_3.5R3T60_amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "3.5R3" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Take control of your online applications with Brocade virtual Traffic Manager (Developer Edition). Enhance customer experience, inspect traffic in real-time, control service levels to differentiate users and services, and reduce your costs with an extensible delivery platform that can grow with your business using ADC-as-a-Service. A fully functional Developer Edition which needs no license key, is limited to 1 Mbps/100 SSL tps throughput, and has access to the Brocade Community support web pages.", - "documentation_url": "http://www.brocade.com/en/products-services/software-networking/application-delivery-controllers/virtual-traffic-manager.html", - "images": [ - { - "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", - "filename": "VirtualTrafficManager-173.qcow2", - "filesize": 2022178816, - "md5sum": "c3425d8ec3f8c7789c0a88b8ed6bdf3b", - "version": "17.3" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", - "filename": "VirtualTrafficManager-172.qcow2", - "filesize": 2039742464, - "md5sum": "00d3ab0422eb786bcbd77f5841220956", - "version": "17.2" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", - "filename": "VirtualTrafficManager-171.qcow2", - "filesize": 1771175936, - "md5sum": "397672218292e739bd33b203a91dbcf4", - "version": "17.1" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", - "filename": "VirtualTrafficManager-111.qcow2", - "filesize": 12189564928, - "md5sum": "3c9c63e2071d79c64cb4b17b355d2582", - "version": "11.1" - }, - { - "download_url": "http://www1.brocade.com/forms/jsp/steelapp-traffic-manager-developer/index.jsp?src=WS&lsd=BRCD&lst=English&cn=PA-GDG-16Q1-EVAL-TrafficManagerDeveloper&intcmp=lp_en_vTMdeveloper_eval_bn_00001", - "filename": "VirtualTrafficManager-110.img", - "filesize": 12191531008, - "md5sum": "7fb0bab8e1cf09076e87270b1418ec81", - "version": "11.0" - }, - { - "download_url": "http://my.brocade.com/", - "filename": "VirtualTrafficManager-104R1.img", - "filesize": 12193562624, - "md5sum": "395542073d6afb9e62e7d5a7b339c3b3", - "version": "10.4R1" - }, - { - "download_url": "http://my.brocade.com/", - "filename": "VirtualTrafficManager-104.img", - "filesize": 12190220288, - "md5sum": "88e31b072e17de12e241ef442bb5faae", - "version": "10.4" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "vTM DE", - "port_name_format": "eth{0}", - "product_name": "vTM DE", - "product_url": "http://www.brocade.com/en/products-services/software-networking/application-delivery-controllers/virtual-traffic-manager.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 8, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "symbol": "loadbalancer.svg", - "usage": "Credentials: admin / admin. The device gets its initial IP address using DHCP. After getting an IP address, you can access the initial configuration using the WebUI at https://IP_ADDRESS:9090", - "vendor_name": "Brocade", - "vendor_url": "http://www.brocade.com/", - "versions": [ - { - "images": { - "hda_disk_image": "VirtualTrafficManager-173.qcow2" - }, - "name": "17.3" - }, - { - "images": { - "hda_disk_image": "VirtualTrafficManager-172.qcow2" - }, - "name": "17.2" - }, - { - "images": { - "hda_disk_image": "VirtualTrafficManager-171.qcow2" - }, - "name": "17.1" - }, - { - "images": { - "hda_disk_image": "VirtualTrafficManager-111.qcow2" - }, - "name": "11.1" - }, - { - "images": { - "hda_disk_image": "VirtualTrafficManager-110.img" - }, - "name": "11.0" - }, - { - "images": { - "hda_disk_image": "VirtualTrafficManager-104R1.img" - }, - "name": "10.4R1" - }, - { - "images": { - "hda_disk_image": "VirtualTrafficManager-104.img" - }, - "name": "10.4" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "BSD Router Project (BSDRP) is an embedded free and open source router distribution based on FreeBSD with Quagga and Bird.", - "images": [ - { - "compression": "xz", - "direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.80/amd64/BSDRP-1.80-full-amd64-serial.img.xz/download", - "download_url": "https://bsdrp.net/downloads", - "filename": "BSDRP-1.80-full-amd64-serial.img", - "filesize": 1000000000, - "md5sum": "a4285be15ac85f67b3c7f044872a54b6", - "version": "1.80" - }, - { - "compression": "xz", - "direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.70/amd64/BSDRP-1.70-full-amd64-serial.img.xz/download", - "download_url": "https://bsdrp.net/downloads", - "filename": "BSDRP-1.70-full-amd64-serial.img", - "filesize": 1000000000, - "md5sum": "9c11f61ddf03ee9a9ae4149676175821", - "version": "1.70" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "BSDRP", - "product_name": "BSDRP", - "qemu": { - "adapter_type": "e1000", - "adapters": 4, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "allow", - "ram": 256 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default user: root (no password set)", - "vendor_name": "Olivier Cochard-Labbe", - "vendor_url": "https://bsdrp.net/", - "versions": [ - { - "images": { - "hda_disk_image": "BSDRP-1.80-full-amd64-serial.img" - }, - "name": "1.80" - }, - { - "images": { - "hda_disk_image": "BSDRP-1.70-full-amd64-serial.img" - }, - "name": "1.70" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "The CentOS Linux distribution is a stable, predictable, manageable and reproducible platform derived from the sources of Red Hat Enterprise Linux (RHEL). We are now looking to expand on that by creating the resources needed by other communities to come together and be able to build on the CentOS Linux platform. And today we start the process by delivering a clear governance model, increased transparency and access. In the coming weeks we aim to publish our own roadmap that includes variants of the core CentOS Linux.", - "documentation_url": "https://wiki.centos.org/", - "images": [ - { - "download_url": "http://www.osboxes.org/centos/", - "filename": "CentOS 7-1611 (64bit).vmdk", - "filesize": 4365877248, - "md5sum": "1da15f6144eab25c8546f81dd1c34092", - "version": "7-1611" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Centos", - "port_name_format": "eth{0}", - "product_name": "Centos", - "product_url": "https://www.centos.org/download/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 1, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "spice", - "hda_disk_interface": "ide", - "kvm": "require", - "options": "-vga qxl", - "ram": 2048 - }, - "registry_version": 5, - "status": "stable", - "usage": "Username: osboxes.org\nPassword: osboxes.org", - "vendor_name": "CentOS Linux", - "vendor_url": "https://www.centos.org/", - "versions": [ - { - "images": { - "hda_disk_image": "CentOS 7-1611 (64bit).vmdk" - }, - "name": "7-1611" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "Check Point Gaia is the next generation Secure Operating System for all Check Point Appliances, Open Servers and Virtualized Gateways.\n\nGaia combines the best features from IPSO and SecurePlatform (SPLAT) into a single unified OS providing greater efficiency and robust performance. By upgrading to Gaia, customers will benefit from improved appliance connection capacity and reduced operating costs. With Gaia, IP Appliance customers will gain the ability to leverage the full breadth and power of all Check Point Software Blades.\n\nGaia secures IPv6 networks utilizing the Check Point Acceleration & Clustering technology and it protects the most dynamic network and virtualized environments by supporting 5 different dynamic routing protocols. As a 64-Bit OS, Gaia increases the connection capacity of existing appliances supporting up-to 10M concurrent connections for select 2012 Models.\n\nGaia simplifies management with segregation of duties by enabling role-based administrative access. Furthermore, Gaia greatly increases operation efficiency by offering Automatic Software Update.\n\nThe feature-rich Web interface allows for search of any command or property in a second.\n\nGaia provides backward compatibility with IPSO and SPLAT CLI-style commands making it an easy transition for existing Check Point customers.", - "documentation_url": "http://downloads.checkpoint.com/dc/download.htm?ID=26770", - "images": [ - { - "download_url": "https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk104859", - "filename": "Check_Point_R80.10_T421_Gaia.iso", - "filesize": 3420127232, - "md5sum": "12d9723fadb89bb722e20ca3f89012ce", - "version": "80.10" - }, - { - "download_url": "https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk104859", - "filename": "Check_Point_R77.30_T204_Install_and_Upgrade.Gaia.iso", - "filesize": 2799271936, - "md5sum": "6fa7586bbb6832fa965d3173276c5b87", - "version": "77.30" - }, - { - "download_url": "https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk104859", - "filename": "Check_Point_R77.20_T124_Install.Gaia.iso", - "filesize": 2632974336, - "md5sum": "7552fa2ad3e1f0ac31615b60b736969c", - "version": "77.20" - }, - { - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty8G.qcow2", - "filesize": 197120, - "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Checkpoint GAiA", - "product_name": "Gaia", - "qemu": { - "adapter_type": "e1000", - "adapters": 8, - "arch": "x86_64", - "boot_priority": "dc", - "console_type": "telnet", - "kvm": "require", - "process_priority": "normal", - "ram": 2048 - }, - "registry_version": 3, - "status": "experimental", - "usage": "At boot choose the install on disk options. You need to open quickly the terminal after launching the appliance if you want to see the menu. You need a web browser in order to finalize the installation. You can use the firefox appliance for this.", - "vendor_name": "Checkpoint", - "vendor_url": "https://www.checkpoint.com", - "versions": [ - { - "images": { - "cdrom_image": "Check_Point_R80.10_T421_Gaia.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "80.10" - }, - { - "images": { - "cdrom_image": "Check_Point_R77.30_T204_Install_and_Upgrade.Gaia.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "77.30" - }, - { - "images": { - "cdrom_image": "Check_Point_R77.20_T124_Install.Gaia.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "77.20" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "The chromium browser", - "docker": { - "adapters": 1, - "console_type": "vnc", - "image": "gns3/chromium:latest" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Chromium", - "product_name": "Chromium", - "registry_version": 3, - "status": "stable", - "vendor_name": "Chromium", - "vendor_url": "https://www.chromium.org/" - }, - { - "builtin": true, - "category": "router", - "description": "Cisco 1700 Router", - "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", - "dynamips": { - "chassis": "1720", - "nvram": 128, - "platform": "c1700", - "ram": 160, - "slot0": "C1700-MB-1FE", - "startup_config": "ios_base_startup-config.txt" - }, - "images": [ - { - "filename": "c1700-adventerprisek9-mz.124-25d.image", - "filesize": 57475320, - "md5sum": "7f4ae12a098391bc0edcaf4f44caaf9d", - "version": "124-25d" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco 1700", - "product_name": "1700", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "idlepc": "0x80358a60", - "images": { - "image": "c1700-adventerprisek9-mz.124-25d.image" - }, - "name": "124-25d" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco 2600 Router", - "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", - "dynamips": { - "chassis": "2610", - "nvram": 128, - "platform": "c2600", - "ram": 160, - "startup_config": "ios_base_startup-config.txt" - }, - "images": [ - { - "filename": "c2600-adventerprisek9-mz.124-15.T14.image", - "filesize": 87256400, - "md5sum": "483e3a579a5144ec23f2f160d4b0c0e2", - "version": "124-15.T14" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco 2600", - "product_name": "2600", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "idlepc": "0x8027ec88", - "images": { - "image": "c2600-adventerprisek9-mz.124-15.T14.image" - }, - "name": "124-15.T14" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco 2691 Router", - "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", - "dynamips": { - "nvram": 256, - "platform": "c3600", - "ram": 192, - "slot0": "GT96100-FE", - "startup_config": "ios_base_startup-config.txt" - }, - "images": [ - { - "filename": "c2691-adventerprisek9-mz.124-15.T14.image", - "filesize": 95976624, - "md5sum": "e7ee5a4a57ed1433e5f73ba6e7695c90", - "version": "124-15.T14" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco 2691", - "product_name": "2691", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "idlepc": "0x60bcf9f8", - "images": { - "image": "c2691-adventerprisek9-mz.124-15.T14.image" - }, - "name": "124-15.T14" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco 3620 Router", - "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", - "dynamips": { - "chassis": "3620", - "nvram": 256, - "platform": "c3600", - "ram": 192, - "startup_config": "ios_base_startup-config.txt" - }, - "images": [ - { - "filename": "c3620-a3jk8s-mz.122-26c.image", - "filesize": 38947996, - "md5sum": "37b444b29191630e5b688f002de2171c", - "version": "122-26c" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco 3620", - "product_name": "3620", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "idlepc": "0x603a8bac", - "images": { - "image": "c3620-a3jk8s-mz.122-26c.image" - }, - "name": "122-26c" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco 3640 Router", - "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", - "dynamips": { - "chassis": "3640", - "nvram": 256, - "platform": "c3600", - "ram": 192, - "startup_config": "ios_base_startup-config.txt" - }, - "images": [ - { - "filename": "c3640-a3js-mz.124-25d.image", - "filesize": 65688632, - "md5sum": "493c4ef6578801d74d715e7d11596964", - "version": "124-25d" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco 3640", - "product_name": "3640", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "idlepc": "0x6050b114", - "images": { - "image": "c3640-a3js-mz.124-25d.image" - }, - "name": "124-25d" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco 3660 Router", - "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", - "dynamips": { - "chassis": "3660", - "nvram": 256, - "platform": "c3600", - "ram": 192, - "startup_config": "ios_base_startup-config.txt" - }, - "images": [ - { - "filename": "c3660-a3jk9s-mz.124-15.T14.image", - "filesize": 90181268, - "md5sum": "daed99f508fd42dbaacf711e560643ed", - "version": "124-15.T14" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco 3660", - "product_name": "3660", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "idlepc": "0x6076e0b4", - "images": { - "image": "c3660-a3jk9s-mz.124-15.T14.image" - }, - "name": "124-15.T14" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco 3725 Router", - "documentation_url": "http://www.cisco.com/c/en/us/support/index.html", - "dynamips": { - "nvram": 256, - "platform": "c3725", - "ram": 128, - "slot0": "GT96100-FE", - "startup_config": "ios_base_startup-config.txt" - }, - "images": [ - { - "filename": "c3725-adventerprisek9-mz.124-15.T14.image", - "filesize": 97859480, - "md5sum": "64f8c427ed48fd21bd02cf1ff254c4eb", - "version": "124-25.T14" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco 3725", - "product_name": "3725", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "idlepc": "0x60c09aa0", - "images": { - "image": "c3725-adventerprisek9-mz.124-15.T14.image" - }, - "name": "124-25.T14" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco 3745 Multiservice Access Router", - "documentation_url": "http://www.cisco.com/c/en/us/support/routers/3745-multiservice-access-router/model.html", - "dynamips": { - "chassis": "", - "nvram": 256, - "platform": "c3745", - "ram": 256, - "slot0": "GT96100-FE", - "slot1": "NM-1FE-TX", - "slot2": "NM-4T", - "slot3": "", - "slot4": "", - "startup_config": "ios_base_startup-config.txt", - "wic0": "WIC-1T", - "wic1": "WIC-1T", - "wic2": "WIC-1T" - }, - "images": [ - { - "filename": "c3745-adventerprisek9-mz.124-25d.image", - "filesize": 82053028, - "md5sum": "ddbaf74274822b50fa9670e10c75b08f", - "version": "124-25d" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco 3745", - "product_name": "3745", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "idlepc": "0x60aa1da0", - "images": { - "image": "c3745-adventerprisek9-mz.124-25d.image" - }, - "name": "124-25d" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco 7200 Router", - "documentation_url": "http://www.cisco.com/c/en/us/products/routers/7200-series-routers/index.html", - "dynamips": { - "midplane": "vxr", - "npe": "npe-400", - "nvram": 512, - "platform": "c7200", - "ram": 512, - "slot0": "C7200-IO-FE", - "startup_config": "ios_base_startup-config.txt" - }, - "images": [ - { - "filename": "c7200-adventerprisek9-mz.124-24.T5.image", - "filesize": 102345240, - "md5sum": "6b89d0d804e1f2bb5b8bda66b5692047", - "version": "124-25.T5" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco 7200", - "product_name": "7200", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "idlepc": "0x606df838", - "images": { - "image": "c7200-adventerprisek9-mz.124-24.T5.image" - }, - "name": "124-25.T5" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "The Adaptive Security Virtual Appliance is a virtualized network security solution based on the market-leading Cisco ASA 5500-X Series firewalls. It supports both traditional and next-generation software-defined network (SDN) and Cisco Application Centric Infrastructure (ACI) environments to provide policy enforcement and threat inspection across heterogeneous multisite environments.", - "documentation_url": "http://www.cisco.com/c/en/us/support/security/virtual-adaptive-security-appliance-firewall/products-installation-guides-list.html", - "first_port_name": "Management0/0", - "images": [ - { - "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", - "filename": "asav981-5.qcow2", - "filesize": 193069056, - "md5sum": "77b3ca856dd2df476bcda34e218425ca", - "version": "9.8.1-5" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286119613&flowid=50242&softwareid=280775065&release=9.8.1&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "asav981.qcow2", - "filesize": 193069056, - "md5sum": "8d3612fe22b1a7dec118010e17e29411", - "version": "9.8.1" - }, - { - "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", - "filename": "asav971-8.qcow2", - "filesize": 197066752, - "md5sum": "b2486c8d0f6fda149ce877208b816818", - "version": "9.7.1-8" - }, - { - "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", - "filename": "asav971-4.qcow2", - "filesize": 197066752, - "md5sum": "f9a671d1ceaf983f7241f19df15e787f", - "version": "9.7.1-4" - }, - { - "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", - "filename": "asav971-2.qcow2", - "filesize": 199753728, - "md5sum": "ff036b23f5dbb2bcf1e6530476cc1989", - "version": "9.7.1-2" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "asav971.qcow2", - "filesize": 198443008, - "md5sum": "07eef9b8ca489a8ad37448fadf45a673", - "version": "9.7.1" - }, - { - "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", - "filename": "asav963-8.qcow2", - "filesize": 168427520, - "md5sum": "8b8a45b94a302dae8076e7ec90c7d4c2", - "version": "9.6.3-8" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286119613&flowid=50242&softwareid=280775065&release=9.6.3&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "asav963-1.qcow2", - "filesize": 172294144, - "md5sum": "d6a5c8d7bff5e69c5987ca664a52dbd8", - "version": "9.6.3-1" - }, - { - "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242", - "filename": "asav962-13.qcow2", - "filesize": 177668096, - "md5sum": "2a6bec030fcaef31b611051180cc142c", - "version": "9.6.2-13" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "asav962.qcow2", - "filesize": 177274880, - "md5sum": "dfb8110ce38da4588e994865d5a9656a", - "version": "9.6.2" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco ASAv", - "port_name_format": "Gi0/{0}", - "product_name": "ASAv", - "product_url": "http://www.cisco.com/c/en/us/products/security/virtual-adaptive-security-appliance-firewall/index.html", - "qemu": { - "adapter_type": "e1000", - "adapters": 8, - "arch": "x86_64", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "symbol": ":/symbols/asa.svg", - "usage": "There is no default password and enable password. A default configuration is present. ASAv goes through a double-boot before becoming active. This is normal and expected.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "asav981-5.qcow2" - }, - "name": "9.8.1-5" - }, - { - "images": { - "hda_disk_image": "asav981.qcow2" - }, - "name": "9.8.1" - }, - { - "images": { - "hda_disk_image": "asav971-8.qcow2" - }, - "name": "9.7.1-8" - }, - { - "images": { - "hda_disk_image": "asav971-4.qcow2" - }, - "name": "9.7.1-4" - }, - { - "images": { - "hda_disk_image": "asav971-2.qcow2" - }, - "name": "9.7.1-2" - }, - { - "images": { - "hda_disk_image": "asav971.qcow2" - }, - "name": "9.7.1" - }, - { - "images": { - "hda_disk_image": "asav963-8.qcow2" - }, - "name": "9.6.3-8" - }, - { - "images": { - "hda_disk_image": "asav963-1.qcow2" - }, - "name": "9.6.3-1" - }, - { - "images": { - "hda_disk_image": "asav962-13.qcow2" - }, - "name": "9.6.2-13" - }, - { - "images": { - "hda_disk_image": "asav962.qcow2" - }, - "name": "9.6.2" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "The Cisco Cloud Services Router 1000V (CSR 1000V) is a router and network services platform in virtual form factor that is intended for deployment in cloud and virtual data centers. It is optimized to serve as a single-tenant or multitenant WAN gateway. Using proven, industry-leading Cisco IOS\u00ae XE Software networking and security features, the CSR 1000V enables enterprises to transparently extend their WANs into external provider-hosted clouds and cloud providers to offer their tenants enterprise-class networking services.", - "documentation_url": "http://www.cisco.com/c/en/us/support/routers/cloud-services-router-1000v-series/products-installation-and-configuration-guides-list.html", - "images": [ - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284364978&flowid=39582&softwareid=282046477&release=Fuji-16.7.1&relind=AVAILABLE&rellifecycle=ED&reltype=latest", - "filename": "csr1000v-universalk9.16.07.01-serial.qcow2", - "filesize": 882769920, - "md5sum": "13adbfc2586d06c9802b9805168c0c44", - "version": "16.7.1" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284364978&flowid=39582&softwareid=282046477&release=Denali-16.3.5&relind=AVAILABLE&rellifecycle=ED&reltype=latest", - "filename": "csr1000v-universalk9.16.06.01-serial.qcow2", - "filesize": 1566179328, - "md5sum": "909e74446d3ff0b82c14327c0058fdc2", - "version": "16.6.1" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284364978&flowid=39582&softwareid=282046477&release=Denali-16.3.5&relind=AVAILABLE&rellifecycle=ED&reltype=latest", - "filename": "csr1000v-universalk9.16.05.02-serial.qcow2", - "filesize": 1322385408, - "md5sum": "59a84da28d59ee75176aa05ecde7f72a", - "version": "16.5.2" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "csr1000v-universalk9.16.5.1b-serial.qcow2", - "filesize": 1209543680, - "md5sum": "ac11d33041b8ff6dc3553e324d02cccb", - "version": "16.5.1b" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "csr1000v-universalk9.03.17.00.S.156-1.S-ext.qcow2", - "filesize": 1346305024, - "md5sum": "06cbfcd11f3557391db64fe2a6015a6e", - "version": "3.17" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "csr1000v-universalk9.16.3.1-build2.qcow2", - "filesize": 1280835584, - "md5sum": "a770e96de928265515304c9c9d6b46b9", - "version": "16.3.1-build2" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284364978&softwareid=282046477&release=Denali-16.3.1", - "filename": "csr1000v-universalk9.16.03.01.qcow2", - "filesize": 1351352320, - "md5sum": "0a7f3a4b93d425c2dcb2df5505816fa5", - "version": "16.3.1" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "csr1000v-universalk9.16.03.02.qcow2", - "filesize": 1167720448, - "md5sum": "2e5803d23cd52cba5d55fa8306be5f13", - "version": "16.3.2" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "csr1000v-universalk9.16.4.1.qcow2", - "filesize": 1261961216, - "md5sum": "3428e0dcf5132a1b11ab7696d8c61b2e", - "version": "16.4.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco CSR1000v", - "port_name_format": "Gi{port1}", - "product_name": "CSR1000v", - "product_url": "http://www.cisco.com/c/en/us/support/routers/cloud-services-router-1000v-series/tsd-products-support-series-home.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "ram": 3072 - }, - "registry_version": 3, - "status": "stable", - "usage": "There is no default password and enable password. A default configuration is present.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "csr1000v-universalk9.16.07.01-serial.qcow2" - }, - "name": "16.7.1" - }, - { - "images": { - "hda_disk_image": "csr1000v-universalk9.16.06.01-serial.qcow2" - }, - "name": "16.6.1" - }, - { - "images": { - "hda_disk_image": "csr1000v-universalk9.16.05.02-serial.qcow2" - }, - "name": "16.5.2" - }, - { - "images": { - "hda_disk_image": "csr1000v-universalk9.16.5.1b-serial.qcow2" - }, - "name": "16.5.1b" - }, - { - "images": { - "hda_disk_image": "csr1000v-universalk9.03.17.00.S.156-1.S-ext.qcow2" - }, - "name": "3.17" - }, - { - "images": { - "hda_disk_image": "csr1000v-universalk9.16.03.01.qcow2" - }, - "name": "16.3.1" - }, - { - "images": { - "hda_disk_image": "csr1000v-universalk9.16.3.1-build2.qcow2" - }, - "name": "16.3.1-build2" - }, - { - "images": { - "hda_disk_image": "csr1000v-universalk9.16.03.02.qcow2" - }, - "name": "16.3.2" - }, - { - "images": { - "hda_disk_image": "csr1000v-universalk9.16.4.1.qcow2" - }, - "name": "16.4.1" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Cisco Data Center Network Manager (DCNM) 10 unifies and automates Cisco Nexus and Cisco MDS 9000 Family multitenant infrastructure for data center management across Cisco Nexus 5000, 6000, 7000, and 9000 Series Switches in NX\u2011OS mode using Cisco NX-OS Software as well as across Cisco MDS 9100 and 9300 Series Multilayer Fabric Switches, 9200 Series Multiservice Switches, and 9500 and 9700 Series Multilayer Directors. Data Center Network Manager 10 lets you manage very large numbers of devices while providing ready-to-use management and automation capabilities plus Virtual Extensible LAN (VXLAN) overlay visibility into Cisco Nexus LAN fabrics.", - "documentation_url": "http://www.cisco.com/c/en/us/support/cloud-systems-management/data-center-network-manager-10/model.html", - "images": [ - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=281722751&softwareid=282088134&release=10.1(1)&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "dcnm-va.10.1.1.iso", - "filesize": 2927532032, - "md5sum": "4eca14506decaf166251c64e67adb110", - "version": "10.1.1" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty100G.qcow2", - "filesize": 198656, - "md5sum": "1e6409a4523ada212dea2ebc50e50a65", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco DCNM", - "port_name_format": "eth{0}", - "product_name": "DCNM", - "product_url": "http://www.cisco.com/c/en/us/products/cloud-systems-management/prime-data-center-network-manager/index.html", - "qemu": { - "adapter_type": "e1000", - "adapters": 2, - "arch": "x86_64", - "console_type": "vnc", - "hda_disk_interface": "ide", - "kvm": "require", - "options": "-smp 2", - "ram": 8192 - }, - "registry_version": 3, - "status": "stable", - "symbol": "mgmt_station.svg", - "usage": "Default credentials: root / cisco123", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "cdrom_image": "dcnm-va.10.1.1.iso", - "hda_disk_image": "empty100G.qcow2" - }, - "name": "10.1.1" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "This is your administrative nerve center for managing critical Cisco network security solutions. It provides complete and unified management over firewalls, application control, intrusion prevention, URL filtering, and advanced malware protection. Easily go from managing a firewall to controlling applications to investigating and remediating malware outbreaks.", - "documentation_url": "http://www.cisco.com/c/en/us/td/docs/security/firepower/quick_start/kvm/fmcv-kvm-qsg.html", - "first_port_name": "eth0", - "images": [ - { - "download_url": "https://software.cisco.com/download/", - "filename": "Cisco_Firepower_Management_Center_Virtual-6.0.0-1005-disk1.vmdk", - "filesize": 1681540608, - "md5sum": "3fed60f1e7d6910c22d13e966acebd7f", - "version": "6.0.0 (1005) vmdk" - }, - { - "download_url": "https://software.cisco.com/download/", - "filename": "Cisco_Firepower_Management_Center_Virtual-6.1.0-330.qcow2", - "filesize": 1909391360, - "md5sum": "e3c64179ec46671caeb7ac3e4e58064f", - "version": "6.1.0 (330)" - }, - { - "download_url": "https://software.cisco.com/download/", - "filename": "Cisco_Firepower_Management_Center_Virtual_VMware-6.1.0-330-disk1.vmdk", - "filesize": 1938142720, - "md5sum": "8bc77b317cf0007dcbb0f187c1a0c01f", - "version": "6.1.0 (330) vmdk" - }, - { - "download_url": "https://software.cisco.com/download/", - "filename": "Cisco_Firepower_Management_Center_Virtual-6.2.0-362.qcow2", - "filesize": 1949302784, - "md5sum": "26e66882bf5f68adc0eca2f6bef7b613", - "version": "6.2.0 (362)" - }, - { - "download_url": "https://software.cisco.com/download/", - "filename": "Cisco_Firepower_Management_Center_Virtual_VMware-6.2.0-362-disk1.vmdk", - "filesize": 1983376384, - "md5sum": "772165cbda3c183bb0e77a1923dd4d09", - "version": "6.2.0 (362) vmdk" - }, - { - "download_url": "https://software.cisco.com/download/", - "filename": "Cisco_Firepower_Management_Center_Virtual-6.2.1-342.qcow2", - "filesize": 2113732608, - "md5sum": "29ebbbe71a6b766f6dea81e5ca32c275", - "version": "6.2.1 (342)" - }, - { - "download_url": "https://software.cisco.com/download/", - "filename": "Cisco_Firepower_Management_Center_Virtual_VMware-6.2.1-342-disk1.vmdk", - "filesize": 2150017536, - "md5sum": "4cf5b7fd68075b6f7ee0dd41a4029ca0", - "version": "6.2.1 (342) vmdk" - } - ], - "maintainer": "Community", - "maintainer_email": "", - "name": "Cisco FMCv", - "port_name_format": "eth{port1}", - "product_name": "Cisco Firepower Management Center Virtual", - "product_url": "http://www.cisco.com/c/en/us/td/docs/security/firepower/quick_start/kvm/fmcv-kvm-qsg.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 1, - "arch": "x86_64", - "console_type": "telnet", - "cpus": 4, - "hda_disk_interface": "scsi", - "kvm": "require", - "options": "", - "ram": 8192 - }, - "registry_version": 4, - "status": "experimental", - "symbol": "cisco-fmcv.svg", - "usage": "BE PATIENT\nOn first boot FMCv generates about 6GB of data. This can take 30 minutes or more. Plan on a long wait after the following line in the boot up:\n\n usbcore: registered new interface driver usb-storage\n\nInitial IP address: 192.168.45.45.\n\nDefault username/password: admin/Admin123.", - "vendor_name": "Cisco Systems", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual-6.0.0-1005-disk1.vmdk" - }, - "name": "6.0.0 (1005) vmdk" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual-6.1.0-330.qcow2" - }, - "name": "6.1.0 (330)" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual_VMware-6.1.0-330-disk1.vmdk" - }, - "name": "6.1.0 (330) vmdk" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual-6.2.0-362.qcow2" - }, - "name": "6.2.0 (362)" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual_VMware-6.2.0-362-disk1.vmdk" - }, - "name": "6.2.0 (362) vmdk" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual-6.2.1-342.qcow2" - }, - "name": "6.2.1 (342)" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Management_Center_Virtual_VMware-6.2.1-342-disk1.vmdk" - }, - "name": "6.2.1 (342) vmdk" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "Cisco Firepower Threat Defense Virtual NGFW appliances combine Cisco's proven network firewall with the industry\u2019s most effective next-gen IPS and advanced malware protection. All so you can get more visibility, be more flexible, save more, and protect better.", - "documentation_url": "http://www.cisco.com/c/en/us/td/docs/security/firepower/quick_start/kvm/ftdv-kvm-qsg.html", - "first_port_name": "Gigabit0/0 (Mgmt)", - "images": [ - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.2.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.2.0-363.qcow2", - "filesize": 1022885888, - "md5sum": "fafdae94ead07b23d6c8dc5f7a731e74", - "version": "6.2.0 (363)" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.2.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.2.0-363.vmdk", - "filesize": 1042470912, - "md5sum": "10297ab20526a8b1586c6ce1cd3d9cbd", - "version": "6.2.0 (363) vmdk" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.1.0-330.qcow2", - "filesize": 1004601344, - "md5sum": "386ab2b3d6d1d28fd2cd03a83df5e00f", - "version": "6.1.0 (330)" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.1.0-330.vmdk", - "filesize": 1024162816, - "md5sum": "c1fa58448841b33d5eed6854dc608816", - "version": "6.1.0 (330) vmdk" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286306503&catid=268438162&softwareid=286306337&release=6.0.1&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "Cisco_Firepower_Threat_Defense_Virtual-6.0.1-1213.vmdk", - "filesize": 714577408, - "md5sum": "bc53461e2ec344814e41a6a8d3a5f774", - "version": "6.0.1 (1213) vmdk" - } - ], - "maintainer": "Community", - "maintainer_email": "", - "name": "Cisco FTDv", - "port_name_format": "Gigabit0/{port1}", - "product_name": "Cisco FTDv", - "product_url": "http://www.cisco.com/c/en/us/td/docs/security/firepower/quick_start/kvm/ftdv-kvm-qsg.html", - "qemu": { - "adapter_type": "e1000", - "adapters": 10, - "arch": "x86_64", - "console_type": "telnet", - "cpus": 4, - "hda_disk_interface": "ide", - "kvm": "require", - "ram": 8192 - }, - "registry_version": 4, - "status": "experimental", - "symbol": ":/symbols/asa.svg", - "usage": "Default username/password: admin/Admin123.", - "vendor_name": "Cisco Systems", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.2.0-363.qcow2" - }, - "name": "6.2.0 (363)" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.2.0-363.vmdk" - }, - "name": "6.2.0 (363) vmdk" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.1.0-330.qcow2" - }, - "name": "6.1.0 (330)" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.1.0-330.vmdk" - }, - "name": "6.1.0 (330) vmdk" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_Threat_Defense_Virtual-6.0.1-1213.vmdk" - }, - "name": "6.0.1 (1213) vmdk" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco Virtual IOS allows user to run IOS on a standard computer.", - "images": [ - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Qemu Appliances/IOSv_startup_config.img/download", - "download_url": "https://sourceforge.net/projects/gns-3/files", - "filename": "IOSv_startup_config.img", - "filesize": 1048576, - "md5sum": "bc605651c4688276f81fd59dcf5cc786", - "version": "1" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "vios-adventerprisek9-m.vmdk.SPA.156-2.T", - "filesize": 128450560, - "md5sum": "83707e3cc93646da58ee6563a68002b5", - "version": "15.6(2)T" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "vios-adventerprisek9-m.vmdk.SPA.156-1.T", - "filesize": 128122880, - "md5sum": "e7cb1bbd0c59280dd946feefa68fa270", - "version": "15.6(1)T" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "vios-adventerprisek9-m.vmdk.SPA.155-3.M", - "filesize": 127926272, - "md5sum": "79f613ac3b179d5a64520730925130b2", - "version": "15.5(3)M" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco IOSv", - "port_name_format": "Gi0/{0}", - "product_name": "IOSv", - "product_url": "http://virl.cisco.com/", - "qemu": { - "adapter_type": "e1000", - "adapters": 4, - "arch": "x86_64", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "require", - "ram": 512 - }, - "registry_version": 3, - "status": "stable", - "usage": "There is no default password and enable password. There is no default configuration present.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "vios-adventerprisek9-m.vmdk.SPA.156-2.T", - "hdb_disk_image": "IOSv_startup_config.img" - }, - "name": "15.6(2)T" - }, - { - "images": { - "hda_disk_image": "vios-adventerprisek9-m.vmdk.SPA.156-1.T", - "hdb_disk_image": "IOSv_startup_config.img" - }, - "name": "15.6(1)T" - }, - { - "images": { - "hda_disk_image": "vios-adventerprisek9-m.vmdk.SPA.155-3.M", - "hdb_disk_image": "IOSv_startup_config.img" - }, - "name": "15.5(3)M" - } - ] - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "Cisco Virtual IOS L2 allows user to run a IOS switching image on a standard computer.", - "images": [ - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "vios_l2-adventerprisek9-m.03.2017.qcow2", - "filesize": 41157632, - "md5sum": "8f14b50083a14688dec2fc791706bb3e", - "version": "15.2(20170321:233949)" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "vios_l2-adventerprisek9-m.vmdk.SSA.152-4.0.55.E", - "filesize": 96862208, - "md5sum": "1a3a21f5697cae64bb930895b986d71e", - "version": "15.2.4055" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco IOSvL2", - "port_name_format": "Gi{1}/{0}", - "port_segment_size": 4, - "product_name": "IOSvL2", - "product_url": "http://virl.cisco.com/", - "qemu": { - "adapter_type": "e1000", - "adapters": 16, - "arch": "x86_64", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 768 - }, - "registry_version": 3, - "status": "stable", - "usage": "There is no default password and enable password. There is no default configuration present.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "vios_l2-adventerprisek9-m.03.2017.qcow2" - }, - "name": "15.2(20170321:233949)" - }, - { - "images": { - "hda_disk_image": "vios_l2-adventerprisek9-m.vmdk.SSA.152-4.0.55.E" - }, - "name": "15.2.4055" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "IOS XRv supports the control plane features introduced in Cisco IOS XR.", - "documentation_url": "http://www.cisco.com/c/en/us/td/docs/ios_xr_sw/ios_xrv/release/notes/xrv-rn.html", - "first_port_name": "MgmtEth0/0/CPU0/0", - "images": [ - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "iosxrv-k9-demo-6.1.3.qcow2", - "filesize": 428588544, - "md5sum": "1693b5d22a398587dd0fed2877d8dfac", - "version": "6.1.3" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "iosxrv-k9-demo-6.0.1.qcow2", - "filesize": 908132352, - "md5sum": "0831ecf43628eccb752ebb275de9a62a", - "version": "6.0.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco IOS XRv", - "port_name_format": "Gi0/0/0/{0}", - "product_name": "IOS XRv", - "product_url": "http://virl.cisco.com/", - "qemu": { - "adapter_type": "e1000", - "adapters": 9, - "arch": "i386", - "console_type": "telnet", - "kvm": "require", - "ram": 3072 - }, - "registry_version": 3, - "status": "stable", - "usage": "You can set admin username and password on first boot. Don't forget about the two-staged configuration, you have to commit your changes.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "iosxrv-k9-demo-6.1.3.qcow2" - }, - "name": "6.1.3" - }, - { - "images": { - "hda_disk_image": "iosxrv-k9-demo-6.0.1.qcow2" - }, - "name": "6.0.1" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "IOS XRv 9000 (aka Sunstone) is the 1st VM released running the 64-bit IOS XR operating system as used on the NCS-6xxx platform. This appliance requires 4 vCPUs and 16GB of memory to run!", - "documentation_url": "http://www.cisco.com/c/en/us/td/docs/ios_xr_sw/ios_xrv/release/notes/xrv-rn.html", - "first_port_name": "MgmtEth0/0/CPU0/0", - "images": [ - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "xrv9k-fullk9-x-6.2.25.qcow2", - "filesize": 1190723584, - "md5sum": "3f54e62b6f7cedfb2607233e5e465766", - "version": "6.2.25" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "xrv9k-fullk9-x.qcow2-6.0.1", - "filesize": 2109210624, - "md5sum": "e20d046807075046c35b6ce7d6766a7f", - "version": "6.0.1" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "xrv9k-fullk9-x.qcow2-6.0.0", - "filesize": 2572943360, - "md5sum": "64c538c34252aaeb4ed1ddb93d6803fd", - "version": "6.0.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco IOS XRv 9000", - "port_name_format": "GigabitEthernet0/0/0/{0}", - "product_name": "IOS XRv 9000", - "product_url": "http://virl.cisco.com/", - "qemu": { - "adapter_type": "e1000", - "adapters": 4, - "arch": "i386", - "console_type": "telnet", - "kvm": "require", - "options": "-smp 4", - "ram": 16384 - }, - "registry_version": 3, - "status": "experimental", - "usage": "Default username/password: admin/admin, cisco/cisco and lab/lab. There is no default configuration present.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "xrv9k-fullk9-x-6.2.25.qcow2" - }, - "name": "6.2.25" - }, - { - "images": { - "hda_disk_image": "xrv9k-fullk9-x.qcow2-6.0.1" - }, - "name": "6.0.1" - }, - { - "images": { - "hda_disk_image": "xrv9k-fullk9-x.qcow2-6.0.0" - }, - "name": "6.0.0" - } - ] - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "Cisco IOS on UNIX Layer 2 image.", - "images": [ - { - "filename": "i86bi-linux-l2-ipbasek9-15.1g.bin", - "filesize": 62137336, - "md5sum": "0b8b9e14ca99b68c654e44c4296857ba", - "version": "15.1g" - }, - { - "filename": "i86bi-linux-l2-adventerprisek9-15.1a.bin", - "filesize": 72726092, - "md5sum": "9549a20a7391fb849da32caa77a0d254", - "version": "15.1a" - }, - { - "filename": "i86bi-linux-l2-adventerprisek9-15.2d.bin", - "filesize": 105036380, - "md5sum": "f16db44433beb3e8c828db5ddad1de8a", - "version": "15.2d" - } - ], - "iou": { - "ethernet_adapters": 4, - "nvram": 128, - "ram": 256, - "serial_adapters": 0, - "startup_config": "iou_l2_base_startup-config.txt" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco IOU L2", - "product_name": "Cisco IOU L2", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "images": { - "image": "i86bi-linux-l2-ipbasek9-15.1g.bin" - }, - "name": "15.1g" - }, - { - "images": { - "image": "i86bi-linux-l2-adventerprisek9-15.1a.bin" - }, - "name": "15.1a" - }, - { - "images": { - "image": "i86bi-linux-l2-adventerprisek9-15.2d.bin" - }, - "name": "15.2d" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cisco IOS on UNIX Layer 3 image.", - "images": [ - { - "filename": "i86bi-linux-l3-adventerprisek9-ms.155-2.T.bin", - "filesize": 172982492, - "md5sum": "45e99761a95cbd3ee3924ecf0f3d89e5", - "version": "155-2T" - }, - { - "filename": "i86bi-linux-l3-adventerprisek9-15.4.1T.bin", - "filesize": 152677848, - "md5sum": "2eabae17778316c49cbc80e8e81262f9", - "version": "15.4.1T" - } - ], - "iou": { - "ethernet_adapters": 2, - "nvram": 128, - "ram": 256, - "serial_adapters": 2, - "startup_config": "iou_l3_base_startup-config.txt" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco IOU L3", - "product_name": "Cisco IOU L3", - "registry_version": 3, - "status": "experimental", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com", - "versions": [ - { - "images": { - "image": "i86bi-linux-l3-adventerprisek9-ms.155-2.T.bin" - }, - "name": "155-2T" - }, - { - "images": { - "image": "i86bi-linux-l3-adventerprisek9-15.4.1T.bin" - }, - "name": "15.4.1T" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "The Cisco ISE platform is a comprehensive, next-generation, contextually-based access control solution. Cisco ISE offers authenticated network access, profiling, posture, guest management, and security group access services along with monitoring, reporting, and troubleshooting capabilities on a single physical or virtual appliance.", - "documentation_url": "http://www.cisco.com/c/en/us/support/security/identity-services-engine/tsd-products-support-series-home.html", - "images": [ - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=283801620&flowid=&softwareid=283802505&release=2.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "ise-2.1.0.474.SPA.x86_64.iso", - "filesize": 6161475584, - "md5sum": "8dc844696790f2f5f37054899fab3e2a", - "version": "2.1.0.474" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=283801620&flowid=&softwareid=283802505&release=2.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "ise-2.0.1.130.SPA.x86_64.iso", - "filesize": 5129990144, - "md5sum": "25ac842fdbb61f6e75f2f8b26beea28e", - "version": "2.0.1.130" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=283801620&flowid=&softwareid=283802505&release=2.0.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "ise-2.0.0.306.SPA.x86_64.iso", - "filesize": 5088827392, - "md5sum": "b7a454ee235db29b5c208b19bfd1fbd1", - "version": "2.0.0.306" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty200G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty200G.qcow2", - "filesize": 200192, - "md5sum": "d1686d2f25695dee32eab9a6f4652c7c", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco ISE", - "port_name_format": "GigabitEthernet{0}", - "product_name": "Identity Services Engine", - "product_url": "http://www.cisco.com/c/en/us/products/security/identity-services-engine/index.html", - "qemu": { - "adapter_type": "e1000", - "adapters": 2, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "ide", - "kvm": "require", - "options": "-smp 2", - "ram": 4096 - }, - "registry_version": 3, - "status": "experimental", - "symbol": "cisco-ise.svg", - "usage": "Starting ISE will start an installation of ISE onto a blank 200GB Drive. This will take time. The intial username is setup.\n\nThis appliance requires KVM. You may try it on a system without KVM, but it will run really slow, if at all.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "cdrom_image": "ise-2.1.0.474.SPA.x86_64.iso", - "hda_disk_image": "empty200G.qcow2" - }, - "name": "2.1.0.474" - }, - { - "images": { - "cdrom_image": "ise-2.0.1.130.SPA.x86_64.iso", - "hda_disk_image": "empty200G.qcow2" - }, - "name": "2.0.1.130" - }, - { - "images": { - "cdrom_image": "ise-2.0.0.306.SPA.x86_64.iso", - "hda_disk_image": "empty200G.qcow2" - }, - "name": "2.0.0.306" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "Cisco Firepower Next-Generation IPS (NGIPS) threat appliances combine superior visibility, embedded security intelligence, automated analysis, and industry-leading threat effectiveness.", - "documentation_url": "http://www.cisco.com/c/en/us/support/security/ngips-virtual-appliance/tsd-products-support-series-home.html", - "first_port_name": "eth0 (Mgmt)", - "images": [ - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286259690&softwareid=286271056&release=6.0.0.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "Cisco_Firepower_NGIPSv_VMware-6.0.0-1005-disk1.vmdk", - "filesize": 804301312, - "md5sum": "72ed34d39c58a9d5ad1c6197d1ff9a62", - "version": "6.0.0 (1005) vmdk" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286259690&softwareid=286271056&release=6.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "Cisco_Firepower_NGIPSv_VMware-6.1.0-330-disk1.vmdk", - "filesize": 860411392, - "md5sum": "7a771cc8c37a0371285f24c25f9886f0", - "version": "6.1.0 (330) vmdk" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=286259690&softwareid=286271056&release=6.2.0&relind=AVAILABLE&rellifecycle=&reltype=latest", - "filename": "Cisco_Firepower_NGIPSv_VMware-6.2.0-362-disk1.vmdk", - "filesize": 877626368, - "md5sum": "46f629149e11ac5c224bae0486c7e406", - "version": "6.2.0 (362) vmdk" - } - ], - "maintainer": "Community", - "maintainer_email": "", - "name": "Cisco NGIPSv", - "port_name_format": "eth{port1}", - "product_name": "Cisco Firepower NGIPS Virtual", - "product_url": "http://www.cisco.com/c/en/us/support/security/ngips-virtual-appliance/tsd-products-support-series-home.html", - "qemu": { - "adapter_type": "vmxnet3", - "adapters": 10, - "arch": "x86_64", - "console_type": "telnet", - "cpus": 4, - "hda_disk_interface": "scsi", - "kvm": "require", - "ram": 8192 - }, - "registry_version": 4, - "status": "experimental", - "symbol": ":/symbols/ids.svg", - "usage": "Default username/password: admin/Admin123.", - "vendor_name": "Cisco Systems", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "Cisco_Firepower_NGIPSv_VMware-6.2.0-362-disk1.vmdk" - }, - "name": "6.2.0 (362) vmdk" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_NGIPSv_VMware-6.1.0-330-disk1.vmdk" - }, - "name": "6.1.0 (330) vmdk" - }, - { - "images": { - "hda_disk_image": "Cisco_Firepower_NGIPSv_VMware-6.0.0-1005-disk1.vmdk" - }, - "name": "6.0.0 (1005) vmdk" - } - ] - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "NXOSv is a reference platform for an implementation of the Cisco Nexus operating system, based on the Nexus 7000-series platforms, running as a full virtual machine on a hypervisor. This includes NXAPI and MPLS LDP support.", - "first_port_name": "mgmt0", - "images": [ - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "titanium-final.7.3.0.D1.1.qcow2", - "filesize": 214368256, - "md5sum": "b4cd6edf15ab4c6bce53c3f6c1e3a742", - "version": "7.3.0" - }, - { - "download_url": "https://virl.mediuscorp.com/my-account/", - "filename": "titanium-d1.7.2.0.D1.1.vmdk", - "filesize": 361103360, - "md5sum": "0ee38c7d717840cb4ca822f4870671d0", - "version": "7.2.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco NX-OSv", - "port_name_format": "Ethernet2/{port1}", - "product_name": "NX-OSv", - "product_url": "http://virl.cisco.com/", - "qemu": { - "adapter_type": "e1000", - "adapters": 16, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "ram": 3072 - }, - "registry_version": 3, - "status": "stable", - "usage": "The default username/password is admin/admin. A default configuration is present.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "titanium-final.7.3.0.D1.1.qcow2" - }, - "name": "7.3.0" - }, - { - "images": { - "hda_disk_image": "titanium-d1.7.2.0.D1.1.vmdk" - }, - "name": "7.2.0" - } - ] - }, - { - "availability": "service-contract", - "builtin": true, - "category": "multilayer_switch", - "description": "The NX-OSv 9000 is a virtual platform that is designed to simulate the control plane aspects of a network element running Cisco Nexus 9000 software. The NX-OSv 9000 shares the same software image running on Cisco Nexus 9000 hardware platform although no specific hardware emulation is implemented. When the software runs as a virtual machine, line card (LC) ASIC provisioning or any interaction from the control plane to hardware ASIC is handled by the NX-OSv 9000 software data plane.\nThe NX-OSv 9000 for the Cisco Nexus 9000 Series provides a useful tool to enable the devops model and rapidly test changes to the infrastructure or to infrastructure automation tools. This enables network simulations in large scale for customers to validate configuration changes on a simulated network prior to applying them on a production network. Some users have also expressed interest in using the simulation system for feature test ,verification, and automation tooling development and test simualtion prior to deployment. NX-OSv 9000 can be used as a programmability vehicle to validate software defined networks (SDNs) and Network Function Virtualization (NFV) based solutions.", - "documentation_url": "http://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus9000/sw/7-x/nx-osv/configuration/guide/b_NX-OSv_9000/b_NX-OSv_chapter_01.html", - "first_port_name": "mgmt0", - "images": [ - { - "download_url": "https://software.cisco.com/download/", - "filename": "nxosv-final.7.0.3.I7.1.qcow2", - "filesize": 903151616, - "md5sum": "3c122f27d0c3684c63657207eadf4d06", - "version": "7.0.3.I7.1" - }, - { - "download_url": "https://software.cisco.com/download/", - "filename": "nxosv-final.7.0.3.I6.1.qcow2", - "filesize": 780402688, - "md5sum": "18bb991b814a508d1190575f99deed99", - "version": "7.0.3.I6.1" - }, - { - "download_url": "https://software.cisco.com/download/", - "filename": "nxosv-final.7.0.3.I5.2.qcow2", - "filesize": 777715712, - "md5sum": "c06aaa02f758a64fd8fee9406756f1da", - "version": "7.0.3.I5.2" - }, - { - "download_url": "https://software.cisco.com/download/", - "filename": "nxosv-final.7.0.3.I5.1.qcow2", - "filesize": 784990208, - "md5sum": "201ea658fa4c57452ee4b2aa4f5262a7", - "version": "7.0.3.I5.1" - }, - { - "compression": "zip", - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/OVMF-20160813.fd.zip/download", - "download_url": "", - "filename": "OVMF-20160813.fd", - "filesize": 2097152, - "md5sum": "8ff0ef1ec56345db5b6bda1a8630e3c6", - "version": "16.08.13" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco NX-OSv 9000", - "port_name_format": "Ethernet1/{port1}", - "product_name": "NX-OSv 9000", - "qemu": { - "adapter_type": "e1000", - "adapters": 10, - "arch": "x86_64", - "console_type": "telnet", - "cpus": 2, - "hda_disk_interface": "sata", - "kvm": "require", - "ram": 8096 - }, - "registry_version": 4, - "status": "stable", - "usage": "The old (I5) versions might require 8192 MB of RAM; adjust it if necessary.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "bios_image": "OVMF-20160813.fd", - "hda_disk_image": "nxosv-final.7.0.3.I7.1.qcow2" - }, - "name": "7.0.3.I7.1" - }, - { - "images": { - "bios_image": "OVMF-20160813.fd", - "hda_disk_image": "nxosv-final.7.0.3.I6.1.qcow2" - }, - "name": "7.0.3.I6.1" - }, - { - "images": { - "bios_image": "OVMF-20160813.fd", - "hda_disk_image": "nxosv-final.7.0.3.I5.2.qcow2" - }, - "name": "7.0.3.I5.2" - }, - { - "images": { - "bios_image": "OVMF-20160813.fd", - "hda_disk_image": "nxosv-final.7.0.3.I5.1.qcow2" - }, - "name": "7.0.3.I5.1" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "The Virtual Wireless Controller can cost-effectively manage, secure, and optimize the performance of local and branch wireless networks. Ideal for small and medium-sized businesses, the Virtual Wireless Controller facilitates server consolidation and improves business continuity in the face of outages.", - "documentation_url": "http://www.cisco.com/c/en/us/products/wireless/wireless-lan-controller/index.html", - "first_port_name": "ServicePort", - "images": [ - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=7.3.101.0", - "filename": "Cisco-vWLC-AIR-CTVM-7-3-101-0-file1.iso", - "filesize": 157900800, - "md5sum": "6bf17dceaf46e57aab0fb0d43eb6ea06", - "version": "7.3.101.0" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=7.6.110.0", - "filename": "AIR-CTVM-7-6-110-0-file1.iso", - "filesize": 185561088, - "md5sum": "7acbd88120f008a25d849b72b7207e92", - "version": "7.6.110.0" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=8.1.120.0", - "filename": "AIR-CTVM-k9-8-1-120.0.iso", - "filesize": 302104576, - "md5sum": "477363f88f07f64499bb4ab80ffa9d2f", - "version": "8.1.120.0" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=8.2.141.0", - "filename": "MFG_CTVM_8_2_141_0.iso", - "filesize": 351156224, - "md5sum": "29483229ce7844df55a90564b077c958", - "version": "8.2.141.0" - }, - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=8.3.102.0", - "filename": "MFG_CTVM_8_3_102_0.iso", - "filesize": 365996032, - "md5sum": "7f6b7968b5bed04b5ecc119b6ba4e41c", - "version": "8.3.102.0" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty8G.qcow2", - "filesize": 197120, - "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cisco vWLC", - "port_name_format": "Management{port1}", - "product_name": "Virtual Wireless LAN Controller", - "product_url": "http://www.cisco.com/c/en/us/support/wireless/virtual-wireless-controller/tsd-products-support-series-home.html", - "qemu": { - "adapter_type": "e1000", - "adapters": 2, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "ide", - "kvm": "require", - "options": "", - "ram": 2048 - }, - "registry_version": 3, - "status": "experimental", - "symbol": ":/symbols/wlan_controller.svg", - "usage": "Starting vWLC will start an installation of vWLC onto a blank 8GB Drive.", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "cdrom_image": "AIR-CTVM-k9-8-1-120.0.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "8.1.120.0" - }, - { - "images": { - "cdrom_image": "MFG_CTVM_8_2_141_0.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "8.2.141.0" - }, - { - "images": { - "cdrom_image": "MFG_CTVM_8_3_102_0.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "8.3.102.0" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "The Cisco WSA was one of the first secure web gateways to combine leading protections to help organizations address the growing challenges of securing and controlling web traffic. It enables simpler, faster deployment with fewer maintenance requirements, reduced latency, and lower operating costs. \u201cSet and forget\u201d technology frees staff after initial automated policy settings go live, and automatic security updates are pushed to network devices every 3 to 5 minutes. Flexible deployment options and integration with your existing security infrastructure help you meet quickly evolving security requirements.", - "documentation_url": "http://www.cisco.com/c/en/us/support/security/web-security-appliance/tsd-products-support-series-home.html", - "images": [ - { - "download_url": "https://software.cisco.com/download/release.html?mdfid=284806698&flowid=41610&softwareid=282975114&release=9.0.1&relind=AVAILABLE&rellifecycle=LD&reltype=latest", - "filename": "coeus-9-0-1-162-S000V.qcow2", - "filesize": 4753719296, - "md5sum": "3561a6dd9e1b0481e6e68f7e0235fa9b", - "version": "9.0.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Web Security Virtual Appliance", - "port_name_format": "nic{0}", - "product_name": "Web Security Virtual Appliance", - "product_url": "http://www.cisco.com/c/en/us/products/security/web-security-appliance/index.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 5, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 4096 - }, - "registry_version": 3, - "status": "stable", - "usage": "Boot takes some time. NIC0 is the management port, it gets its initial address using DHCP. Default credentials: admin / ironport", - "vendor_name": "Cisco", - "vendor_url": "http://www.cisco.com/", - "versions": [ - { - "images": { - "hda_disk_image": "coeus-9-0-1-162-S000V.qcow2" - }, - "name": "9.0.1" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Today\u2019s enterprises face more demands than ever, from cloud computing to 24/7 availability to increasing security threats. NetScaler ADC, an advanced software-defined application delivery controller, is your networking power player. It provides outstanding delivery of business applications\u2014to any device and any location\u2014with unmatched security, superior L4-7 load balancing, reliable GSLB, and 100 percent uptime. In fact, NetScaler ADC offers up to five times the performance of our closest competitor. Plus our TriScale technology saves you money by allowing your network to scale up or down without additional hardware costs.", - "documentation_url": "https://www.citrix.com/products/netscaler-adc/support.html", - "images": [ - { - "download_url": "https://www.citrix.com/downloads/netscaler-adc/virtual-appliances/netscaler-vpx-express.html", - "filename": "NSVPX-KVM-11.1-47.14_nc.raw", - "filesize": 21474836480, - "md5sum": "f7100f8b6588e152ce6f64e45b1e99fc", - "version": "11.1-47.14 F" - }, - { - "download_url": "https://www.citrix.com/downloads/netscaler-adc/virtual-appliances/netscaler-vpx-express.html", - "filename": "NSVPX-KVM-10.5-56.22_nc.raw", - "filesize": 21474836480, - "md5sum": "b7569f09d4c348c5cf825627169131e7", - "version": "10.5-56.22" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "NetScaler VPX", - "port_name_format": "1/{0}", - "product_name": "NetScaler VPX", - "product_url": "https://www.citrix.com/products/netscaler-adc/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "telnet", - "hda_disk_interface": "ide", - "kvm": "require", - "options": "-smp 2 -cpu host", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "symbol": "loadbalancer.svg", - "usage": "The image file is large (21.5 GB), make sure you have enough space. Default credentials: nsroot / nsroot", - "vendor_name": "Citrix", - "vendor_url": "http://www.citrix.com/", - "versions": [ - { - "images": { - "hda_disk_image": "NSVPX-KVM-11.1-47.14_nc.raw" - }, - "name": "11.1-47.14 F" - }, - { - "images": { - "hda_disk_image": "NSVPX-KVM-10.5-56.22_nc.raw" - }, - "name": "10.5-56.22" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "ClearOS is an operating system for your Server, Network, and Gateway systems. It is designed for homes, small to medium businesses, and distributed environments. ClearOS is commonly known as the Next Generation Small Business Server, while including indispensable Gateway and Networking functionality. It delivers a powerful IT solution with an elegant user interface that is completely web-based. Simply put.. ClearOS is the new way of delivering IT.", - "documentation_url": "https://www.clearos.com/resources/documentation/clearos-7-documentation-overview", - "images": [ - { - "download_url": "https://www.clearos.com/clearfoundation/software/clearos-downloads", - "filename": "ClearOS-7.3-DVD-x86_64.iso", - "filesize": 884998144, - "md5sum": "1bae8b2d7abe1bc72665a270f10a5149", - "version": "7.3" - }, - { - "download_url": "https://www.clearos.com/clearfoundation/software/clearos-downloads", - "filename": "ClearOS-7.2-DVD-x86_64.iso", - "filesize": 855638016, - "md5sum": "a094763e6ed5d9b073fd4e651f9a48f1", - "version": "7.2" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "ClearOS CE", - "product_name": "ClearOS CE", - "product_url": "https://www.clearos.com/clearfoundation/software/clearos-7-community", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 3, - "arch": "x86_64", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "usage": "Follow the installer.", - "vendor_name": "ClearCenter, Corp.", - "vendor_url": "https://www.clearos.com/", - "versions": [ - { - "images": { - "cdrom_image": "ClearOS-7.3-DVD-x86_64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "7.3" - }, - { - "images": { - "cdrom_image": "ClearOS-7.2-DVD-x86_64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "7.2" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "The CloudRouter Project is a collaborative open source project focused on developing a powerful, easy to use router designed for the cloud.\nCompute resources are rapidly migrating from physical infrastructure to a combination of physical, virtual and cloud environments. A similar transition is emerging in the networking space, with network control logic shifting from proprietary hardware-based platforms to open source software-based platforms. CloudRouter is a software-based router distribution designed to run on physical, virtual and cloud environments, supporting software-defined networking infrastructure. It includes the features of traditional hardware routers, as well as support for emerging technologies such as containers and software-defined interconnection. CloudRouter aims to facilitate migration to the cloud without giving up control over network routing and governance.", - "documentation_url": "https://cloudrouter.atlassian.net/wiki/display/CPD/CloudRouter+Project+Information", - "images": [ - { - "compression": "xz", - "direct_download_url": "https://repo.cloudrouter.org/4/centos/7/images/cloudrouter-centos-cloud-full.raw.xz", - "download_url": "https://cloudrouter.atlassian.net/wiki/display/CPD/CloudRouter+Downloads", - "filename": "cloudrouter-centos-cloud-full.raw", - "filesize": 10737418240, - "md5sum": "d148288ecc0806e08f8347ef0ad755e8", - "version": "4.0 Full" - }, - { - "compression": "xz", - "direct_download_url": "https://repo.cloudrouter.org/4/centos/7/images/cloudrouter-centos-cloud-minimal.raw.xz", - "download_url": "https://cloudrouter.atlassian.net/wiki/display/CPD/CloudRouter+Downloads", - "filename": "cloudrouter-centos-cloud-minimal.raw", - "filesize": 10737418240, - "md5sum": "8d982a37a49bc446a0edc59cefcadcdb", - "version": "4.0 Minimal" - }, - { - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/cloudrouter-init-gns3.iso/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "cloudrouter-init-gns3.iso", - "filesize": 374784, - "md5sum": "8cfb7e338bf241cc64abc084243e9be1", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "CloudRouter", - "port_name_format": "eth{0}", - "product_name": "CloudRouter", - "product_url": "https://cloudrouter.org/about/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 16, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default credentials: cloudrouter / gns3", - "vendor_name": "CloudRouter Community", - "vendor_url": "https://cloudrouter.org/", - "versions": [ - { - "images": { - "cdrom_image": "cloudrouter-init-gns3.iso", - "hda_disk_image": "cloudrouter-centos-cloud-full.raw" - }, - "name": "4.0 Full" - }, - { - "images": { - "cdrom_image": "cloudrouter-init-gns3.iso", - "hda_disk_image": "cloudrouter-centos-cloud-minimal.raw" - }, - "name": "4.0 Minimal" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "CoreOS is designed for security, consistency, and reliability. Instead of installing packages via yum or apt, CoreOS uses Linux containers to manage your services at a higher level of abstraction. A single service's code and all dependencies are packaged within a container that can be run on one or many CoreOS machines.", - "documentation_url": "https://coreos.com/docs/", - "images": [ - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1520.8.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1520.8.0/", - "filename": "coreos_production_qemu_image.1520.8.0.img", - "filesize": 842661888, - "md5sum": "a69fb2cd3ae475f9afbc268f7d391e83", - "version": "1520.8.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1465.7.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1465.7.0/", - "filename": "coreos_production_qemu_image.1465.7.0.img", - "filesize": 796590080, - "md5sum": "1db77d47e76d3d9082846584e0f4b4bc", - "version": "1465.7.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1409.7.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1409.7.0/", - "filename": "coreos_production_qemu_image.1409.7.0.img", - "filesize": 812187648, - "md5sum": "b8db4a07bac71468ed47bd09bedc1bdf", - "version": "1409.7.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1353.8.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1353.8.0/", - "filename": "coreos_production_qemu_image.1353.8.0.img", - "filesize": 795934720, - "md5sum": "f84bf924d7b30190539a14e14d94d4f8", - "version": "1353.8.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1353.7.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1353.7.0/", - "filename": "coreos_production_qemu_image.1353.7.0.img", - "filesize": 796852224, - "md5sum": "2d4ecc377b41ee5b1ffd90090548ebc0", - "version": "1353.7.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.9.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1235.9.0/", - "filename": "coreos_production_qemu_image.1235.9.0.img", - "filesize": 795869184, - "md5sum": "77a256ceaa0da6960391c03ebfe5388c", - "version": "1235.9.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.8.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1235.8.0/", - "filename": "coreos_production_qemu_image.1235.8.0.img", - "filesize": 785252352, - "md5sum": "0eec78690fd9f6d3b9e8d8ff41bc10b5", - "version": "1235.8.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.6.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1235.6.0/", - "filename": "coreos_production_qemu_image.1235.6.0.img", - "filesize": 784990208, - "md5sum": "2ff81c223be4bfa40c9ef765bb0d7f26", - "version": "1235.6.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.5.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1235.5.0/", - "filename": "coreos_production_qemu_image.1235.5.0.img", - "filesize": 792592384, - "md5sum": "11aa05a27654b66a4e6dfb1e9f1c7ff9", - "version": "1235.5.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1235.4.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1235.4.0/", - "filename": "coreos_production_qemu_image.1235.4.0.img", - "filesize": 787415040, - "md5sum": "c59930b3b1ad0716c91a62ac56234d97", - "version": "1235.4.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1185.5.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1185.5.0/", - "filename": "coreos_production_qemu_image.1185.5.0.img", - "filesize": 754843648, - "md5sum": "97b6eaa9857c68c67e56d7b742d43f5e", - "version": "1185.5.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1185.3.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/1185.3.0/", - "filename": "coreos_production_qemu_image.1185.3.0.img", - "filesize": 753926144, - "md5sum": "a1b6b69e5a58a1900b145b024340eff0", - "version": "1185.3.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://stable.release.core-os.net/amd64-usr/835.9.0/coreos_production_qemu_image.img.bz2", - "download_url": "http://stable.release.core-os.net/amd64-usr/835.9.0/", - "filename": "coreos_production_qemu_image.835.9.img", - "filesize": 635633664, - "md5sum": "768a5df35784a014ba06609da88f5158", - "version": "835.9.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "CoreOS", - "product_name": "CoreOS", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 1, - "arch": "x86_64", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdd_disk_interface": "ide", - "kvm": "allow", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "vendor_name": "CoreOS, Inc", - "vendor_url": "https://coreos.com/", - "versions": [ - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1520.8.0.img" - }, - "name": "1520.8.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1465.7.0.img" - }, - "name": "1465.7.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1409.7.0.img" - }, - "name": "1409.7.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1353.8.0.img" - }, - "name": "1353.8.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1353.7.0.img" - }, - "name": "1353.7.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1235.9.0.img" - }, - "name": "1235.9.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1235.8.0.img" - }, - "name": "1235.8.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1235.6.0.img" - }, - "name": "1235.6.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1235.5.0.img" - }, - "name": "1235.5.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1235.4.0.img" - }, - "name": "1235.4.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1185.5.0.img" - }, - "name": "1185.5.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.1185.3.0.img" - }, - "name": "1185.3.0" - }, - { - "images": { - "hda_disk_image": "coreos_production_qemu_image.835.9.img" - }, - "name": "835.9.0" - } - ] - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "Cumulus VX is a community-supported virtual appliance that enables cloud admins and network engineers to preview and test Cumulus Networks technology at zero cost. You can build sandbox environments to learn Open Networking concepts, prototype network operations and script & develop applications risk-free. With Cumulus VX, you can get started with Open Networking at your pace, on your time, and in your environment!", - "documentation_url": "http://docs.cumulusnetworks.com/", - "first_port_name": "eth0", - "images": [ - { - "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.4.3-vx-amd64.qcow2", - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.4.3-vx-amd64.qcow2", - "filesize": 988872704, - "md5sum": "fd9144cdab7cac66cf421a13c6f50ac8", - "version": "3.4.3" - }, - { - "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.4.2-vx-amd64.qcow2", - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.4.2-vx-amd64.qcow2", - "filesize": 1060700160, - "md5sum": "ca844684784ceeee893d0cd76dc44e3b", - "version": "3.4.2" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.4.1-vx-amd64.qcow2", - "filesize": 975503360, - "md5sum": "38319aa04533d91b1121a02f6ed99993", - "version": "3.4.1" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.4.0-vx-amd64.qcow2", - "filesize": 918355968, - "md5sum": "d93a15072bc7f8d15268f5e43f735a5e", - "version": "3.4.0" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.3.2-vx-amd64.qcow2", - "filesize": 980090880, - "md5sum": "8364f93cabaa442c13c8c6752a248a5d", - "version": "3.3.2" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.2.1-vx-amd64-1486153138.ac46c24zd00d13e.qcow2", - "filesize": 1232601088, - "md5sum": "145519af273d7f21ee1845780de7dce3", - "version": "3.2.1" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.2.0-vx-amd64-1481684769.ac46c24z090952a.qcow2", - "filesize": 1217593344, - "md5sum": "4cd6cee606483d4403d3329a72697ca4", - "version": "3.2.0" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.1.2-vx-amd64-1478059878.e1f18b3zacdc5c1.qcow2", - "filesize": 1291911168, - "md5sum": "e25d4dde0d2d5378a469380bd1d8d082", - "version": "3.1.2" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.1.1-vx-amd64-1474681409.bd4e10cz3c4e23f.qcow2", - "filesize": 1230372864, - "md5sum": "ad7688721417f167ea3537e60feac3da", - "version": "3.1.1" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.1.0-vx-amd64-1471979027.dc7e2adza017cfb.qcow2", - "filesize": 1190789120, - "md5sum": "6a68b8c8ef45c7227e80009e9920729c", - "version": "3.1.0" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.0.1-vx-amd64-1468215109.5d83176z20fa23d.qcow2", - "filesize": 1284112384, - "md5sum": "9f312bf4de1b410ce48e26b38f3bef48", - "version": "3.0.1" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "cumulus-linux-3.0.0-vx-amd64-1464279382.a8e7985zf0f5ad5.qcow2", - "filesize": 1237581824, - "md5sum": "ef23948870b77bb1373b9f06de4e7742", - "version": "3.0.0" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "CumulusVX-2.5.5-cc665123486ac43d.qcow2", - "filesize": 1092550656, - "md5sum": "e0cad2491d47f859828703a0b50cf633", - "version": "2.5.5" - }, - { - "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "filename": "CumulusVX-2.5.3-4eb681f3df86c478.qcow2", - "filesize": 1040973824, - "md5sum": "5128aec2568991ea0586293cb85f7a97", - "version": "2.5.3" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Cumulus VX", - "port_name_format": "swp{port1}", - "product_name": "Cumulus VX", - "product_url": "https://cumulusnetworks.com/cumulus-vx/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 7, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "ram": 512 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default username is cumulus and password is CumulusLinux!", - "vendor_name": "Cumulus Network", - "vendor_url": "https://www.cumulusnetworks.com", - "versions": [ - { - "images": { - "hda_disk_image": "cumulus-linux-3.4.3-vx-amd64.qcow2" - }, - "name": "3.4.3" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.4.2-vx-amd64.qcow2" - }, - "name": "3.4.2" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.4.1-vx-amd64.qcow2" - }, - "name": "3.4.1" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.4.0-vx-amd64.qcow2" - }, - "name": "3.4.0" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.3.2-vx-amd64.qcow2" - }, - "name": "3.3.2" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.2.1-vx-amd64-1486153138.ac46c24zd00d13e.qcow2" - }, - "name": "3.2.1" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.2.0-vx-amd64-1481684769.ac46c24z090952a.qcow2" - }, - "name": "3.2.0" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.1.2-vx-amd64-1478059878.e1f18b3zacdc5c1.qcow2" - }, - "name": "3.1.2" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.1.1-vx-amd64-1474681409.bd4e10cz3c4e23f.qcow2" - }, - "name": "3.1.1" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.1.0-vx-amd64-1471979027.dc7e2adza017cfb.qcow2" - }, - "name": "3.1.0" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.0.1-vx-amd64-1468215109.5d83176z20fa23d.qcow2" - }, - "name": "3.0.1" - }, - { - "images": { - "hda_disk_image": "cumulus-linux-3.0.0-vx-amd64-1464279382.a8e7985zf0f5ad5.qcow2" - }, - "name": "3.0.0" - }, - { - "images": { - "hda_disk_image": "CumulusVX-2.5.5-cc665123486ac43d.qcow2" - }, - "name": "2.5.5" - }, - { - "images": { - "hda_disk_image": "CumulusVX-2.5.3-4eb681f3df86c478.qcow2" - }, - "name": "2.5.3" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "DEFT (acronym for Digital Evidence & Forensics Toolkit) is a distribution made for Computer Forensics, with the purpose of running live on systems without tampering or corrupting devices (hard disks, pendrives, etc\u2026) connected to the PC where the boot process takes place.\nThe DEFT system is based on GNU Linux, it can run live (via DVDROM or USB pendrive), installed or run as a Virtual Appliance on VMware or Virtualbox. DEFT employs LXDE as desktop environment and WINE for executing Windows tools under Linux. It features a comfortable mount manager for device management.\nDEFT is paired with DART (acronym for Digital Advanced Response Toolkit), a Forensics System which can be run on Windows and contains the best tools for Forensics and Incident Response. DART features a GUI with logging and integrity check for the instruments here contained.\nBesides all this, the DEFT staff is devoted to implementing and developing applications which are released to Law Enforcement Officers, such as Autopsy 3 for Linux.", - "documentation_url": "http://www.deftlinux.net/deft-manual/", - "images": [ - { - "direct_download_url": "http://na.mirror.garr.it/mirrors/deft/deft-8.2.iso", - "download_url": "http://www.deftlinux.net/download/", - "filename": "deft-8.2.iso", - "filesize": 3317876736, - "md5sum": "8a70f61507251355153cbe94809323dd", - "version": "8.2" - }, - { - "direct_download_url": "http://na.mirror.garr.it/mirrors/deft/deft-8.1.iso", - "download_url": "http://www.deftlinux.net/download/", - "filename": "deft-8.1.iso", - "filesize": 3267639296, - "md5sum": "76bad80c7ea1552c9bd97bcca5de8d50", - "version": "8.1" - }, - { - "direct_download_url": "http://na.mirror.garr.it/mirrors/deft/deft-8.0.iso", - "download_url": "http://www.deftlinux.net/download/", - "filename": "deft-8.0.iso", - "filesize": 2898477056, - "md5sum": "fcedb54176de7a3018adfa7571a3a626", - "version": "8.0" - }, - { - "direct_download_url": "http://na.mirror.garr.it/mirrors/deft/deft-7.2.iso", - "download_url": "http://www.deftlinux.net/download/", - "filename": "deft-7.2.iso", - "filesize": 2695090176, - "md5sum": "1ea8ec6a2d333d0f0a64656bdf595a28", - "version": "7.2" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "DEFT Linux", - "product_name": "DEFT Linux", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "x86_64", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "usage": "You can run the LiveCD or install to the local disk. Default root password: deft", - "vendor_name": "DEFT Association", - "vendor_url": "http://www.deftlinux.net/", - "versions": [ - { - "images": { - "cdrom_image": "deft-8.2.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "8.2" - }, - { - "images": { - "cdrom_image": "deft-8.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "8.1" - }, - { - "images": { - "cdrom_image": "deft-8.0.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "8.0" - }, - { - "images": { - "cdrom_image": "deft-7.2.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "7.2" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Dell Networking OS10 combines the best of Linux, open computing and networking to advance open networking disaggregation. Dell Networking OS10 is a transformational software platform that provides networking hardware abstraction through a common set of APIs. Enable consistency across compute and network resources for your system operators (SysOps) groups that require server-like manageability. Easily leverage your existing network configuration. Dell Networking OS10 incorporates traditional networking integration. Enhance the integration and control you allow your development and operations (DevOps) teams, down to identifying an object as an individual, manageable entity within the platform.", - "first_port_name": "Management0/0", - "images": [ - { - "compression": "zip", - "download_url": "https://www.force10networks.com/csportal20/Software/Downloads.aspx", - "filename": "FTOS-SI-9.8.0.0.iso", - "filesize": 108115968, - "md5sum": "b9b50eda0a73407dc381792ff7975e24", - "version": "9.8.0" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Dell FTOS", - "port_name_format": "fortyGigE0/{0}", - "product_name": "Dell FTOS", - "product_url": "http://www.dell.com/us/business/p/open-platform-software/pd", - "qemu": { - "adapter_type": "e1000", - "adapters": 6, - "arch": "i386", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "ide", - "kvm": "require", - "ram": 512 - }, - "registry_version": 3, - "status": "experimental", - "usage": "Abort the BCM process and format the flash after first boot by entering these commands:\nen\nformat flash:\n\nSometimes the flash device is not available after boot.", - "vendor_name": "Dell Inc.", - "vendor_url": "http://www.dell.com/", - "versions": [ - { - "images": { - "cdrom_image": "FTOS-SI-9.8.0.0.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.8.0" - } - ] - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "ExtremeXOS was designed from the ground up to meet the needs of large cloud and private data centers, service providers, intelligent, converged enterprise edge networks, and everything in between. It provides the high performance and rich features required by these diverse environments.", - "documentation_url": "http://www.extremenetworks.com/support/documentation", - "first_port_name": "Management", - "images": [ - { - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.2.1.5.iso", - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "filename": "exosvm-22.2.1.5.iso", - "filesize": 44578816, - "md5sum": "bf51fd5b3c5e9dab10a616055265bcf2", - "version": "22.2.1.5" - }, - { - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.1.1.5.iso", - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "filename": "exosvm-22.1.1.5.iso", - "filesize": 44220416, - "md5sum": "df3897ca2d7c7053582587ed120114fa", - "version": "22.1.1.5" - }, - { - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/vm-21.1.2.14.iso?raw=true", - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "filename": "exosvm-21.1.2.14.iso", - "filesize": 41101312, - "md5sum": "de0752d56e41d92027ce1fccd604b14b", - "version": "21.1.2.14" - }, - { - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/vm-21.1.1.4.iso?raw=true", - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "filename": "exosvm-21.1.1.4.iso", - "filesize": 41046016, - "md5sum": "4d5db0e01a39b08775ed6a3e2c8bf663", - "version": "21.1.1.4" - }, - { - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.2.1.6.iso?raw=true", - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "filename": "exospc-16.2.1.6.iso", - "filesize": 36306944, - "md5sum": "b4be339afb02c03dcb4349630c1adb4f", - "version": "16.2.1.6" - }, - { - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.1.3.6.iso?raw=true", - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "filename": "exospc-16.1.3.6.iso", - "filesize": 35758080, - "md5sum": "4c17b2bf2a4909527f6c866a68ba406e", - "version": "16.1.3.6" - }, - { - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.1.2.14.iso?raw=true", - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "filename": "exospc-16.1.2.14.iso", - "filesize": 35743744, - "md5sum": "140cdc11f426156ffcbde150b2f46768", - "version": "16.1.2.14" - }, - { - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty8G.qcow2", - "filesize": 197120, - "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "EXOS", - "port_name_format": "Port{port1}", - "product_name": "EXOS", - "product_url": "http://www.extremenetworks.com/product/extremexos-network-operating-system", - "qemu": { - "adapter_type": "e1000", - "adapters": 13, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "telnet", - "hda_disk_interface": "ide", - "kvm": "require", - "options": "-smp 2 -cpu core2duo", - "ram": 256 - }, - "registry_version": 3, - "status": "stable", - "usage": "You can change the console to telnet after install. Default user: admin (no password set)", - "vendor_name": "Extreme Networks", - "vendor_url": "http://www.extremenetworks.com/", - "versions": [ - { - "images": { - "cdrom_image": "exosvm-22.2.1.5.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "22.2.1.5" - }, - { - "images": { - "cdrom_image": "exosvm-22.1.1.5.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "22.1.1.5" - }, - { - "images": { - "cdrom_image": "exosvm-21.1.2.14.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "21.1.2.14" - }, - { - "images": { - "cdrom_image": "exosvm-21.1.1.4.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "21.1.1.4" - }, - { - "images": { - "cdrom_image": "exospc-16.2.1.6.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "16.2.1.6" - }, - { - "images": { - "cdrom_image": "exospc-16.1.3.6.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "16.1.3.6" - }, - { - "images": { - "cdrom_image": "exospc-16.1.2.14.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "16.1.2.14" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "The BIG-IP family of products offers the application intelligence that network managers need to ensure applications are fast, secure, and available. All BIG-IP products share a common underlying architecture, F5's Traffic Management Operating System (TMOS), which provides unified intelligence, flexibility, and programmability. Together, BIG-IP's powerful platforms, advanced modules, and centralized management system make up the most comprehensive set of application delivery tools in the industry. BIG-IP Virtual Edition (VE) is a version of the BIG-IP system that runs as a virtual machine in specifically-supported hypervisors. BIG-IP VE emulates a hardware-based BIG-IP system running a VE-compatible version of BIG-IP software.", - "documentation_url": "https://support.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/bigip-ve-kvm-setup-11-3-0.html", - "images": [ - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v13.x/13.0.0/english/virtual-edition_base-plus-hf2/&sw=BIG-IP&pro=big-ip_v13.x&ver=13.0.0&container=Virtual-Edition_Base-Plus-HF2&file=BIGIP-13.0.0.2.0.1671.LTM.qcow2.zip", - "filename": "BIGIP-13.0.0.2.0.1671.qcow2", - "filesize": 4435476480, - "md5sum": "62d27f37c66118710c69c07a2ee78d67", - "version": "13.0.0 HF2" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v13.x/13.0.0/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v13.x&ver=13.0.0&container=Virtual-Edition&file=BIGIP-13.0.0.0.0.1645.ALL.qcow2.zip", - "filename": "BIGIP-13.0.0.0.0.1645.qcow2", - "filesize": 3833135104, - "md5sum": "4ec417477c44cdf84edc825a631990e3", - "version": "13.0.0" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.2/english/virtual-edition_base-plus-hf1/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.2&container=Virtual-Edition_Base-Plus-HF1&file=BIGIP-12.1.2.1.0.271.LTM.qcow2.zip", - "filename": "BIGIP-12.1.2.1.0.271.LTM.qcow2", - "filesize": 3764846592, - "md5sum": "b34301c3945b7ddb88f41195efef1104", - "version": "12.1.2 HF1" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.2/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.2&container=Virtual-Edition&file=BIGIP-12.1.2.0.0.249.LTM.qcow2.zip", - "filename": "BIGIP-12.1.2.0.0.249.qcow2", - "filesize": 3196649472, - "md5sum": "f3aa2d51d82fa3f5a4fa10005a378e16", - "version": "12.1.2" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.1/english/virtual-edition_base-plus-hf2/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.1&container=Virtual-Edition_Base-Plus-HF2&file=BIGIP-12.1.1.2.0.204.LTM.qcow2.zip", - "filename": "BIGIP-12.1.1.2.0.204.qcow2", - "filesize": 3563716608, - "md5sum": "74d4d21db3579efb9011a1829a2124b7", - "version": "12.1.1 HF2" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.0/english/virtual-edition_base-plus-hf1/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.0&container=Virtual-Edition_Base-Plus-HF1&file=BIGIP-12.1.0.1.0.1447.ALL.qcow2.zip", - "filename": "BIGIP-12.1.0.1.0.1447.qcow2", - "filesize": 3503226880, - "md5sum": "15725ba2c72a0fe932985e695f0f3f1f", - "version": "12.1.0 HF1" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.0.0/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.0.0&container=Virtual-Edition&file=BIGIP-12.0.0.0.0.606.ALL.qcow2.zip", - "filename": "BIGIP-12.0.0.0.0.606.qcow2", - "filesize": 3152609280, - "md5sum": "8f578d697554841f003afd1e2965df7e", - "version": "12.0.0" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v11.x/11.6.1/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v11.x&ver=11.6.1&container=Virtual-Edition&file=BIGIP-11.6.1.0.0.317.ALL.qcow2.zip", - "filename": "BIGIP-11.6.1.0.0.317.qcow2", - "filesize": 2824273920, - "md5sum": "01a2939840d81458bfef0a5c53fb74be", - "version": "11.6.1" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v11.x/11.6.0/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v11.x&ver=11.6.0&container=Virtual-Edition&file=BIGIP-11.6.0.0.0.401.ALL.qcow2.zip", - "filename": "BIGIP-11.6.0.0.0.401.qcow2", - "filesize": 2851733504, - "md5sum": "87723dc8c9713a36bde9a650b94205e3", - "version": "11.6.0" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v11.x/11.3.0/english/virtual-edition-trial/&sw=BIG-IP&pro=big-ip_v11.x&ver=11.3.0&container=Virtual-Edition-Trial&file=BIGIP-11.3.0.39.0.qcow2.zip", - "filename": "BIGIP-11.3.0.39.0.qcow2", - "filesize": 1842020352, - "md5sum": "f3dec4565484fe81233077ab2ce426ae", - "version": "11.3.0" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty100G.qcow2", - "filesize": 198656, - "md5sum": "1e6409a4523ada212dea2ebc50e50a65", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "F5 BIG-IP LTM VE", - "port_name_format": "1.{port1}", - "product_name": "F5 BIG-IP LTM VE", - "product_url": "https://f5.com/products/modules/local-traffic-manager", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 8, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "require", - "options": "-smp 2 -cpu host", - "ram": 4096 - }, - "registry_version": 3, - "status": "stable", - "symbol": "loadbalancer.svg", - "usage": "Console credentials: root/default. WebUI credentials: admin/admin. The boot process might take a few minutes without providing any output to the console. Please be patient (or set console to vnc to see tty outputs).\n\nIn case the 'localhost emerg logger: Re-starting chmand' log appears on the console, you can find the solution here: https://devcentral.f5.com/questions/big-ip-ltm-ve-on-kvm", - "vendor_name": "F5", - "vendor_url": "http://www.f5.com/", - "versions": [ - { - "images": { - "hda_disk_image": "BIGIP-13.0.0.2.0.1671.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "13.0.0 HF2" - }, - { - "images": { - "hda_disk_image": "BIGIP-13.0.0.0.0.1645.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "13.0.0" - }, - { - "images": { - "hda_disk_image": "BIGIP-12.1.2.1.0.271.LTM.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "12.1.2 HF1" - }, - { - "images": { - "hda_disk_image": "BIGIP-12.1.2.0.0.249.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "12.1.2" - }, - { - "images": { - "hda_disk_image": "BIGIP-12.1.1.2.0.204.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "12.1.1 HF2" - }, - { - "images": { - "hda_disk_image": "BIGIP-12.1.0.1.0.1447.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "12.1.0 HF1" - }, - { - "images": { - "hda_disk_image": "BIGIP-12.0.0.0.0.606.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "12.0.0" - }, - { - "images": { - "hda_disk_image": "BIGIP-11.6.1.0.0.317.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "11.6.1" - }, - { - "images": { - "hda_disk_image": "BIGIP-11.6.0.0.0.401.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "11.6.0" - }, - { - "images": { - "hda_disk_image": "BIGIP-11.3.0.39.0.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "11.3.0" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "When you go from managing a few boxes to managing a few dozen, your processes, logistics, and needs all change. BIG-IQ Centralized Management brings all of your devices together, so you can discover, track, upgrade, and deploy more efficiently. You can also monitor key metrics from one location, saving yourself both time and effort.\n\nCentrally manage up to 200 physical, virtual, or virtual clustered multiprocessing (vCMP) based BIG-IP devices. BIG-IQ Centralized Management also handles licensing for up to 5,000 unmanaged devices, so you can spin BIG-IP virtual editions (VEs) up or down as needed.", - "documentation_url": "https://support.f5.com/csp/#/knowledge-center/software/BIG-IQ?module=BIG-IQ%20Centralized%20Management", - "first_port_name": "mgmt", - "images": [ - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.3.0/english/v5.3.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.3.0&container=v5.3.0&file=BIG-IQ-5.3.0.0.0.1119.qcow2.zip", - "filename": "BIG-IQ-5.3.0.0.0.1119.qcow2", - "filesize": 3269263360, - "md5sum": "75f06ba59f858c3828d47dcf8caf3775", - "version": "5.3.0" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.2.0/english/v5.2.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.2.0&container=v5.2.0&file=BIG-IQ-5.2.0.0.0.5741.qcow2.zip", - "filename": "BIG-IQ-5.2.0.0.0.5741.qcow2", - "filesize": 3256352768, - "md5sum": "c40d9724fb6c15ef0ee949437a9558db", - "version": "5.2.0" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.1.0/english/v5.1.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.1.0&container=v5.1.0&file=BIG-IQ-5.1.0.0.0.631.qcow2.zip", - "filename": "BIG-IQ-5.1.0.0.0.631.qcow2", - "filesize": 2335440896, - "md5sum": "f8f52d9ef56c6bdd0a0604f1b50b81c6", - "version": "5.1.0" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.0.0/english/v5.0.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.0.0&container=v5.0.0&file=BIG-IQ-5.0.0.0.0.3026.qcow2.zip", - "filename": "BIG-IQ-5.0.0.0.0.3026.qcow2", - "filesize": 2301820928, - "md5sum": "072194d6eb052ee083cf8cef9e7a87d6", - "version": "5.0.0" - }, - { - "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.0.0/english/v5.0.0/&sw=BIG-IQ&pro=big-iq_CM&ver=5.0.0&container=v5.0.0&file=BIG-IQ-5.0.0.0.0.3026.qcow2.zip", - "filename": "BIG-IQ-5.x.DATASTOR.LTM.qcow2", - "filesize": 393216, - "md5sum": "c7f82b8834436eb67b7d619767ac7476", - "version": "5.x" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty100G.qcow2", - "filesize": 198656, - "md5sum": "1e6409a4523ada212dea2ebc50e50a65", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "F5 BIG-IQ CM", - "port_name_format": "1.{port1}", - "product_name": "F5 BIG-IQ CM", - "product_url": "https://f5.com/products/big-iq-centralized-management", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "hdd_disk_interface": "virtio", - "kvm": "require", - "options": "-smp 2 -cpu host", - "ram": 4096 - }, - "registry_version": 3, - "status": "stable", - "symbol": "mgmt_station.svg", - "usage": "Console credentials: root/default\nWebUI credentials: admin/admin\nThe boot process might take a few minutes without providing any output to the console. Please be patient (or set console to vnc to see tty outputs).", - "vendor_name": "F5", - "vendor_url": "http://www.f5.com/", - "versions": [ - { - "images": { - "hda_disk_image": "BIG-IQ-5.3.0.0.0.1119.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "5.3.0" - }, - { - "images": { - "hda_disk_image": "BIG-IQ-5.2.0.0.0.5741.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "5.2.0" - }, - { - "images": { - "hda_disk_image": "BIG-IQ-5.1.0.0.0.631.qcow2", - "hdb_disk_image": "empty100G.qcow2", - "hdd_disk_image": "BIG-IQ-5.x.DATASTOR.LTM.qcow2" - }, - "name": "5.1.0" - }, - { - "images": { - "hda_disk_image": "BIG-IQ-5.0.0.0.0.3026.qcow2", - "hdb_disk_image": "empty100G.qcow2", - "hdd_disk_image": "BIG-IQ-5.x.DATASTOR.LTM.qcow2" - }, - "name": "5.0.0" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "A light Linux based on TinyCore Linux with Firefox preinstalled", - "documentation_url": "https://support.mozilla.org", - "images": [ - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-tinycore-linux-6.4-firefox-33.1.1-2.img", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "linux-tinycore-linux-6.4-firefox-33.1.1-2.img", - "filesize": 93257728, - "md5sum": "8db0d8dc890797cc335ceb8aaf2255f0", - "version": "31.1.1~2" - }, - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-tinycore-linux-6.4-firefox-33.1.1.img", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "linux-tinycore-linux-6.4-firefox-33.1.1.img", - "filesize": 82313216, - "md5sum": "9e51ad24dc25c4a26f7a8fb99bc77830", - "version": "31.1.1~1" - } - ], - "maintainer": "GNS3 team", - "maintainer_email": "developers@gns3.net", - "name": "Firefox", - "product_name": "Firefox", - "product_url": "https://www.mozilla.org/firefox", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "i386", - "console_type": "vnc", - "kvm": "allow", - "options": "-vga std -usbdevice tablet", - "ram": 256 - }, - "registry_version": 3, - "status": "stable", - "symbol": "firefox.svg", - "vendor_name": "Mozilla Foundation", - "vendor_url": "http://www.mozilla.org", - "versions": [ - { - "images": { - "hda_disk_image": "linux-tinycore-linux-6.4-firefox-33.1.1-2.img" - }, - "name": "31.1.1~2" - }, - { - "images": { - "hda_disk_image": "linux-tinycore-linux-6.4-firefox-33.1.1.img" - }, - "name": "31.1.1~1" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Fortinet ADC appliances optimize the availability, user experience, and scalability of enterprise application delivery. They deliver fast, secure, and intelligent acceleration and distribution of even the most demanding enterprise applications.", - "documentation_url": "http://docs.fortinet.com/fortiadc-d-series/admin-guides", - "images": [ - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2", - "filesize": 30998528, - "md5sum": "b7500835594e62d8acb1c6ec43d597c1", - "version": "4.x.x" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0977-FORTINET.out.kvm-boot.qcow2", - "filesize": 72876032, - "md5sum": "285ca7a601a0d06bb893ef91ad7748fd", - "version": "4.8.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0970-FORTINET.out.kvm-boot.qcow2", - "filesize": 72351744, - "md5sum": "8f604b2a89ac3d9cc3d2d79d85b2d7ff", - "version": "4.8.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0937-FORTINET.out.kvm-boot.qcow2", - "filesize": 72089600, - "md5sum": "448f5906c42dd7e535c3acb2adab253c", - "version": "4.8.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0858-FORTINET.out.kvm-boot.qcow2", - "filesize": 63700992, - "md5sum": "6d81b1b3df55174e4db8526d6cfd8b0e", - "version": "4.7.4" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0849-FORTINET.out.kvm-boot.qcow2", - "filesize": 64028672, - "md5sum": "c85f49cd320fdca36e71c0d7cdc26f8c", - "version": "4.7.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0844-FORTINET.out.kvm-boot.qcow2", - "filesize": 63963136, - "md5sum": "6f035cda6138af993153ef322231a201", - "version": "4.7.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0832-FORTINET.out.kvm-boot.qcow2", - "filesize": 67960832, - "md5sum": "70577d11ae77ce765cae944f3a7c3941", - "version": "4.7.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0828-FORTINET.out.kvm-boot.qcow2", - "filesize": 67960832, - "md5sum": "4a0bf9d4ad29628ca08a1638662a43a6", - "version": "4.7.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0679-FORTINET.out.kvm-boot.qcow2", - "filesize": 82903040, - "md5sum": "31147f42b54ce8e9c953dea519a4b9a6", - "version": "4.6.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0677-FORTINET.out.kvm-boot.qcow2", - "filesize": 82837504, - "md5sum": "2a9c32c7b32807f4dc384ed6e2082802", - "version": "4.6.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0660-FORTINET.out.kvm-boot.qcow2", - "filesize": 82509824, - "md5sum": "50cc9bc44409180f7106e4201b2dae2a", - "version": "4.6.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-V400-build0605-FORTINET.out.kvm-boot.qcow2", - "filesize": 48168960, - "md5sum": "d415bc621bf0abc2b5aa32c03390e11f", - "version": "4.5.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-v400-build0597-FORTINET.out.kvm-boot.qcow2", - "filesize": 66584576, - "md5sum": "47a905193e8f9ddc25be71aeccccc7b9", - "version": "4.5.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-v400-build0581-FORTINET.out.kvm-boot.qcow2", - "filesize": 67305472, - "md5sum": "bfc93d5881dda3f0a3123f54665bdcf0", - "version": "4.5.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAD_KVM-v400-build0560-FORTINET.out.kvm-boot.qcow2", - "filesize": 68026368, - "md5sum": "7a71f52bde93c0000b047626731b7aef", - "version": "4.5.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiADC", - "port_name_format": "Port{port1}", - "product_name": "FortiADC", - "product_url": "https://www.fortinet.com/products-services/products/application-delivery-controllers/fortiadc.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 10, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "allow", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "Default username is admin, no password is set. Silent boot, it might take a while.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0977-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.8.2" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0970-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.8.1" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0937-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.8.0" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0858-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.7.4" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0849-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.7.3" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0844-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.7.2" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0832-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.7.1" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0828-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.7.0" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0679-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.6.2" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0677-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.6.1" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0660-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.6.0" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-V400-build0605-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.5.3" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-v400-build0597-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.5.2" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-v400-build0581-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.5.1" - }, - { - "images": { - "hda_disk_image": "FAD_KVM-v400-build0560-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" - }, - "name": "4.5.0" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "FortiAnalyzer Network Security Logging, Analysis, and Reporting Appliances securely aggregate log data from Fortinet Security Appliances. A comprehensive suite of easily customable reports allows you to quickly analyze and visualize network threats, inefficiencies and usage.", - "documentation_url": "http://docs.fortinet.com/fortianalyzer/", - "images": [ - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build1557-FORTINET.out.kvm.qcow2", - "filesize": 106905600, - "md5sum": "6aa0a185723efcab464aa298b364d12b", - "version": "5.6.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build1225-FORTINET.out.kvm.qcow2", - "filesize": 88715264, - "md5sum": "69cddb5c3e49bab3dc287353d8600b45", - "version": "5.4.4" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build1187-FORTINET.out.kvm.qcow2", - "filesize": 86036480, - "md5sum": "4f9fa1e7dbfa9187a4cb479458144596", - "version": "5.4.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build1151-FORTINET.out.kvm.qcow2", - "filesize": 85651456, - "md5sum": "c4f7bf355c7483f23edd4f6bf34bc602", - "version": "5.4.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build1082-FORTINET.out.kvm.qcow2", - "filesize": 81580032, - "md5sum": "e9bae3fc7195200f659178060968c7c4", - "version": "5.4.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build1019-FORTINET.out.kvm.qcow2", - "filesize": 66256896, - "md5sum": "72530309422616a1a1478fa0c78fbb08", - "version": "5.4.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build0786-FORTINET.out.kvm.qcow2", - "filesize": 55238656, - "md5sum": "b9553e0f1cfc875d2121c840a1fafebc", - "version": "5.2.10" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build0780-FORTINET.out.kvm.qcow2", - "filesize": 55042048, - "md5sum": "e79581adb9ac36913823f0119a1c8da8", - "version": "5.2.9" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build0777-FORTINET.out.kvm.qcow2", - "filesize": 55361536, - "md5sum": "9a061657c3fdac9e9b631621a100cdc8", - "version": "5.2.8" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAZ_VM64_KVM-v5-build0760-FORTINET.out.kvm.qcow2", - "filesize": 55070720, - "md5sum": "a349f4d9f4f12e8963e3b471357dcbb6", - "version": "5.2.7" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiAnalyzer", - "port_name_format": "Port{port1}", - "product_name": "FortiAnalyzer", - "product_url": "https://www.fortinet.com/products-services/products/management-reporting/fortianalyzer.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "allow", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "Default username is admin, no password is set.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build1557-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.6.0" - }, - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build1225-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.4" - }, - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build1187-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.3" - }, - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build1151-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.2" - }, - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build1082-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.1" - }, - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build1019-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.0" - }, - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build0786-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.10" - }, - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build0780-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.9" - }, - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build0777-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.8" - }, - { - "images": { - "hda_disk_image": "FAZ_VM64_KVM-v5-build0760-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.7" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "FortiAuthenticator user identity management appliances strengthen enterprise security by simplifying and centralizing the management and storage of user identity information.", - "documentation_url": "http://docs.fortinet.com/fortiauthenticator/admin-guides", - "images": [ - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAC_VM_KVM-v500-build0091-FORTINET.out.kvm.qcow2", - "filesize": 71135232, - "md5sum": "7bdafd32db552954c4c7fe60296fc600", - "version": "5.1.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAC_VM_KVM-v500-build0086-FORTINET.out.kvm.qcow2", - "filesize": 71819264, - "md5sum": "960017582fe16e7ce7ab9602600e65fe", - "version": "5.1.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAC_VM_KVM-v500-build0083-FORTINET.out.kvm.qcow2", - "filesize": 72495104, - "md5sum": "eec53c2dbe5d00c8ce2a7ca50226325a", - "version": "5.1.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAC_VM_KVM-v500-build0012-FORTINET.out.kvm.qcow2", - "filesize": 62771200, - "md5sum": "2af90bdad68a37f38fda39ee04cf2fba", - "version": "5.0.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FAC_VM_KVM-v500-DATADRIVE.qcow2", - "filesize": 258048, - "md5sum": "09bad6cfe6301930adbc829eb8a67149", - "version": "5.x.x" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiAuthenticator", - "port_name_format": "Port{port1}", - "product_name": "FortiAuthenticator", - "product_url": "https://www.fortinet.com/products/identity-access-management/fortiauthenticator.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "allow", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "Default username is admin, no password is set. First book takes longer.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FAC_VM_KVM-v500-build0091-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" - }, - "name": "5.1.2" - }, - { - "images": { - "hda_disk_image": "FAC_VM_KVM-v500-build0086-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" - }, - "name": "5.1.1" - }, - { - "images": { - "hda_disk_image": "FAC_VM_KVM-v500-build0083-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" - }, - "name": "5.1.0" - }, - { - "images": { - "hda_disk_image": "FAC_VM_KVM-v500-build0012-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" - }, - "name": "5.0.0" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "FortiCache VM high performance Web Caching virtual appliances address bandwidth saturation, high latency, and poor performance caused by caching popular internet content locally for carriers, service providers, enterprises and educational networks. FortiCache VM appliances reduce the cost and impact of cached content on the network, while increasing performance and end- user satisfaction by improving the speed of delivery of popular repeated content.", - "documentation_url": "http://docs.fortinet.com/forticache/admin-guides", - "images": [ - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FCHKVM-v400-build0213-FORTINET.out.kvm.qcow2", - "filesize": 27508736, - "md5sum": "78db88447f29f363b4ba8e4833474637", - "version": "4.2.5" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FCHKVM-v400-build0204-FORTINET.out.kvm.qcow2", - "filesize": 27623424, - "md5sum": "8f0aad31131add43ac6bf709dd708970", - "version": "4.2.4" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FCHKVM-v400-build0200-FORTINET.out.kvm.qcow2", - "filesize": 27467776, - "md5sum": "7ec6c4c4e4ba7976793769422550fc30", - "version": "4.2.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FCHKVM-v400-build0127-FORTINET.out.kvm.qcow2", - "filesize": 26087424, - "md5sum": "c607391c3aaaa014e9cec8c61354485b", - "version": "4.1.6" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FCHKVM-v400-build0123-FORTINET.out.kvm.qcow2", - "filesize": 25845760, - "md5sum": "f6d161636528ecee87243174c51e56e7", - "version": "4.1.5" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FCHKVM-v400-build0119-FORTINET.out.kvm.qcow2", - "filesize": 25825280, - "md5sum": "d2c8236768e795eb80114e5c5f4dfac9", - "version": "4.1.4" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FCHKVM-v400-build0112-FORTINET.out.kvm.qcow2", - "filesize": 25812992, - "md5sum": "554ebdf8874753b275c2f1ed9104e081", - "version": "4.1.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FCHKVM-v400-build0109-FORTINET.out.kvm.qcow2", - "filesize": 25829376, - "md5sum": "c54246365b3d3f03c9ff2184127695ea", - "version": "4.1.2" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty100G.qcow2", - "filesize": 198656, - "md5sum": "1e6409a4523ada212dea2ebc50e50a65", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiCache", - "port_name_format": "Port{port1}", - "product_name": "FortiCache", - "product_url": "https://www.fortinet.com/products-services/products/wan-appliances/forticache.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 3, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "ide", - "hdb_disk_interface": "ide", - "kvm": "require", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "Default username is admin, no password is set.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FCHKVM-v400-build0213-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "4.2.5" - }, - { - "images": { - "hda_disk_image": "FCHKVM-v400-build0204-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "4.2.4" - }, - { - "images": { - "hda_disk_image": "FCHKVM-v400-build0200-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "4.2.3" - }, - { - "images": { - "hda_disk_image": "FCHKVM-v400-build0127-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "4.1.6" - }, - { - "images": { - "hda_disk_image": "FCHKVM-v400-build0123-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "4.1.5" - }, - { - "images": { - "hda_disk_image": "FCHKVM-v400-build0119-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "4.1.4" - }, - { - "images": { - "hda_disk_image": "FCHKVM-v400-build0112-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "4.1.3" - }, - { - "images": { - "hda_disk_image": "FCHKVM-v400-build0109-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "4.1.2" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "FortiGate Virtual Appliance offers the same level of advanced threat prevention features like the physical appliances in private, hybrid and public cloud deployment.", - "documentation_url": "http://docs.fortinet.com/p/inside-fortios", - "images": [ - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build1486-FORTINET.out.kvm.qcow2", - "filesize": 39231488, - "md5sum": "afb9f237de2545db8663f4a2c5805355", - "version": "5.6.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build1484-FORTINET.out.kvm.qcow2", - "filesize": 39227392, - "md5sum": "6f76d1207b9f6cb724f8034f57711705", - "version": "5.6.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build1449-FORTINET.out.kvm.qcow2", - "filesize": 38760448, - "md5sum": "17ee2cc8c76c4928a68a2d016aa83ace", - "version": "5.6.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build1165-FORTINET.out.kvm.qcow2", - "filesize": 38457344, - "md5sum": "4429f1f0f2cce4a8781354a9eb745c61", - "version": "5.4.6" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build1138-FORTINET.out.kvm.qcow2", - "filesize": 38096896, - "md5sum": "66c6f6a4b12f0223dd2997b199067e67", - "version": "5.4.5" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build7605-FORTINET.out.kvm.qcow2", - "filesize": 37761024, - "md5sum": "2602fd0c79dd1a69c14b0b46121c875e", - "version": "5.4.4" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build1111-FORTINET.out.kvm.qcow2", - "filesize": 38141952, - "md5sum": "576f95dd7809dd24440fee147252177f", - "version": "5.4.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build1100-FORTINET.out.kvm.qcow2", - "filesize": 37789696, - "md5sum": "9ec360c4ffc0811cdecf3d74b152bc14", - "version": "5.4.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build1064-FORTINET.out.kvm.qcow2", - "filesize": 37715968, - "md5sum": "441ca5fae1aff9a42fdcaaf8aceb731c", - "version": "5.4.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build1011-FORTINET.out.kvm.qcow2", - "filesize": 35373056, - "md5sum": "22fc2bdca456dfe3027ad48dff370352", - "version": "5.4.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build0754-FORTINET.out.kvm.qcow2", - "filesize": 35069952, - "md5sum": "b6cdab6a8240e89f50c0448cf0b711ea", - "version": "5.2.11" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build0742-FORTINET.out.kvm.qcow2", - "filesize": 34779136, - "md5sum": "21fc2bab23a42faa9dc6dcb1a4b180aa", - "version": "5.2.10" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build0736-FORTINET.out.kvm.qcow2", - "filesize": 34590720, - "md5sum": "89cd0883798beed4841dd300f69e462a", - "version": "5.2.9" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build0727-FORTINET.out.kvm.qcow2", - "filesize": 34508800, - "md5sum": "ae7597450893bc60722ef7a787f0a925", - "version": "5.2.8" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build0718-FORTINET.out.kvm.qcow2", - "filesize": 34439168, - "md5sum": "1c59a521885c465004456f74d003726c", - "version": "5.2.7" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FGT_VM64_KVM-v5-build0701-FORTINET.out.kvm.qcow2", - "filesize": 33902592, - "md5sum": "c4d2cbe51669796e48623e006782f7dc", - "version": "5.2.5" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiGate", - "port_name_format": "Port{port1}", - "product_name": "FortiGate", - "product_url": "http://www.fortinet.com/products/fortigate/virtual-appliances.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 10, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "allow", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "Default username is admin, no password is set.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build1486-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.6.2" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build1484-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.6.1" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build1449-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.6.0" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build1165-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.6" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build1138-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.5" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build7605-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.4" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build1111-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.3" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build1100-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.2" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build1064-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.1" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build1011-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.0" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build0754-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.11" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build0742-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.10" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build0736-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.9" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build0727-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.8" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build0718-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.7" - }, - { - "images": { - "hda_disk_image": "FGT_VM64_KVM-v5-build0701-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.5" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "FortiMail is a complete Secure Email Gateway offering suitable for any size organization. It provides a single solution to protect against inbound attacks - including advanced malware -, as well as outbound threats and data loss with a wide range of top-rated security capabilities.", - "documentation_url": "http://docs.fortinet.com/fortimail/admin-guides", - "images": [ - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v54-build0707-FORTINET.out.kvm.qcow2", - "filesize": 92864512, - "md5sum": "b51260cc3e408bf1352a204b8370254b", - "version": "5.4.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v54-build0704-FORTINET.out.kvm.qcow2", - "filesize": 94568448, - "md5sum": "1f6553e182512cc87e20f47cc2b65abf", - "version": "5.4.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v54-build0692-FORTINET.out.kvm.qcow2", - "filesize": 101253120, - "md5sum": "c9e0885cab65e52ab01d8143ed466b01", - "version": "5.4.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0648-FORTINET.out.kvm.qcow2", - "filesize": 88670208, - "md5sum": "bd34a81c1bb6772c7e4919620027a5d4", - "version": "5.3.11" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0643-FORTINET.out.kvm.qcow2", - "filesize": 88801280, - "md5sum": "08f3258533ac2b4f15e86ca3973be17e", - "version": "5.3.10" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0634-FORTINET.out.kvm.qcow2", - "filesize": 86376448, - "md5sum": "a66b82f0713ba4ea418bd959d0cb5732", - "version": "5.3.9" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0627-FORTINET.out.kvm.qcow2", - "filesize": 86769664, - "md5sum": "83108e5cb68bad681b68ec1ef7e29f25", - "version": "5.3.8" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0623-FORTINET.out.kvm.qcow2", - "filesize": 86573056, - "md5sum": "7e208d04c3f9bc4dedcf6d45e8d99a76", - "version": "5.3.7" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0621-FORTINET.out.kvm.qcow2", - "filesize": 86638592, - "md5sum": "3fe1521b73af886359d78eb4c1509466", - "version": "5.3.6" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0618-FORTINET.out.kvm.qcow2", - "filesize": 86376448, - "md5sum": "5f4159956b87538c008654c030e00e37", - "version": "5.3.5" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0608-FORTINET.out.kvm.qcow2", - "filesize": 86048768, - "md5sum": "b78f647148923e1bddfa2dcfbcc0c85c", - "version": "5.3.4" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0599-FORTINET.out.kvm.qcow2", - "filesize": 84606976, - "md5sum": "f1f3ae5593029d4fc0a5024bcf786cc7", - "version": "5.3.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FML_VMKV-64-v53-build0593-FORTINET.out.kvm.qcow2", - "filesize": 84541440, - "md5sum": "0447819ed4aa382ea6871c0cb913b592", - "version": "5.3.2" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiMail", - "port_name_format": "Port{port1}", - "product_name": "FortiMail", - "product_url": "http://www.fortinet.com/products/fortimail/index.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "allow", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "First boot takes a few minutes. Admin URL is https://x.x.x.x/admin, default username is admin, no password is set.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FML_VMKV-64-v54-build0707-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.2" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v54-build0704-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.1" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v54-build0692-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.0" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0648-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.11" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0643-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.10" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0634-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.9" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0627-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.8" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0623-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.7" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0621-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.6" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0618-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.5" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0608-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.4" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0599-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.3" - }, - { - "images": { - "hda_disk_image": "FML_VMKV-64-v53-build0593-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.3.2" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "FortiManager Security Management appliances allow you to centrally manage any number of Fortinet Network Security devices, from several to thousands, including FortiGate, FortiWiFi, and FortiCarrier.", - "documentation_url": "http://docs.fortinet.com/p/inside-fortios", - "images": [ - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build1557-FORTINET.out.kvm.qcow2", - "filesize": 108363776, - "md5sum": "f8bd600796f894f4ca1ea2d6b4066d3d", - "version": "5.6.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build1225-FORTINET.out.kvm.qcow2", - "filesize": 89911296, - "md5sum": "53bc6e320fe7bde5d2b636bde95a910c", - "version": "5.4.4" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build1187-FORTINET.out.kvm.qcow2", - "filesize": 87425024, - "md5sum": "53602c776d215d98e32163a10804fc49", - "version": "5.4.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build1151-FORTINET.out.kvm.qcow2", - "filesize": 86437888, - "md5sum": "8e131ad40009c740f3efdee6dc3a0ac3", - "version": "5.4.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build1082-FORTINET.out.kvm.qcow2", - "filesize": 83124224, - "md5sum": "fc1815410f3f0536e2e3a9c1c5c07f41", - "version": "5.4.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build1019-FORTINET.out.kvm.qcow2", - "filesize": 77541376, - "md5sum": "1cfb22671cb372d8bf3e47b9c3c55ded", - "version": "5.4.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build0786-FORTINET.out.kvm.qcow2", - "filesize": 64962560, - "md5sum": "377fe38bf07bc2435608e5b65f780f07", - "version": "5.2.10" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build0780-FORTINET.out.kvm.qcow2", - "filesize": 65007616, - "md5sum": "04268e779d3d5e6c928c6fd638423c52", - "version": "5.2.9" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build0777-FORTINET.out.kvm.qcow2", - "filesize": 65011712, - "md5sum": "6dbf148ace9bf309ad383757afd75fad", - "version": "5.2.8" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FMG_VM64_KVM-v5-build0757-FORTINET.out.kvm.qcow2", - "filesize": 65056768, - "md5sum": "d37dbaa49d7522324681eeba19f7699b", - "version": "5.2.7" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiManager", - "port_name_format": "Port{port1}", - "product_name": "FortiManager", - "product_url": "http://www.fortinet.com/products/fortimanager/virtual-security-management.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "allow", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "Default username is admin, no password is set.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build1557-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.6.0" - }, - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build1225-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.4" - }, - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build1187-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.3" - }, - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build1151-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.2" - }, - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build1082-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.1" - }, - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build1019-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.4.0" - }, - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build0786-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.10" - }, - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build0780-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.9" - }, - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build0777-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.8" - }, - { - "images": { - "hda_disk_image": "FMG_VM64_KVM-v5-build0757-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "5.2.7" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "Today's threats are increasingly sophisticated and often bypass traditional malware security by masking their malicious activity. A sandbox augments your security architecture by validating threats in a separate, secure environment. FortiSandbox offers a powerful combination of advanced detection, automated mitigation, actionable insight, and flexible deployment to stop targeted attacks and subsequent data loss. It's also a key component of our Advanced Threat Protection solution.", - "documentation_url": "http://docs.fortinet.com/fortisandbox/admin-guides", - "images": [ - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FSA_KVM-v200-build0261-FORTINET.out.kvm.qcow2", - "filesize": 98763264, - "md5sum": "6551ccca8ffe6333742dad54770a01cd", - "version": "2.4.1" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FSA_KVM-v200-build0252-FORTINET.out.kvm.qcow2", - "filesize": 99811840, - "md5sum": "47a4489e617f165b92fd8dda68e00bf2", - "version": "2.4.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FSA_KVM-v200-build0205-FORTINET.out.kvm.qcow2", - "filesize": 94962176, - "md5sum": "1ecb0acf1604bdeee0beb1b75864ca99", - "version": "2.3.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FSA_KVM-v200-build0195-FORTINET.out.kvm.qcow2", - "filesize": 115868160, - "md5sum": "00147d048c8002c98aa55d73f022204d", - "version": "2.3.2" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FSA_VM-v200-build0183-FORTINET.out.kvm.qcow2", - "filesize": 118226944, - "md5sum": "2ff03862e33c8a826a0bce10be12f45e", - "version": "2.3.0" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FSA_v200-datadrive.qcow2", - "filesize": 200192, - "md5sum": "f2dc0a8fc7591699c364aff400369157", - "version": "2.x" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiSandbox", - "port_name_format": "Port{port1}", - "product_name": "FortiSandbox", - "product_url": "https://www.fortinet.com/products/sandbox/fortisandbox.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 3, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "require", - "options": "-smp 2", - "ram": 8096 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "First boot will take some time without console output. Default username is admin, no password is set.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FSA_KVM-v200-build0261-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" - }, - "name": "2.4.1" - }, - { - "images": { - "hda_disk_image": "FSA_KVM-v200-build0252-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" - }, - "name": "2.4.0" - }, - { - "images": { - "hda_disk_image": "FSA_KVM-v200-build0205-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" - }, - "name": "2.3.3" - }, - { - "images": { - "hda_disk_image": "FSA_KVM-v200-build0195-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" - }, - "name": "2.3.2" - }, - { - "images": { - "hda_disk_image": "FSA_VM-v200-build0183-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" - }, - "name": "2.3.0" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Breaches to network security continue to occur across all industry verticals, even to the most respected brands. The time it takes to discover, isolate, and remediate the incident continues to be measured in hundreds of days-having material impacts on security and compliance standards. It is no wonder that many organizations are struggling. As recent surveys have shown, enterprises have an average of 32 different vendors' devices in their network, with no automated ability to cross-correlate the data that each is collecting. It is also easy to see why organizations are strapped for the cyber security personnel they need to manage all the data in these complex environments.\n\nFrom its inception, FortiSIEM was built to reduce complexity in managing network and security operations. FortiSIEM provides organizations of all sizes with a comprehensive, holistic, and scalable solution for managing security, performance, and compliance from IoT to the cloud.", - "documentation_url": "http://docs.fortinet.com/fortisiem/admin-guides", - "images": [ - { - "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", - "filename": "FortiSIEM-VA-KVM-4.10.0.1102.qcow2", - "filesize": 8622505984, - "md5sum": "636d94c78ea02e5a39eadb9d44210dfb", - "version": "4.10.0" - }, - { - "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", - "filename": "FortiSIEM-VA-KVM-4.10.0.1102-1.qcow2", - "filesize": 46858240, - "md5sum": "52fee02e94fd220275b613a4ec5b46eb", - "version": "4.10.0" - }, - { - "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", - "filename": "FortiSIEM-VA-KVM-4.10.0.1102-2.qcow2", - "filesize": 46858240, - "md5sum": "088a34864e30abdb95385b089574baba", - "version": "4.10.0" - }, - { - "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", - "filename": "FortiSIEM-VA-KVM-4.9.0.1041.qcow2", - "filesize": 8484487168, - "md5sum": "c2db828b6985297b33833f376c5106b0", - "version": "4.9.0" - }, - { - "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", - "filename": "FortiSIEM-VA-KVM-4.9.0.1041-1.qcow2", - "filesize": 46858240, - "md5sum": "b3f0cd44995f37648aa429303eeeb455", - "version": "4.9.0" - }, - { - "download_url": "https://www.fortinet.com/offers/fortisiem-free-trial.html", - "filename": "FortiSIEM-VA-KVM-4.9.0.1041-2.qcow2", - "filesize": 46858240, - "md5sum": "70a8abb4253d5bb724ded3b33a8385c4", - "version": "4.9.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiSIEM", - "port_name_format": "Port{port1}", - "product_name": "FortiSIEM", - "product_url": "https://www.fortinet.com/products/siem/fortisiem.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "hdc_disk_interface": "virtio", - "kvm": "require", - "options": "-smp 4", - "ram": 16384 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "This is the Super/Worker component. Default credentials:\n- admin / admin*1\n - root / ProspectHills\n\nIf you get a 503 error on the WebUI, run /opt/phoenix/deployment/jumpbox/phinitsuper as root.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FortiSIEM-VA-KVM-4.10.0.1102.qcow2", - "hdb_disk_image": "FortiSIEM-VA-KVM-4.10.0.1102-1.qcow2", - "hdc_disk_image": "FortiSIEM-VA-KVM-4.10.0.1102-2.qcow2" - }, - "name": "4.10.0" - }, - { - "images": { - "hda_disk_image": "FortiSIEM-VA-KVM-4.9.0.1041.qcow2", - "hdb_disk_image": "FortiSIEM-VA-KVM-4.9.0.1041-1.qcow2", - "hdc_disk_image": "FortiSIEM-VA-KVM-4.9.0.1041-2.qcow2" - }, - "name": "4.9.0" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "FortiWeb Web Application Firewalls provide specialized, layered web application threat protection for medium/large enterprises, application service providers, and SaaS providers.", - "documentation_url": "http://docs.fortinet.com/fortiweb", - "images": [ - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FWB_KVM-v500-build0739-FORTINET.out.kvm-log.qcow2", - "filesize": 7602176, - "md5sum": "d42225723d2e2ee0160f101c5b9663d5", - "version": "5.5.4" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FWB_KVM-v500-FORTINET.out.kvm-log.qcow2", - "filesize": 7602176, - "md5sum": "b90cd0a382cb09db31cef1d0cdf7d6e9", - "version": "5.5.2 - 5.5.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FWB_KVM-v500-build0739-FORTINET.out.kvm-boot.qcow2", - "filesize": 87228416, - "md5sum": "a11b91efacce70212b6b9e1f9916cc3e", - "version": "5.5.4" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FWB_KVM-v500-build0730-FORTINET.out.kvm-boot.qcow2", - "filesize": 87228416, - "md5sum": "12ebec432a54900e6c63540af8ebfbb4", - "version": "5.5.3" - }, - { - "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx", - "filename": "FWB_KVM-v500-build0723-FORTINET.out.kvm-boot.qcow2", - "filesize": 87162880, - "md5sum": "0a613191948d3618ae16cd9f11988448", - "version": "5.5.2" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FortiWeb", - "port_name_format": "Port{port1}", - "product_name": "FortiWeb", - "product_url": "http://www.fortinet.com/products/fortiweb/index.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "allow", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "symbol": "fortinet.svg", - "usage": "Default username is admin, no password is set. Console keeps sending 'access uuid file failed, error number 2' messages; ignore it.", - "vendor_name": "Fortinet", - "vendor_url": "http://www.fortinet.com/", - "versions": [ - { - "images": { - "hda_disk_image": "FWB_KVM-v500-build0739-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FWB_KVM-v500-build0739-FORTINET.out.kvm-log.qcow2" - }, - "name": "5.5.4" - }, - { - "images": { - "hda_disk_image": "FWB_KVM-v500-build0730-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FWB_KVM-v500-FORTINET.out.kvm-log.qcow2" - }, - "name": "5.5.3" - }, - { - "images": { - "hda_disk_image": "FWB_KVM-v500-build0723-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FWB_KVM-v500-FORTINET.out.kvm-log.qcow2" - }, - "name": "5.5.2" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "FreeBSD is an advanced computer operating system used to power modern servers, desktops, and embedded platforms. A large community has continually developed it for more than thirty years. Its advanced networking, security, and storage features have made FreeBSD the platform of choice for many of the busiest web sites and most pervasive embedded networking and storage devices.", - "documentation_url": "https://www.freebsd.org/docs.html", - "images": [ - { - "compression": "xz", - "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/11.1-RELEASE/amd64/Latest/FreeBSD-11.1-RELEASE-amd64.qcow2.xz", - "download_url": "https://www.freebsd.org/where.html", - "filename": "FreeBSD-11.1-RELEASE-amd64.qcow2", - "filesize": 1533345792, - "md5sum": "d78b2a7d05ec62f799e14ded4817ea69", - "version": "11.1" - }, - { - "compression": "xz", - "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/11.0-RELEASE/amd64/Latest/FreeBSD-11.0-RELEASE-amd64.qcow2.xz", - "download_url": "https://www.freebsd.org/where.html", - "filename": "FreeBSD-11.0-RELEASE-amd64.qcow2", - "filesize": 1384382464, - "md5sum": "1b04999198f492afd6dc4935b8c7cc22", - "version": "11.0" - }, - { - "compression": "xz", - "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/10.4-RELEASE/amd64/Latest/FreeBSD-10.4-RELEASE-amd64.qcow2.xz", - "download_url": "https://www.freebsd.org/where.html", - "filename": "FreeBSD-10.4-RELEASE-amd64.qcow2", - "filesize": 1013448704, - "md5sum": "ad498873733c57d1f6d890d587a11e3c", - "version": "10.4" - }, - { - "compression": "xz", - "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/10.3-RELEASE/amd64/Latest/FreeBSD-10.3-RELEASE-amd64.qcow2.xz", - "download_url": "https://www.freebsd.org/where.html", - "filename": "FreeBSD-10.3-RELEASE-amd64.qcow2", - "filesize": 974651392, - "md5sum": "1a00cebef520dfac8d2bda10ea16a951", - "version": "10.3" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FreeBSD", - "port_name_format": "em{0}", - "product_name": "FreeBSD", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 256 - }, - "registry_version": 3, - "status": "stable", - "usage": "User: root, not password is set.", - "vendor_name": "FreeBSD", - "vendor_url": "http://www.freebsd.org", - "versions": [ - { - "images": { - "hda_disk_image": "FreeBSD-11.1-RELEASE-amd64.qcow2" - }, - "name": "11.1" - }, - { - "images": { - "hda_disk_image": "FreeBSD-11.0-RELEASE-amd64.qcow2" - }, - "name": "11.0" - }, - { - "images": { - "hda_disk_image": "FreeBSD-10.4-RELEASE-amd64.qcow2" - }, - "name": "10.4" - }, - { - "images": { - "hda_disk_image": "FreeBSD-10.3-RELEASE-amd64.qcow2" - }, - "name": "10.3" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "FreeNAS is a Free and Open Source Network Attached Storage (NAS) software appliance. This means that you can use FreeNAS to share data over file-based sharing protocols, including CIFS for Windows users, NFS for Unix-like operating systems, and AFP for Mac OS X users. FreeNAS uses the ZFS file system to store, manage, and protect data. ZFS provides advanced features like snapshots to keep old versions of files, incremental remote backups to keep your data safe on another device without huge file transfers, and intelligent compression, which reduces the size of files so quickly and efficiently that it actually helps transfers happen faster.", - "documentation_url": "https://doc.freenas.org/9.10/freenas.html", - "images": [ - { - "direct_download_url": "http://download.freenas.org/11/11.0-U4/x64/FreeNAS-11.0-U4.iso", - "download_url": "http://www.freenas.org/download/", - "filename": "FreeNAS-11.0-U4.iso", - "filesize": 567312384, - "md5sum": "4c210f1a6510d1fa95257d81ef569ff8", - "version": "11.0-U4" - }, - { - "direct_download_url": "https://download.freenas.org/9.10/STABLE/latest/x64/FreeNAS-9.10.1-U4.iso", - "download_url": "http://www.freenas.org/download/", - "filename": "FreeNAS-9.10.1-U4.iso", - "filesize": 533098496, - "md5sum": "b4fb14513dcbb4eb4c5596c5911ca9cc", - "version": "9.10" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "FreeNAS", - "port_name_format": "eth{0}", - "product_name": "FreeNAS", - "product_url": "http://www.openfiler.com/products", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "ide", - "hdb_disk_interface": "ide", - "kvm": "require", - "ram": 8096 - }, - "registry_version": 3, - "status": "stable", - "vendor_name": "iXsystems", - "vendor_url": "http://www.freenas.org", - "versions": [ - { - "images": { - "cdrom_image": "FreeNAS-11.0-U4.iso", - "hda_disk_image": "empty30G.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "11.0" - }, - { - "images": { - "cdrom_image": "FreeNAS-9.10.1-U4.iso", - "hda_disk_image": "empty30G.qcow2", - "hdb_disk_image": "empty30G.qcow2" - }, - "name": "9.10" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "The HP VSR1000 Virtual Services Router Series is a software application, running on a server, which provides functionality similar to that of a physical router: robust routing between networked devices using a number of popular routing protocols. It also delivers the critical network services associated with today's enterprise routers such as VPN gateway, firewall and other security and traffic management functions.\n\nThe virtual services router (VSR) application runs on a hypervqcor on the server, and supports VMware vSphere and Linux KVM hypervqcors. From one to eight virtual CPUs are supported, depending on license.\n\nBecause the VSR1000 Series application runs the same HP Comware version 7 operating system as HP switches and routers, it enables significant operational savings. And being virtual, additional agility and ease of deployment is realized, as resources on the VSR can be dynamically allocated and upgraded upon demand as performance requirements grow.\n\nA variety of deployment models are supported including enterprise branch CPE routing, and cloud offload for small to medium workloads.", - "documentation_url": "http://h20195.www2.hpe.com/v2/default.aspx?cc=us&lc=en&oid=5443878", - "images": [ - { - "download_url": "https://h10145.www1.hp.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=22702&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=", - "filename": "VSR1000_HPE-CMW710-R0327L01-X64.qco", - "filesize": 138739712, - "md5sum": "907de5140a4a029afe1c517cfc27ecde", - "version": "7.10.R0327L01" - }, - { - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=", - "filename": "VSR1000_HPE-CMW710-R0326-X64.qco", - "filesize": 138412032, - "md5sum": "4153d638bfa72ca72a957ea8682ad0e2", - "version": "7.10.R0326" - }, - { - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=", - "filename": "VSR1000_HPE-CMW710-E0325-X64.qco", - "filesize": 111738880, - "md5sum": "a6731f3af86bee9b209a8b342be6bf75", - "version": "7.10.E0325" - }, - { - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=", - "filename": "VSR1000_HPE-CMW710-E0518-X64.qco", - "filesize": 201588736, - "md5sum": "4991436442ae706df8041c69778a48df", - "version": "7.10.E0518" - }, - { - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=", - "filename": "VSR1000_HPE-CMW710-E0324-X64.qco", - "filesize": 111411200, - "md5sum": "7a0ff32281284c042591c6181426effd", - "version": "7.10.E0324" - }, - { - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=", - "filename": "VSR1000_HPE-CMW710-E0322P01-X64.qco", - "filesize": 110428160, - "md5sum": "0aa2dbe5910fa64eb8c623e083b21a5e", - "version": "7.10.E0322P01" - }, - { - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=", - "filename": "VSR1000_HPE-CMW710-E0322-X64.qco", - "filesize": 113770496, - "md5sum": "05e0dab6b7aa489f627448b4d79b1f50", - "version": "7.10.E0322" - }, - { - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=", - "filename": "VSR1000_HPE-CMW710-E0321P01-X64.qco", - "filesize": 113639424, - "md5sum": "26d4375fafeedc81f298f29f593de252", - "version": "7.10.E0321P01" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "HPE VSR1001", - "port_name_format": "GE{port1}/0", - "product_name": "VSR1001", - "product_url": "https://www.hpe.com/us/en/product-catalog/networking/networking-routers/pip.hpe-flexnetwork-vsr1000-virtual-services-router-series.5443163.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 16, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "vendor_name": "HPE", - "vendor_url": "http://www.hpe.com", - "versions": [ - { - "images": { - "hda_disk_image": "VSR1000_HPE-CMW710-R0327L01-X64.qco" - }, - "name": "7.10.R0327L01" - }, - { - "images": { - "hda_disk_image": "VSR1000_HPE-CMW710-R0326-X64.qco" - }, - "name": "7.10.R0326" - }, - { - "images": { - "hda_disk_image": "VSR1000_HPE-CMW710-E0325-X64.qco" - }, - "name": "7.10.E0325" - }, - { - "images": { - "hda_disk_image": "VSR1000_HPE-CMW710-E0518-X64.qco" - }, - "name": "7.10.E0518" - }, - { - "images": { - "hda_disk_image": "VSR1000_HPE-CMW710-E0324-X64.qco" - }, - "name": "7.10.E0324" - }, - { - "images": { - "hda_disk_image": "VSR1000_HPE-CMW710-E0322P01-X64.qco" - }, - "name": "7.10.E0322P01" - }, - { - "images": { - "hda_disk_image": "VSR1000_HPE-CMW710-E0322-X64.qco" - }, - "name": "7.10.E0322" - }, - { - "images": { - "hda_disk_image": "VSR1000_HPE-CMW710-E0321P01-X64.qco" - }, - "name": "7.10.E0321P01" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "This appliance simulate a domestic modem. It provide an IP via DHCP and will nat all connection to the internet without the need of using a cloud interface in your topologies. IP will be in the subnet 172.16.0.0/16. Multiple internet will have different IP range from 172.16.1.0/24 to 172.16.253.0/24 .\n\nWARNING USE IT ONLY WITH THE GNS3 VM.", - "documentation_url": "http://www.gns3.com", - "images": [ - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/core-linux-6.4-internet-0.1.img", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "core-linux-6.4-internet-0.1.img", - "filesize": 16711680, - "md5sum": "8ebc5a6ec53a1c05b7aa101b5ceefe31", - "version": "0.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Internet", - "product_name": "Internet", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "i386", - "console_type": "telnet", - "kvm": "allow", - "options": "-device e1000,netdev=internet0 -netdev vde,sock=/var/run/vde2/qemu0.ctl,id=internet0", - "ram": 64 - }, - "registry_version": 3, - "status": "stable", - "symbol": ":/symbols/cloud.svg", - "usage": "Just connect stuff to the appliance. Everything is automated.", - "vendor_name": "GNS3", - "vendor_url": "http://www.gns3.com", - "versions": [ - { - "images": { - "hda_disk_image": "core-linux-6.4-internet-0.1.img" - }, - "name": "0.1" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "IPFire was designed with both modularity and a high-level of flexibility in mind. You can easily deploy many variations of it, such as a firewall, a proxy server or a VPN gateway. The modular design ensures that it runs exactly what you've configured it for and nothing more. Everything is simple to manage and update through the package manager, making maintenance a breeze.", - "documentation_url": "http://wiki.ipfire.org/en/start", - "images": [ - { - "compression": "gzip", - "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.19-core116/ipfire-2.19.1gb-ext4-scon.x86_64-full-core116.img.gz", - "download_url": "http://www.ipfire.org/download", - "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core116.img", - "filesize": 1063256064, - "md5sum": "2a8df99d117a0dbfb67870494c0c67cd", - "version": "2.19.116" - }, - { - "compression": "gzip", - "direct_download_url": "http://downloads.ipfire.org/releases/ipfire-2.x/2.19-core110/ipfire-2.19.1gb-ext4-scon.x86_64-full-core110.img.gz", - "download_url": "http://www.ipfire.org/download", - "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core111.img", - "filesize": 1063256064, - "md5sum": "741ab771cadd2f6a1fc4a85b3478ae5f", - "version": "2.19.111" - }, - { - "compression": "gzip", - "direct_download_url": "http://downloads.ipfire.org/releases/ipfire-2.x/2.19-core110/ipfire-2.19.1gb-ext4-scon.x86_64-full-core110.img.gz", - "download_url": "http://www.ipfire.org/download", - "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core110.img", - "filesize": 958398464, - "md5sum": "d91bdabee5db83d0f93573f88ea542b1", - "version": "2.19.110" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "IPFire", - "port_name_format": "eth{0}", - "product_name": "IPFire", - "product_url": "http://www.ipfire.org/features", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "allow", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "usage": "A config wizard will be started at first boot.", - "vendor_name": "IPFire Project", - "vendor_url": "http://www.ipfire.org/", - "versions": [ - { - "images": { - "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core116.img" - }, - "name": "2.19.116" - }, - { - "images": { - "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core111.img" - }, - "name": "2.19.111" - }, - { - "images": { - "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core110.img" - }, - "name": "2.19.110" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "ipterm is a debian based networking toolbox.\nIt contains the following utilities: net-tools, iproute2, ping, traceroute, curl, host, iperf3, mtr, socat, ssh client, tcpdump and the multicast testing tools msend/mreceive.", - "docker": { - "adapters": 1, - "image": "gns3/ipterm:latest" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "ipterm", - "product_name": "ipterm", - "registry_version": 3, - "status": "stable", - "symbol": "linux_guest.svg", - "usage": "The /root directory is persistent.", - "vendor_name": "ipterm", - "vendor_url": "https://www.debian.org" - }, - { - "builtin": true, - "category": "router", - "description": "The vMX is a full-featured, carrier-grade virtual MX Series 3D Universal Edge Router that extends 15+ years of Juniper Networks edge routing expertise to the virtual realm. This appliance is for the Virtual Control Plane (vCP) VM and is meant to be paired with the Virtual Forwarding Plane (vFP) VM.", - "documentation_url": "http://www.juniper.net/techpubs/", - "first_port_name": "fxp0", - "images": [ - { - "filename": "vcp_17.1R1.8-disk1.vmdk", - "filesize": 1065513984, - "md5sum": "2dba6dff363c0619903f85c3dedce8d8", - "version": "17.1R1.8-ESXi" - }, - { - "filename": "vcp_17.1R1.8-disk2.vmdk", - "filesize": 5928448, - "md5sum": "df7016f8b0fd456044425fa92566c129", - "version": "17.1R1.8-ESXi" - }, - { - "filename": "vcp_17.1R1.8-disk3.vmdk", - "filesize": 71680, - "md5sum": "e9460158e6e27f7885981ab562e60944", - "version": "17.1R1.8-ESXi" - }, - { - "filename": "junos-vmx-x86-64-17.1R1.8.qcow2", - "filesize": 1192296448, - "md5sum": "4434e70fedfec2ef205412236ae934a4", - "version": "17.1R1.8-KVM" - }, - { - "filename": "vmxhdd-17.1R1.img", - "filesize": 108986368, - "md5sum": "3634fa16219852d0dba46b2fb77d5969", - "version": "17.1R1.8-KVM" - }, - { - "filename": "metadata-usb-re-17.1R1.img", - "filesize": 16777216, - "md5sum": "e911911dc77e7fef1375e66ae98e41b8", - "version": "17.1R1.8-KVM" - }, - { - "filename": "vcp_16.2R1.6-disk1.vmdk", - "filesize": 1093272576, - "md5sum": "6407f6b448de3b45b86fccb4d586a977", - "version": "16.2R1.6-ESXi" - }, - { - "filename": "vcp_16.2R1.6-disk2.vmdk", - "filesize": 5928960, - "md5sum": "73db51629c009466d39f5d7fdf736224", - "version": "16.2R1.6-ESXi" - }, - { - "filename": "vcp_16.2R1.6-disk3.vmdk", - "filesize": 71680, - "md5sum": "6df61c10f25ea6279562e5a13342100d", - "version": "16.2R1.6-ESXi" - }, - { - "filename": "junos-vmx-x86-64-16.2R1.6.qcow2", - "filesize": 1217462272, - "md5sum": "61497595fb62a9d9805724a3e0a56fa0", - "version": "16.2R1.6-KVM" - }, - { - "filename": "vmxhdd-16.2R1.img", - "filesize": 108986368, - "md5sum": "ce75a16cf130d8744652c8f23d1d13ef", - "version": "16.2R1.6-KVM" - }, - { - "filename": "metadata-usb-re-16.2R1.img", - "filesize": 16777216, - "md5sum": "dded4a98c18ecc79daaa1d11dd0cfb2f", - "version": "16.2R1.6-KVM" - }, - { - "filename": "vcp_16.1R4.7-disk1.vmdk", - "filesize": 987702272, - "md5sum": "e438f48a34d6b8047e36994fb323a97b", - "version": "16.1R4.7-ESXi" - }, - { - "filename": "vcp_16.1R4.7-disk2.vmdk", - "filesize": 5929472, - "md5sum": "fb30d5afd182a03f36daaaf985e0d1ef", - "version": "16.1R4.7-ESXi" - }, - { - "filename": "vcp_16.1R4.7-disk3.vmdk", - "filesize": 71680, - "md5sum": "c185a44561890a4b6e84cea6b86ad92a", - "version": "16.1R4.7-ESXi" - }, - { - "filename": "junos-vmx-x86-64-16.1R4.7.qcow2", - "filesize": 1115815936, - "md5sum": "020db6733c158bd871bf28dcd7d039e9", - "version": "16.1R4.7-KVM" - }, - { - "filename": "vmxhdd-16.1R4.img", - "filesize": 108986368, - "md5sum": "97b86d9d69f9615fb97d50a8d4aecd97", - "version": "16.1R4.7-KVM" - }, - { - "filename": "metadata-usb-re-16.1R4.img", - "filesize": 16777216, - "md5sum": "fb200eec654e14201bfa0720b39a64f0", - "version": "16.1R4.7-KVM" - }, - { - "filename": "vcp_16.1R3.10-disk1.vmdk", - "filesize": 977419776, - "md5sum": "532ab7d63c1873e6e6e9b9b057eb83ec", - "version": "16.1R3.10-ESXi" - }, - { - "filename": "vcp_16.1R3.10-disk2.vmdk", - "filesize": 5928448, - "md5sum": "c563254a38c0d83c4bb9a866cae661f0", - "version": "16.1R3.10-ESXi" - }, - { - "filename": "vcp_16.1R3.10-disk3.vmdk", - "filesize": 71680, - "md5sum": "9c8f3a8f26ff418eb6a5acd4803a3ca2", - "version": "16.1R3.10-ESXi" - }, - { - "filename": "junos-vmx-x86-64-16.1R3.10.qcow2", - "filesize": 1105526784, - "md5sum": "f677c8235f579c54ee746daade5ee443", - "version": "16.1R3.10-KVM" - }, - { - "filename": "vmxhdd-16.1R3.img", - "filesize": 108986368, - "md5sum": "28626ce47bea74b7d92bb4e28fa85c93", - "version": "16.1R3.10-KVM" - }, - { - "filename": "metadata-usb-re-16.1R3.img", - "filesize": 16777216, - "md5sum": "b187253fa654a30a7dd0b331e2c6e6a4", - "version": "16.1R3.10-KVM" - }, - { - "filename": "vcp_16.1R2.11-disk1.vmdk", - "filesize": 970741248, - "md5sum": "20945c0114fa4f88cdbedd0551f62d8f", - "version": "16.1R2.11-ESXi" - }, - { - "filename": "vcp_16.1R2.11-disk2.vmdk", - "filesize": 5930496, - "md5sum": "904acd14a9eef0bdb60f18db63b8a653", - "version": "16.1R2.11-ESXi" - }, - { - "filename": "vcp_16.1R2.11-disk3.vmdk", - "filesize": 71680, - "md5sum": "f6f6c24c0f991faf93c45f1fbc2ed0ae", - "version": "16.1R2.11-ESXi" - }, - { - "filename": "junos-vmx-x86-64-16.1R2.11.qcow2", - "filesize": 1194065920, - "md5sum": "da443543eee6d7305a6851d38d0613ea", - "version": "16.1R2.11-KVM" - }, - { - "filename": "vmxhdd-16.1R2.img", - "filesize": 108986368, - "md5sum": "962c04d00d2b3272f40f3571d1305d6d", - "version": "16.1R2.11-KVM" - }, - { - "filename": "metadata-usb-re-16.1R2.img", - "filesize": 16777216, - "md5sum": "10f219a0b5d23553dbbf3a7ec1358a68", - "version": "16.1R2.11-KVM" - }, - { - "filename": "vcp_16.1R1.7-disk1.vmdk", - "filesize": 1067432448, - "md5sum": "0a97d16b7014be8e3ae270cc2028d10d", - "version": "16.1R1.7-ESXi" - }, - { - "filename": "vcp_16.1R1.7-disk2.vmdk", - "filesize": 5930496, - "md5sum": "e96972233a144b93aa9bcc321b2a215b", - "version": "16.1R1.7-ESXi" - }, - { - "filename": "vcp_16.1R1.7-disk3.vmdk", - "filesize": 71680, - "md5sum": "815af90310e6681204ba511d9659d2ad", - "version": "16.1R1.7-ESXi" - }, - { - "filename": "junos-vmx-x86-64-16.1R1.7.qcow2", - "filesize": 1194065920, - "md5sum": "f7b53cc04672a1abf7c0236a772cea51", - "version": "16.1R1.7-KVM" - }, - { - "filename": "vmxhdd-16.1R1.img", - "filesize": 108986368, - "md5sum": "c239c4de2a4cf902747c8fc300f08493", - "version": "16.1R1.7-KVM" - }, - { - "filename": "metadata-usb-re-16.1R1.img", - "filesize": 16777216, - "md5sum": "47e578bd41890272dcd5aa1e436068d4", - "version": "16.1R1.7-KVM" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "jinstall64-vmx-15.1F4.15-domestic.img", - "filesize": 1003945984, - "md5sum": "e6b2e1ad9cba5220aa764ae4dd008952", - "version": "15.1F4.15" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vmxhdd-15.1.img", - "filesize": 108986368, - "md5sum": "c3c7090ed3b1799e3de7579ac887e39d", - "version": "15.1F4.15" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "metadata-usb-15.1.img", - "filesize": 16777216, - "md5sum": "af48f7e03f94ffcfeecd15a59a4f1567", - "version": "15.1F4.15" - } - ], - "maintainer": "none", - "maintainer_email": "developers@gns3.net", - "name": "Juniper vMX vCP", - "port_name_format": "em{port1}", - "product_name": "Juniper vMX vCP", - "product_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "qemu": { - "adapter_type": "e1000", - "adapters": 2, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "options": "-nographic -enable-kvm", - "ram": 2048 - }, - "registry_version": 3, - "status": "experimental", - "symbol": "juniper-vmx.svg", - "usage": "Initial username is root, no password.\n\nUSAGE INSTRUCTIONS\n\nConnect the first interface (fxp0) to your admin VLAN. Connect the second interface (em1) directly to the second interface (eth1) of the vFP.", - "vendor_name": "Juniper", - "vendor_url": "https://www.juniper.net/us/en/", - "versions": [ - { - "images": { - "hda_disk_image": "vcp_17.1R1.8-disk1.vmdk", - "hdb_disk_image": "vcp_17.1R1.8-disk2.vmdk", - "hdc_disk_image": "vcp_17.1R1.8-disk3.vmdk" - }, - "name": "17.1R1.8-ESXi" - }, - { - "images": { - "hda_disk_image": "junos-vmx-x86-64-17.1R1.8.qcow2", - "hdb_disk_image": "vmxhdd-17.1R1.img", - "hdc_disk_image": "metadata-usb-re-17.1R1.img" - }, - "name": "17.1R1.8-KVM" - }, - { - "images": { - "hda_disk_image": "vcp_16.2R1.6-disk1.vmdk", - "hdb_disk_image": "vcp_16.2R1.6-disk2.vmdk", - "hdc_disk_image": "vcp_16.2R1.6-disk3.vmdk" - }, - "name": "16.2R1.6-ESXi" - }, - { - "images": { - "hda_disk_image": "junos-vmx-x86-64-16.2R1.6.qcow2", - "hdb_disk_image": "vmxhdd-16.2R1.img", - "hdc_disk_image": "metadata-usb-re-16.2R1.img" - }, - "name": "16.2R1.6-KVM" - }, - { - "images": { - "hda_disk_image": "vcp_16.1R4.7-disk1.vmdk", - "hdb_disk_image": "vcp_16.1R4.7-disk2.vmdk", - "hdc_disk_image": "vcp_16.1R4.7-disk3.vmdk" - }, - "name": "16.1R4.7-ESXi" - }, - { - "images": { - "hda_disk_image": "junos-vmx-x86-64-16.1R4.7.qcow2", - "hdb_disk_image": "vmxhdd-16.1R4.img", - "hdc_disk_image": "metadata-usb-re-16.1R4.img" - }, - "name": "16.1R4.7-KVM" - }, - { - "images": { - "hda_disk_image": "vcp_16.1R3.10-disk1.vmdk", - "hdb_disk_image": "vcp_16.1R3.10-disk2.vmdk", - "hdc_disk_image": "vcp_16.1R3.10-disk3.vmdk" - }, - "name": "16.1R3.10-ESXi" - }, - { - "images": { - "hda_disk_image": "junos-vmx-x86-64-16.1R3.10.qcow2", - "hdb_disk_image": "vmxhdd-16.1R3.img", - "hdc_disk_image": "metadata-usb-re-16.1R3.img" - }, - "name": "16.1R3.10-KVM" - }, - { - "images": { - "hda_disk_image": "vcp_16.1R2.11-disk1.vmdk", - "hdb_disk_image": "vcp_16.1R2.11-disk2.vmdk", - "hdc_disk_image": "vcp_16.1R2.11-disk3.vmdk" - }, - "name": "16.1R2.11-ESXi" - }, - { - "images": { - "hda_disk_image": "junos-vmx-x86-64-16.1R2.11.qcow2", - "hdb_disk_image": "vmxhdd-16.1R2.img", - "hdc_disk_image": "metadata-usb-re-16.1R2.img" - }, - "name": "16.1R2.11-KVM" - }, - { - "images": { - "hda_disk_image": "vcp_16.1R1.7-disk1.vmdk", - "hdb_disk_image": "vcp_16.1R1.7-disk2.vmdk", - "hdc_disk_image": "vcp_16.1R1.7-disk3.vmdk" - }, - "name": "16.1R1.7-ESXi" - }, - { - "images": { - "hda_disk_image": "junos-vmx-x86-64-16.1R1.7.qcow2", - "hdb_disk_image": "vmxhdd-16.1R1.img", - "hdc_disk_image": "metadata-usb-re-16.1R1.img" - }, - "name": "16.1R1.7-KVM" - }, - { - "images": { - "hda_disk_image": "jinstall64-vmx-15.1F4.15-domestic.img", - "hdb_disk_image": "vmxhdd-15.1.img", - "hdc_disk_image": "metadata-usb-15.1.img" - }, - "name": "15.1F4.15" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "The vMX is a full-featured, carrier-grade virtual MX Series 3D Universal Edge Router that extends 15+ years of Juniper Networks edge routing expertise to the virtual realm. This appliance is for the Virtual Forwarding Plane (vFP) VM and is meant to be paired with the Virtual Control Plane (vCP) VM.", - "documentation_url": "http://www.juniper.net/techpubs/", - "first_port_name": "Eth0", - "images": [ - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vfpc_17.1R1.8-disk1.vmdk", - "filesize": 102820352, - "md5sum": "169dd487b8547d58b12b2918a5667360", - "version": "17.1R1.8-ESXi" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vFPC-20170216.img", - "filesize": 2313158656, - "md5sum": "e838b8dd116a8b388d8dfd99575e7e98", - "version": "17.1R1.8-KVM" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vfpc_16.2R1.6-disk1.vmdk", - "filesize": 102430208, - "md5sum": "abb15d485cd195b9a693a2f3f091564a", - "version": "16.2R1.6-ESXi" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vFPC-20161025.img", - "filesize": 2313158656, - "md5sum": "3105a5af7d859fc24b686e71113413a9", - "version": "16.2R1.6-KVM" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vfpc_16.1R4.7-disk1.vmdk", - "filesize": 102431232, - "md5sum": "c381a23038dc5d4f939b7b5c3d074ce2", - "version": "16.1R4.7-ESXi" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vFPC-20170211.img", - "filesize": 2313158656, - "md5sum": "cdec45ecca1cd9bfefe318b066bd500b", - "version": "16.1R4.7-KVM" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vfpc_16.1R3.10-disk1.vmdk", - "filesize": 102437376, - "md5sum": "03b9d23c0223d8078fa3830c23fcf144", - "version": "16.1R3.10-ESXi" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vFPC-20161019.img", - "filesize": 2313158656, - "md5sum": "0fbba19da959c3e76b438128b28726f7", - "version": "16.1R3.10-KVM" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vfpc_16.1R2.11-disk1.vmdk", - "filesize": 102431232, - "md5sum": "1a90e5dc0c02c8336b9084cbdf17f635", - "version": "16.1R2.11-ESXi" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vFPC-20160902.img", - "filesize": 2313158656, - "md5sum": "09ee97c6c18b392b1b72f5e3e4743c2d", - "version": "16.1R2.11-KVM" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vfpc_16.1R1.7-disk1.vmdk", - "filesize": 63884800, - "md5sum": "8475d8b065768f585659a49c50f1d7e1", - "version": "16.1R1.7-ESXi" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vFPC-20160617.img", - "filesize": 2313158656, - "md5sum": "5ccf252002184a21413cad23fd239c3f", - "version": "16.1R1.7-KVM" - }, - { - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "filename": "vFPC-20151203.img", - "filesize": 2313158656, - "md5sum": "b3faa91b4d20836a9a6dd6bad2629dd1", - "version": "15.1F4.15" - } - ], - "maintainer": "none", - "maintainer_email": "developers@gns3.net", - "name": "Juniper vMX vFP", - "port_name_format": "Eth{port1}", - "product_name": "Juniper vMX vFP", - "product_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 12, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "options": "-nographic -enable-kvm -smp cpus=3", - "ram": 4096 - }, - "registry_version": 3, - "status": "experimental", - "symbol": "juniper-vmx.svg", - "usage": "Initial username is root, password is root.\n", - "vendor_name": "Juniper", - "vendor_url": "https://www.juniper.net/us/en/", - "versions": [ - { - "images": { - "hda_disk_image": "vfpc_17.1R1.8-disk1.vmdk" - }, - "name": "17.1R1.8-ESXi" - }, - { - "images": { - "hda_disk_image": "vFPC-20170216.img" - }, - "name": "17.1R1.8-KVM" - }, - { - "images": { - "hda_disk_image": "vfpc_16.2R1.6-disk1.vmdk" - }, - "name": "16.2R1.6-ESXi" - }, - { - "images": { - "hda_disk_image": "vFPC-20161025.img" - }, - "name": "16.2R1.6-KVM" - }, - { - "images": { - "hda_disk_image": "vfpc_16.1R4.7-disk1.vmdk" - }, - "name": "16.1R4.7-ESXi" - }, - { - "images": { - "hda_disk_image": "vFPC-20170211.img" - }, - "name": "16.1R4.7-KVM" - }, - { - "images": { - "hda_disk_image": "vfpc_16.1R3.10-disk1.vmdk" - }, - "name": "16.1R3.10-ESXi" - }, - { - "images": { - "hda_disk_image": "vFPC-20161019.img" - }, - "name": "16.1R3.10-KVM" - }, - { - "images": { - "hda_disk_image": "vfpc_16.1R2.11-disk1.vmdk" - }, - "name": "16.1R2.11-ESXi" - }, - { - "images": { - "hda_disk_image": "vFPC-20160902.img" - }, - "name": "16.1R2.11-KVM" - }, - { - "images": { - "hda_disk_image": "vfpc_16.1R1.7-disk1.vmdk" - }, - "name": "16.1R1.7-ESXi" - }, - { - "images": { - "hda_disk_image": "vFPC-20160617.img" - }, - "name": "16.1R1.7-KVM" - }, - { - "images": { - "hda_disk_image": "vFPC-20151203.img" - }, - "name": "15.1F4.15" - } - ] - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "The vQFX10000 makes it easy for you to try out our physical QFX10000 high-performance data center switch without the wait for physical delivery. Although the virtual version has limited performance relative to the physical switch, it lets you quickly emulate the same features for the control plane of the physical switch, or both its control and data planes.", - "documentation_url": "http://www.juniper.net/techpubs/", - "images": [ - { - "download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", - "filename": "vqfx10k-pfe-20160609-2.vmdk", - "filesize": 584086528, - "md5sum": "faa6905fd8e935c6e97859191143e8c3", - "version": "15.1X53-D60" - } - ], - "maintainer": "none", - "maintainer_email": "developers@gns3.net", - "name": "Juniper vQFX PFE", - "port_name_format": "em{0}", - "product_name": "Juniper vQFX PFE", - "product_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", - "qemu": { - "adapter_type": "e1000", - "adapters": 2, - "arch": "x86_64", - "console_type": "vnc", - "kvm": "require", - "options": "-nographic", - "ram": 2048 - }, - "registry_version": 3, - "status": "experimental", - "symbol": "juniper-vqfx.svg", - "usage": "\n\nUSAGE INSTRUCTIONS\n\nConnect the first interface (em0) to your admin VLAN. Connect the second interface (em1) directly to the second interface (em1) of the RE. The switch ports do not connect here, but on the RE", - "vendor_name": "Juniper", - "vendor_url": "https://www.juniper.net/us/en/", - "versions": [ - { - "images": { - "hda_disk_image": "vqfx10k-pfe-20160609-2.vmdk" - }, - "name": "15.1X53-D60" - } - ] - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "The vQFX10000 makes it easy for you to try out our physical QFX10000 high-performance data center switch without the wait for physical delivery. Although the virtual version has limited performance relative to the physical switch, it lets you quickly emulate the same features for the control plane of the physical switch, or both its control and data planes.", - "documentation_url": "http://www.juniper.net/techpubs/", - "images": [ - { - "download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", - "filename": "vqfx10k-re-15.1X53-D60.vmdk", - "filesize": 355542528, - "md5sum": "758669e88213fbd7943f5da7f6d7bd59", - "version": "15.1X53-D60" - } - ], - "maintainer": "none", - "maintainer_email": "developers@gns3.net", - "name": "Juniper vQFX RE", - "port_name_format": "em{0}", - "product_name": "Juniper vQFX RE", - "product_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/", - "qemu": { - "adapter_type": "e1000", - "adapters": 12, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "options": "-nographic -smp 2", - "ram": 1024 - }, - "registry_version": 3, - "status": "experimental", - "symbol": "juniper-vqfx.svg", - "usage": "Initial username is root, password is Juniper (capitol J).\n\nUSAGE INSTRUCTIONS\n\nConnect the first interface (em0) to your admin VLAN. Connect the second interface (em1) directly to the second interface (em1) of the PFE. The switch ports connect here on the RE", - "vendor_name": "Juniper", - "vendor_url": "https://www.juniper.net/us/en/", - "versions": [ - { - "images": { - "hda_disk_image": "vqfx10k-re-15.1X53-D60.vmdk" - }, - "name": "15.1X53-D60" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "The vSRX delivers core firewall, networking, advanced security, and automated lifecycle management capabilities for enterprises and service providers. The industry\u2019s fastest virtual security platform, the vSRX offers firewall speeds up to 17 Gbps using only two virtual CPUs, providing scalable, secure protection across private, public, and hybrid clouds.\n\nJuniper version 12 can support only 1GB of ram.", - "documentation_url": "http://www.juniper.net/techpubs/", - "images": [ - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "media-vsrx-vmdisk-17.3R1.10.qcow2", - "filesize": 3782541312, - "md5sum": "49b276e9ccdd8588f9e2ff38cccc884a", - "version": "17.3R1" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "media-vsrx-vmdisk-15.1X49-D110.4.qcow2", - "filesize": 3280011264, - "md5sum": "8d74641594eb036b2e2c6b462d541156", - "version": "15.1X49-D110" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "media-vsrx-vmdisk-15.1X49-D100.6.qcow2", - "filesize": 3279290368, - "md5sum": "aa29686dd6f2d38f668f23cb4bc9f354", - "version": "15.1X49-D100" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "media-vsrx-vmdisk-15.1X49-D90.7.qcow2", - "filesize": 3189440512, - "md5sum": "a64f3910054d461c4bbb32620008cba3", - "version": "15.1X49-D90" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "media-vsrx-vmdisk-15.1X49-D80.4.qcow2", - "filesize": 3186884608, - "md5sum": "ceb9d06a827c8f8bfb4fd1c9065bdd20", - "version": "15.1X49-D80" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "media-vsrx-vmdisk-15.1X49-D75.5.qcow2", - "filesize": 3116236800, - "md5sum": "197f167f338420d36a6db0f4e84ad376", - "version": "15.1X49-D75" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "media-vsrx-vmdisk-15.1X49-D70.3.qcow2", - "filesize": 3115450368, - "md5sum": "7b11babaef0b775f36281ec1d16f1708", - "version": "15.1X49-D70" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "junos-vsrx-vmdisk-15.1X49-D60.qcow2", - "filesize": 3094478848, - "md5sum": "d2ec79880f67e141c4dd662c656da278", - "version": "15.1X49-D60" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "junos-vsrx-vmdisk-15.1X49-D50.qcow2", - "filesize": 3063021568, - "md5sum": "60e1b80603c2ecf8aa9920c384209863", - "version": "15.1X49-D50" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "junos-vsrx-vmdisk-15.1X49-D40.qcow2", - "filesize": 3054043136, - "md5sum": "8d929c0262fd1eea3b3d02ef9e73c8c5", - "version": "15.1X49-D40" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "junos-vsrx-vmdisk-15.1X49-D20.2.qcow2", - "filesize": 2904096768, - "md5sum": "43e8000870207db47c1382192319eb45", - "version": "15.1X49-D20.2" - }, - { - "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/", - "filename": "junos-vsrx-12.1X47-D20.7-domestic-disk1.vmdk", - "filesize": 235894272, - "md5sum": "d22ed7a7eb131984e892a4430c5f4730", - "version": "12.1X47-D20.7" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "vSRX", - "port_name_format": "ge-0/0/{0}", - "product_name": "Juniper vSRX", - "product_url": "https://www.juniper.net/us/en/products-services/security/srx-series/vsrx/", - "qemu": { - "adapter_type": "e1000", - "adapters": 6, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "require", - "options": "-smp 2", - "ram": 4096 - }, - "registry_version": 3, - "status": "experimental", - "usage": "Initial username is root, no password.", - "vendor_name": "Juniper", - "vendor_url": "https://www.juniper.net/us/en/", - "versions": [ - { - "images": { - "hda_disk_image": "media-vsrx-vmdisk-17.3R1.10.qcow2" - }, - "name": "17.3R1" - }, - { - "images": { - "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D110.4.qcow2" - }, - "name": "15.1X49-D110" - }, - { - "images": { - "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D100.6.qcow2" - }, - "name": "15.1X49-D100" - }, - { - "images": { - "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D90.7.qcow2" - }, - "name": "15.1X49-D90" - }, - { - "images": { - "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D80.4.qcow2" - }, - "name": "15.1X49-D80" - }, - { - "images": { - "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D75.5.qcow2" - }, - "name": "15.1X49-D75" - }, - { - "images": { - "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D70.3.qcow2" - }, - "name": "15.1X49-D70" - }, - { - "images": { - "hda_disk_image": "junos-vsrx-vmdisk-15.1X49-D60.qcow2" - }, - "name": "15.1X49-D60" - }, - { - "images": { - "hda_disk_image": "junos-vsrx-vmdisk-15.1X49-D50.qcow2" - }, - "name": "15.1X49-D50" - }, - { - "images": { - "hda_disk_image": "junos-vsrx-vmdisk-15.1X49-D40.qcow2" - }, - "name": "15.1X49-D40" - }, - { - "images": { - "hda_disk_image": "junos-vsrx-vmdisk-15.1X49-D20.2.qcow2" - }, - "name": "15.1X49-D20" - }, - { - "images": { - "hda_disk_image": "junos-vsrx-12.1X47-D20.7-domestic-disk1.vmdk" - }, - "name": "12.1X47-D20" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, machine learning and much more.", - "docker": { - "adapters": 1, - "console_http_path": "/", - "console_http_port": 8888, - "console_type": "http", - "image": "gns3/jupyter:v2" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Jupyter", - "product_name": "Jupyter", - "registry_version": 3, - "status": "stable", - "vendor_name": "Project Jupyter", - "vendor_url": "http://jupyter.org/" - }, - { - "builtin": true, - "category": "guest", - "description": "The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, machine learning and much more. This appliance provide python 2.7.", - "docker": { - "adapters": 1, - "console_http_path": "/", - "console_http_port": 8888, - "console_type": "http", - "image": "gns3/jupyter27:v2" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Jupyter 2.7", - "product_name": "Jupyter", - "registry_version": 3, - "status": "stable", - "vendor_name": "Project Jupyter", - "vendor_url": "http://jupyter.org/" - }, - { - "builtin": true, - "category": "guest", - "description": "From the creators of BackTrack comes Kali Linux, the most advanced and versatile penetration testing platform ever created. We have a set of amazing features lined up in our security distribution geared at streamlining the penetration testing experience. This version has no GUI.Include packages:\n* nmap\n* metasploit\n* sqlmap\n* hydra\n* telnet client\n* dnsutils (dig)", - "docker": { - "adapters": 2, - "image": "gns3/kalilinux:v2" - }, - "documentation_url": "https://www.kali.org/kali-linux-documentation/", - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Kali Linux CLI", - "product_name": "Kali Linux", - "registry_version": 3, - "status": "stable", - "vendor_name": "Kali Linux", - "vendor_url": "https://www.kali.org/" - }, - { - "builtin": true, - "category": "guest", - "description": "From the creators of BackTrack comes Kali Linux, the most advanced and versatile penetration testing platform ever created. We have a set of amazing features lined up in our security distribution geared at streamlining the penetration testing experience.", - "documentation_url": "https://www.kali.org/kali-linux-documentation/", - "images": [ - { - "direct_download_url": "http://cdimage.kali.org/kali-2017.2/kali-linux-2017.2-amd64.iso", - "download_url": "http://cdimage.kali.org/kali-2017.2/", - "filename": "kali-linux-2017.2-amd64.iso", - "filesize": 3020619776, - "md5sum": "541654f8f818450dc0db866a0a0f6eec", - "version": "2017.2" - }, - { - "direct_download_url": "http://cdimage.kali.org/kali-2017.1/kali-linux-2017.1-amd64.iso", - "download_url": "http://cdimage.kali.org/kali-2017.1/", - "filename": "kali-linux-2017.1-amd64.iso", - "filesize": 2794307584, - "md5sum": "c8e742283929d7a12dbe7c58e398ff08", - "version": "2017.1" - }, - { - "direct_download_url": "http://cdimage.kali.org/kali-2016.2/kali-linux-2016.2-amd64.iso", - "download_url": "http://cdimage.kali.org/kali-2016.2/", - "filename": "kali-linux-2016.2-amd64.iso", - "filesize": 3076767744, - "md5sum": "3d163746bc5148e61ad689d94bc263f9", - "version": "2016.2" - }, - { - "direct_download_url": "http://cdimage.kali.org/kali-2016.1/kali-linux-2016.1-amd64.iso", - "download_url": "http://cdimage.kali.org/kali-2016.1/", - "filename": "kali-linux-2016.1-amd64.iso", - "filesize": 2945482752, - "md5sum": "2e1230dc14036935b3279dfe3e49ad39", - "version": "2016.1" - }, - { - "direct_download_url": "http://images.kali.org/Kali-Linux-2.0.0-vm-amd64.7z", - "download_url": "https://www.offensive-security.com/kali-linux-vmware-arm-image-download/", - "filename": "kali-linux-2.0-amd64.iso", - "filesize": 3320512512, - "md5sum": "ef192433017c5d99a156eaef51fd389d", - "version": "2.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Kali Linux", - "product_name": "Kali Linux", - "qemu": { - "adapter_type": "e1000", - "adapters": 8, - "arch": "x86_64", - "console_type": "vnc", - "kvm": "require", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default password is toor", - "vendor_name": "Kali Linux", - "vendor_url": "https://www.kali.org/", - "versions": [ - { - "images": { - "cdrom_image": "kali-linux-2017.2-amd64.iso" - }, - "name": "2017.2" - }, - { - "images": { - "cdrom_image": "kali-linux-2017.1-amd64.iso" - }, - "name": "2017.1" - }, - { - "images": { - "cdrom_image": "kali-linux-2016.2-amd64.iso" - }, - "name": "2016.2" - }, - { - "images": { - "cdrom_image": "kali-linux-2016.1-amd64.iso" - }, - "name": "2016.1" - }, - { - "images": { - "cdrom_image": "kali-linux-2.0-amd64.iso" - }, - "name": "2.0" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "KEMP Technologies free LoadMaster Application Load Balancer is a fully featured member of our award winning and industry leading Load Balancer family. It can be used without charge in production environments with throughput requirements that don\u2019t exceed 20 Mbps, and for services that do not directly generate revenue. It is an ideal choice for low traffic web sites and applications, DevOps testing environments, technical training environments, and for any other deployments that suit your non-commercial needs.", - "documentation_url": "https://support.kemptechnologies.com/hc/en-us/articles/204427785", - "images": [ - { - "download_url": "http://freeloadbalancer.com/download/", - "filename": "LoadMaster-VLM-7.2.40.0.15707.RELEASE-Linux-KVM-XEN-FREE.disk", - "filesize": 17179869185, - "md5sum": "4284a80141f7974d082a2eed91ec6216", - "version": "7.2.40.0" - }, - { - "download_url": "http://freeloadbalancer.com/download/", - "filename": "LoadMaster-VLM-7.2.38.0.14750.RELEASE-Linux-KVM-XEN.disk", - "filesize": 17179869185, - "md5sum": "f51f17640793b31a7eab70b53f6ae3ae", - "version": "7.2.38.0" - }, - { - "download_url": "http://freeloadbalancer.com/download/", - "filename": "LoadMaster-VLM-7.2.36.2.14271.RELEASE-Linux-KVM-XEN-FREE.disk", - "filesize": 17179869185, - "md5sum": "eebfc96bd6c1c50827d00647206b59dd", - "version": "7.1.36.2" - }, - { - "download_url": "http://freeloadbalancer.com/download/", - "filename": "LoadMaster-VLM-7.1.35.0.13244.RELEASE-Linux-KVM-XEN-FREE.disk", - "filesize": 17179869185, - "md5sum": "f72e8dffa201c8ec92767872593a52a1", - "version": "7.1.35.0" - }, - { - "download_url": "http://freeloadbalancer.com/download/", - "filename": "LoadMaster-VLM-7.1.34.1.12802.RELEASE-Linux-KVM-XEN-FREE.disk", - "filesize": 17179869185, - "md5sum": "157b36233bbd9d9dfa18363958b34fd1", - "version": "7.1.34.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "KEMP Free VLM", - "port_name_format": "eth{0}", - "product_name": "KEMP Free VLM", - "product_url": "http://freeloadbalancer.com/#about", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "allow", - "options": "-smp 2", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "symbol": "loadbalancer.svg", - "usage": "Credentials: bal / 1fourall", - "vendor_name": "KEMP", - "vendor_url": "http://freeloadbalancer.com/", - "versions": [ - { - "images": { - "hda_disk_image": "LoadMaster-VLM-7.2.40.0.15707.RELEASE-Linux-KVM-XEN-FREE.disk" - }, - "name": "7.2.40.0" - }, - { - "images": { - "hda_disk_image": "LoadMaster-VLM-7.2.38.0.14750.RELEASE-Linux-KVM-XEN.disk" - }, - "name": "7.2.38.0" - }, - { - "images": { - "hda_disk_image": "LoadMaster-VLM-7.2.36.2.14271.RELEASE-Linux-KVM-XEN-FREE.disk" - }, - "name": "7.2.36.2" - }, - { - "images": { - "hda_disk_image": "LoadMaster-VLM-7.1.35.0.13244.RELEASE-Linux-KVM-XEN-FREE.disk" - }, - "name": "7.1.35.0" - }, - { - "images": { - "hda_disk_image": "LoadMaster-VLM-7.1.34.1.12802.RELEASE-Linux-KVM-XEN-FREE.disk" - }, - "name": "7.1.34.1" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Kerio Connect makes email, calendars, contacts and task management easy and affordable. With Kerio Connect, you have immediate, secure access to your communications anytime, anywhere, on any device \u2014 without complexity or expensive overhead.", - "documentation_url": "http://kb.kerio.com/product/kerio-connect/", - "images": [ - { - "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.5-3336/kerio-connect-appliance-9.2.5-3336-p3-vmware-amd64-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-connect", - "filename": "kerio-connect-appliance-9.2.5-3336-p3-vmware-amd64-disk1.vmdk", - "filesize": 824496128, - "md5sum": "f2a202f29e71dc6e8bebce4c05a9e44d", - "version": "9.2.5p3" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.4-3252/kerio-connect-appliance-9.2.4-3252-vmware-amd64-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-connect", - "filename": "kerio-connect-appliance-9.2.4-3252-vmware-amd64-disk1.vmdk", - "filesize": 720217088, - "md5sum": "c585587a8de878d3940e42cf389b0f06", - "version": "9.2.4" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.3-2929/kerio-connect-appliance-9.2.3-2929-vmware-amd64-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-connect", - "filename": "kerio-connect-appliance-9.2.3-2929-vmware-amd64-disk1.vmdk", - "filesize": 676196352, - "md5sum": "29ecf7ac72b32e576e1556af9a741ab2", - "version": "9.2.3" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.2-2831/kerio-connect-appliance-9.2.2-2831-p1-vmware-amd64-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-connect", - "filename": "kerio-connect-appliance-9.2.2-2831-p1-vmware-amd64-disk1.vmdk", - "filesize": 673714688, - "md5sum": "586ab9830602746e6a3438afaa6ee9b8", - "version": "9.2.2p1" - }, - { - "compression": "zip", - "direct_download_url": "http://download.kerio.com/dwn/kerio-connect-appliance-vmware-amd64.zip", - "download_url": "http://www.kerio.com/support/kerio-connect", - "filename": "kerio-connect-appliance-9.2.1-vmware-disk1.vmdk", - "filesize": 1851523072, - "md5sum": "f1d60094c237f55e6737b0da9b5912ce", - "version": "9.2.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Kerio Connect", - "port_name_format": "eth{0}", - "product_name": "Kerio Connect", - "product_url": "http://www.kerio.com/products/kerio-connect", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default ucredentials: root / kerio", - "vendor_name": "Kerio Technologies Inc.", - "vendor_url": "http://www.kerio.com", - "versions": [ - { - "images": { - "hda_disk_image": "kerio-connect-appliance-9.2.5-3336-p3-vmware-amd64-disk1.vmdk" - }, - "name": "9.2.5" - }, - { - "images": { - "hda_disk_image": "kerio-connect-appliance-9.2.4-3252-vmware-amd64-disk1.vmdk" - }, - "name": "9.2.4" - }, - { - "images": { - "hda_disk_image": "kerio-connect-appliance-9.2.3-2929-vmware-amd64-disk1.vmdk" - }, - "name": "9.2.3" - }, - { - "images": { - "hda_disk_image": "kerio-connect-appliance-9.2.2-2831-p1-vmware-amd64-disk1.vmdk" - }, - "name": "9.2.2p1" - }, - { - "images": { - "hda_disk_image": "kerio-connect-appliance-9.2.1-vmware-disk1.vmdk" - }, - "name": "9.2.1" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "Protect your network from viruses, malware and malicious activity with Kerio Control, the easy-to-administer yet powerful all-in-one security solution.\nKerio Control brings together next-generation firewall capabilities - including a network firewall and router, intrusion detection and prevention (IPS), gateway anti-virus, VPN, and web content and application filtering. These comprehensive capabilities and unmatched deployment flexibility make Kerio Control the ideal choice for small and mid-sized businesses.", - "documentation_url": "http://kb.kerio.com/product/kerio-control/", - "images": [ - { - "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.4-2223/kerio-control-appliance-9.2.4-2223-vmware-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-control", - "filename": "kerio-control-appliance-9.2.4-2223-vmware-disk1.vmdk", - "filesize": 191687168, - "md5sum": "20970f3638c7ca5603c2afbe56e89421", - "version": "9.2.4" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.3-2219/kerio-control-appliance-9.2.3-2219-vmware-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-control", - "filename": "kerio-control-appliance-9.2.3-2219-vmware-disk1.vmdk", - "filesize": 191716352, - "md5sum": "767d5b25bdca2b45c2ba269189ea9bd0", - "version": "9.2.3" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.2-2172/kerio-control-appliance-9.2.2-2172-vmware-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-control", - "filename": "kerio-control-appliance-9.2.2-2172-vmware-disk1.vmdk", - "filesize": 190841856, - "md5sum": "4efeacbc39db1b3e53ef96af1338cf52", - "version": "9.2.2" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.1-2019/kerio-control-appliance-9.2.1-2019-vmware-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-control", - "filename": "kerio-control-appliance-9.2.1-2019-vmware-disk1.vmdk", - "filesize": 254364160, - "md5sum": "0405890e323e29a4808ec288600875ba", - "version": "9.2.1" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.1.4-1535/kerio-control-appliance-9.1.4-1535-vmware.vmdk", - "download_url": "http://www.kerio.com/support/kerio-control", - "filename": "kerio-control-appliance-9.1.4-1535-vmware.vmdk", - "filesize": 483459072, - "md5sum": "5ea5a7f103b1f008d4c24444400333ec", - "version": "9.1.4" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Kerio Control", - "port_name_format": "eth{0}", - "product_name": "Kerio Control", - "product_url": "http://www.kerio.com/products/kerio-control", - "qemu": { - "adapter_type": "e1000", - "adapters": 2, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 4096 - }, - "registry_version": 3, - "status": "stable", - "vendor_name": "Kerio Technologies Inc.", - "vendor_url": "http://www.kerio.com", - "versions": [ - { - "images": { - "hda_disk_image": "kerio-control-appliance-9.2.4-2223-vmware-disk1.vmdk" - }, - "name": "9.2.4" - }, - { - "images": { - "hda_disk_image": "kerio-control-appliance-9.2.3-2219-vmware-disk1.vmdk" - }, - "name": "9.2.3" - }, - { - "images": { - "hda_disk_image": "kerio-control-appliance-9.2.2-2172-vmware-disk1.vmdk" - }, - "name": "9.2.2" - }, - { - "images": { - "hda_disk_image": "kerio-control-appliance-9.2.1-2019-vmware-disk1.vmdk" - }, - "name": "9.2.1" - }, - { - "images": { - "hda_disk_image": "kerio-control-appliance-9.1.4-1535-vmware.vmdk" - }, - "name": "9.1.4" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Stay connected to your customers and colleagues without being chained to your desk.\nKerio Operator is a VoIP based phone system that provides powerful yet affordable enterprise-class voice and video communication capabilities for small and mid-sized businesses globally.", - "documentation_url": "http://kb.kerio.com/product/kerio-operator/", - "images": [ - { - "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.6.0-8413/kerio-operator-appliance-2.6.0-8413-vmware-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-operator", - "filename": "kerio-operator-appliance-2.6.0-8413-vmware-disk1.vmdk", - "filesize": 291227136, - "md5sum": "3eddbb73d685ac4666841f5df2c6bec9", - "version": "2.6.0" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.5.5-8309/kerio-operator-appliance-2.5.5-8309-p2-vmware-disk1.vmdk", - "download_url": "http://www.kerio.com/support/kerio-operator", - "filename": "kerio-operator-appliance-2.5.5-8309-p2-vmware-disk1.vmdk", - "filesize": 291217408, - "md5sum": "dc0b4d0b264eb39c8c73289b6c8de749", - "version": "2.5.5p2" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.5.4-6916/kerio-operator-appliance-2.5.4-6916-p1-vmware.vmdk", - "download_url": "http://www.kerio.com/support/kerio-operator", - "filename": "kerio-operator-appliance-2.5.4-6916-p1-vmware.vmdk", - "filesize": 276318720, - "md5sum": "6737b36bd36635b8a5ba21816938f0d6", - "version": "2.5.4p1" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.5.3-6630/kerio-operator-appliance-2.5.3-6630-vmware.vmdk", - "download_url": "http://www.kerio.com/support/kerio-operator", - "filename": "kerio-operator-appliance-2.5.3-6630-vmware.vmdk", - "filesize": 276422144, - "md5sum": "ae9f45606900dba05f353a94d4fc14fc", - "version": "2.5.3" - }, - { - "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.5.2-6404/kerio-operator-appliance-2.5.2-6404-vmware.vmdk", - "download_url": "http://www.kerio.com/support/kerio-operator", - "filename": "kerio-operator-appliance-2.5.2-6404-vmware.vmdk", - "filesize": 561512448, - "md5sum": "0279baebe587b17f32bfc3302df9352c", - "version": "2.5.2" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Kerio Operator", - "port_name_format": "eth{0}", - "product_name": "Kerio Operator", - "product_url": "http://www.kerio.com/products/kerio-operator", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default credentials: root (no password set)", - "vendor_name": "Kerio Technologies Inc.", - "vendor_url": "http://www.kerio.com", - "versions": [ - { - "images": { - "hda_disk_image": "kerio-operator-appliance-2.6.0-8413-vmware-disk1.vmdk" - }, - "name": "2.6.0" - }, - { - "images": { - "hda_disk_image": "kerio-operator-appliance-2.5.5-8309-p2-vmware-disk1.vmdk" - }, - "name": "2.5.5p2" - }, - { - "images": { - "hda_disk_image": "kerio-operator-appliance-2.5.4-6916-p1-vmware.vmdk" - }, - "name": "2.5.4p1" - }, - { - "images": { - "hda_disk_image": "kerio-operator-appliance-2.5.3-6630-vmware.vmdk" - }, - "name": "2.5.3" - }, - { - "images": { - "hda_disk_image": "kerio-operator-appliance-2.5.2-6404-vmware.vmdk" - }, - "name": "2.5.2" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "LEDE is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers). Unlike many other distributions for these routers, OpenWrt is built from the ground up to be a full-featured, easily modifiable operating system for your router. In practice, this means that you can have all the features you need with none of the bloat, powered by a Linux kernel that's more recent than most other distributions.", - "documentation_url": "http://wiki.openwrt.org/doc/", - "images": [ - { - "direct_download_url": "https://downloads.lede-project.org/releases/17.01.2/targets/x86/generic/lede-17.01.2-x86-generic-combined-squashfs.img", - "download_url": "https://downloads.lede-project.org/releases/17.01.2/targets/x86/generic/", - "filename": "lede-17.01.2-x86-generic-combined-squashfs.img", - "filesize": 19774794, - "md5sum": "a466e493ef12935dad5e0c622b1a7859", - "version": "17.01.2" - }, - { - "direct_download_url": "https://downloads.lede-project.org/releases/17.01.1/targets/x86/generic/lede-17.01.1-x86-generic-combined-squashfs.img", - "download_url": "https://downloads.lede-project.org/releases/17.01.1/targets/x86/generic/", - "filename": "lede-17.01.1-x86-generic-combined-squashfs.img", - "filesize": 19771166, - "md5sum": "b050e734c605a34a429389c752ae7c30", - "version": "17.01.1" - }, - { - "direct_download_url": "https://downloads.lede-project.org/releases/17.01.0/targets/x86/generic/lede-17.01.0-r3205-59508e3-x86-generic-combined-squashfs.img", - "download_url": "https://downloads.lede-project.org/releases/17.01.0/targets/x86/generic/", - "filename": "lede-17.01.0-r3205-59508e3-x86-generic-combined-squashfs.img", - "filesize": 19755118, - "md5sum": "3c5e068d50a377d4e26b548ab1ca7b1e", - "version": "17.01.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "LEDE", - "product_name": "LEDE", - "product_url": "https://lede-project.org/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "i386", - "console_type": "telnet", - "kvm": "allow", - "ram": 64 - }, - "registry_version": 3, - "status": "stable", - "usage": "Ethernet0 is the LAN link, Ethernet1 the WAN link.", - "vendor_name": "LEDE Project", - "vendor_url": "https://lede-project.org/", - "versions": [ - { - "images": { - "hda_disk_image": "lede-17.01.2-x86-generic-combined-squashfs.img" - }, - "name": "lede 17.01.2" - }, - { - "images": { - "hda_disk_image": "lede-17.01.1-x86-generic-combined-squashfs.img" - }, - "name": "lede 17.01.1" - }, - { - "images": { - "hda_disk_image": "lede-17.01.0-r3205-59508e3-x86-generic-combined-squashfs.img" - }, - "name": "lede 17.01.0" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Don't you hate it when companies artificially cripple performance? We just give you two simple choices - Now isn't that a refreshing change?", - "documentation_url": "https://loadbalancer.org/support/support-resources", - "images": [ - { - "download_url": "https://loadbalancer.org/resources/free-trial", - "filename": "Loadbalancer.org_Enterprise_VA-8.3-disk1.qcow2", - "filesize": 368332288, - "md5sum": "f0e41f39a5cab47990edc0509c579bac", - "version": "8.3" - }, - { - "download_url": "https://loadbalancer.org/resources/free-trial", - "filename": "Loadbalancer.org_Enterprise_VA-8.2-disk1.qcow2", - "filesize": 8430419968, - "md5sum": "8b74b330a6f629a081f3b36a5d64605b", - "version": "8.2" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Loadbalancer.org Enterprise VA", - "product_name": "Loadbalancer.org Enterprise VA", - "product_url": "https://loadbalancer.org/products/virtual", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "x86_64", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "symbol": "loadbalancer.svg", - "usage": "Default credentials:\n Network config CLI: setup / setup\n CLI: root / loadbalancer\n WebUI: loadbalancer / loadbalancer", - "vendor_name": "Loadbalancer.org", - "vendor_url": "https://loadbalancer.org/", - "versions": [ - { - "images": { - "hda_disk_image": "Loadbalancer.org_Enterprise_VA-8.3-disk1.qcow2" - }, - "name": "8.3" - }, - { - "images": { - "hda_disk_image": "Loadbalancer.org_Enterprise_VA-8.2-disk1.qcow2" - }, - "name": "8.2" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Micro Core Linux is a smaller variant of Tiny Core without a graphical desktop.\n\nThis is complete Linux system needing few resources to run.", - "documentation_url": "http://wiki.tinycorelinux.net/", - "images": [ - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-microcore-6.4.img", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "linux-microcore-6.4.img", - "filesize": 16580608, - "md5sum": "877419f975c4891c019947ceead5c696", - "version": "6.4" - }, - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-microcore-4.0.2-clean.img", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "linux-microcore-4.0.2-clean.img", - "filesize": 26411008, - "md5sum": "e13d0d1c0b3999ae2386bba70417930c", - "version": "4.0.2" - }, - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-microcore-3.4.1.img", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "linux-microcore-3.4.1.img", - "filesize": 24969216, - "md5sum": "fa2ec4b1fffad67d8103c3391bbf9df2", - "version": "3.4.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Micro Core Linux", - "product_name": "Micro Core Linux", - "product_url": "http://distro.ibiblio.org/tinycorelinux", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "i386", - "console_type": "telnet", - "kvm": "allow", - "ram": 64 - }, - "registry_version": 3, - "status": "stable", - "symbol": "linux_guest.svg", - "usage": "For version >= 6.4, login/password is gns3. For older version it is tc. Note that sudo works without any password", - "vendor_name": "Team Tiny Core", - "vendor_url": "http://distro.ibiblio.org/tinycorelinux", - "versions": [ - { - "images": { - "hda_disk_image": "linux-microcore-6.4.img" - }, - "name": "6.4" - }, - { - "images": { - "hda_disk_image": "linux-microcore-4.0.2-clean.img" - }, - "name": "4.0.2" - }, - { - "images": { - "hda_disk_image": "linux-microcore-3.4.1.img" - }, - "name": "3.4.1" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Cloud Hosted Router (CHR) is a RouterOS version meant for running as a virtual machine. It supports x86 64-bit architecture and can be used on most of popular hypervisors such as VMWare, Hyper-V, VirtualBox, KVM and others. CHR has full RouterOS features enabled by default but has a different licensing model than other RouterOS versions.", - "documentation_url": "http://wiki.mikrotik.com/wiki/Manual:CHR", - "images": [ - { - "compression": "zip", - "direct_download_url": "https://download2.mikrotik.com/routeros/6.40.5/chr-6.40.5.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.40.5.img", - "filesize": 134217728, - "md5sum": "5d3bef219a859d417fea704ae7109eb7", - "version": "6.40.5" - }, - { - "compression": "zip", - "direct_download_url": "https://download2.mikrotik.com/routeros/6.40.3/chr-6.40.3.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.40.3.img", - "filesize": 134217728, - "md5sum": "1861df67e9bbf17433f11f33f7dedd1e", - "version": "6.40.3" - }, - { - "compression": "zip", - "direct_download_url": "https://download2.mikrotik.com/routeros/6.39.2/chr-6.39.2.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.39.2.img", - "filesize": 134217728, - "md5sum": "ecb37373dedfba04267a999d23b8e203", - "version": "6.39.2" - }, - { - "compression": "zip", - "direct_download_url": "https://download2.mikrotik.com/routeros/6.39.1/chr-6.39.1.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.39.1.img", - "filesize": 134217728, - "md5sum": "c53293bc41f76d85a8642005fd1cbd54", - "version": "6.39.1" - }, - { - "compression": "zip", - "direct_download_url": "https://download2.mikrotik.com/routeros/6.39/chr-6.39.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.39.img", - "filesize": 134217728, - "md5sum": "7e77c8ac4c9aeaf88f6ff15897f33163", - "version": "6.39" - }, - { - "compression": "zip", - "direct_download_url": "https://download2.mikrotik.com/routeros/6.38.7/chr-6.38.7.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.38.7.img", - "filesize": 134217728, - "md5sum": "69a51c96b1247bbaf1253d2873617122", - "version": "6.38.7" - }, - { - "compression": "zip", - "direct_download_url": "https://download2.mikrotik.com/routeros/6.38.5/chr-6.38.5.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.38.5.img", - "filesize": 134217728, - "md5sum": "8147f42ea1ee96f580a35a298b7f9354", - "version": "6.38.5" - }, - { - "compression": "zip", - "direct_download_url": "https://download2.mikrotik.com/routeros/6.38.1/chr-6.38.1.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.38.1.img", - "filesize": 134217728, - "md5sum": "753ed7c86e0f54fd9e18d044db64538d", - "version": "6.38.1" - }, - { - "compression": "zip", - "direct_download_url": "http://download2.mikrotik.com/routeros/6.38/chr-6.38.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.38.img", - "filesize": 134217728, - "md5sum": "37e2165112f8a9beccac06a9a6009000", - "version": "6.38" - }, - { - "compression": "zip", - "direct_download_url": "http://download2.mikrotik.com/routeros/6.37.3/chr-6.37.3.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.37.3.img", - "filesize": 134217728, - "md5sum": "bda87db475f80debdf3181accf6b78e2", - "version": "6.37.3" - }, - { - "compression": "zip", - "direct_download_url": "http://download2.mikrotik.com/routeros/6.37.1/chr-6.37.1.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.37.1.img", - "filesize": 134217728, - "md5sum": "713b14a5aba9f967f7bdd9029c8d85b6", - "version": "6.37.1" - }, - { - "compression": "zip", - "direct_download_url": "http://download2.mikrotik.com/routeros/6.36.4/chr-6.36.4.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.36.4.img", - "filesize": 134217728, - "md5sum": "09527bde50697711926c08d545940c1e", - "version": "6.36.4" - }, - { - "direct_download_url": "http://download2.mikrotik.com/routeros/6.34.2/chr-6.34.2.vmdk", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.34.2.vmdk", - "filesize": 30277632, - "md5sum": "0360f121b76a8b491a05dc37640ca319", - "version": "6.34.2 (.vmdk)" - }, - { - "direct_download_url": "http://download2.mikrotik.com/routeros/6.34.2/chr-6.34.2.vdi", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.34.2.vdi", - "filesize": 30409728, - "md5sum": "e7e4021aeeee2eaabd024d48702bb2e1", - "version": "6.34.2 (.vdi)" - }, - { - "compression": "zip", - "direct_download_url": "http://download2.mikrotik.com/routeros/6.34.2/chr-6.34.2.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.34.2.img", - "filesize": 134217728, - "md5sum": "984d4d11c2ff209fcdc21ac42895edbe", - "version": "6.34.2 (.img)" - }, - { - "direct_download_url": "http://download2.mikrotik.com/routeros/6.34/chr-6.34.vmdk", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.34.vmdk", - "filesize": 30277632, - "md5sum": "c5e6d192ae19d263a9a313d4b4bee7e4", - "version": "6.34 (.vmdk)" - }, - { - "direct_download_url": "http://download2.mikrotik.com/routeros/6.34/chr-6.34.vdi", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.34.vdi", - "filesize": 30409728, - "md5sum": "34b161f83a792c744c76a529afc094a8", - "version": "6.34 (.vdi)" - }, - { - "compression": "zip", - "direct_download_url": "http://download2.mikrotik.com/routeros/6.34/chr-6.34.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.34.img", - "filesize": 134217728, - "md5sum": "32ffde7fb934c7bfee555c899ccd77b6", - "version": "6.34 (.img)" - }, - { - "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.5/chr-6.33.5.vmdk", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.33.5.vmdk", - "filesize": 23920640, - "md5sum": "cd284e28aa02ae59f55ed8f43ff27fbf", - "version": "6.33.5 (.vmdk)" - }, - { - "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.5/chr-6.33.5.vdi", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.33.5.vdi", - "filesize": 24118272, - "md5sum": "fa84e63a558e7c61d7d338386cfd08c9", - "version": "6.33.5 (.vdi)" - }, - { - "compression": "zip", - "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.5/chr-6.33.5.img.zip", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.33.5.img", - "filesize": 67108864, - "md5sum": "210cc8ad06f25c9f27b6b99f6e00bd91", - "version": "6.33.5 (.img)" - }, - { - "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.3/chr-6.33.3.vmdk", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.33.3.vmdk", - "filesize": 23920640, - "md5sum": "08532a5af1a830182d65c416eab2b089", - "version": "6.33.3 (.vmdk)" - }, - { - "direct_download_url": "http://download2.mikrotik.com/routeros/6.33.2/chr-6.33.2.vmdk", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.33.2.vmdk", - "filesize": 23920640, - "md5sum": "6291893c2c9626603c6d38d23390a8be", - "version": "6.33.2 (.vmdk)" - }, - { - "direct_download_url": "http://download2.mikrotik.com/routeros/6.33/chr-6.33.vmdk", - "download_url": "http://www.mikrotik.com/download", - "filename": "chr-6.33.vmdk", - "filesize": 23920640, - "md5sum": "63bee5405fa1e209388adc6b5f78bb70", - "version": "6.33 (.vmdk)" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "MikroTik CHR", - "port_name_format": "ether{port1}", - "product_name": "MikroTik Cloud Hosted Router", - "product_url": "http://www.mikrotik.com/download", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "allow", - "options": "-nographic", - "ram": 128 - }, - "registry_version": 3, - "status": "stable", - "symbol": ":/symbols/router_firewall.svg", - "usage": "If you'd like a different sized main disk, resize the image before booting the VM for the first time.\n\nOn first boot, RouterOS is actually being installed, formatting the whole main virtual disk, before finally rebooting. That whole process may take a minute or so.\n\nThe console will become available after the installation is complete. Most Telnet/SSH clients (certainly SuperPutty) will keep retrying to connect, thus letting you know when installation is done.\n\nFrom that point on, everything about RouterOS is also true about Cloud Hosted Router, including the default credentials: Username \"admin\" and an empty password.\n\nThe primary differences between RouterOS and CHR are in support for virtual devices (this appliance comes with them being selected), and in the different license model, for which you can read more about at http://wiki.mikrotik.com/wiki/Manual:CHR.", - "vendor_name": "MikroTik", - "vendor_url": "http://mikrotik.com/", - "versions": [ - { - "images": { - "hda_disk_image": "chr-6.40.5.img" - }, - "name": "6.40.5" - }, - { - "images": { - "hda_disk_image": "chr-6.40.3.img" - }, - "name": "6.40.3" - }, - { - "images": { - "hda_disk_image": "chr-6.39.2.img" - }, - "name": "6.39.2" - }, - { - "images": { - "hda_disk_image": "chr-6.39.1.img" - }, - "name": "6.39.1" - }, - { - "images": { - "hda_disk_image": "chr-6.39.img" - }, - "name": "6.39" - }, - { - "images": { - "hda_disk_image": "chr-6.38.7.img" - }, - "name": "6.38.7" - }, - { - "images": { - "hda_disk_image": "chr-6.38.5.img" - }, - "name": "6.38.5" - }, - { - "images": { - "hda_disk_image": "chr-6.38.1.img" - }, - "name": "6.38.1" - }, - { - "images": { - "hda_disk_image": "chr-6.38.img" - }, - "name": "6.38" - }, - { - "images": { - "hda_disk_image": "chr-6.37.3.img" - }, - "name": "6.37.3" - }, - { - "images": { - "hda_disk_image": "chr-6.37.1.img" - }, - "name": "6.37.1" - }, - { - "images": { - "hda_disk_image": "chr-6.36.4.img" - }, - "name": "6.36.4" - }, - { - "images": { - "hda_disk_image": "chr-6.34.2.vmdk" - }, - "name": "6.34.2 (.vmdk)" - }, - { - "images": { - "hda_disk_image": "chr-6.34.2.vdi" - }, - "name": "6.34.2 (.vdi)" - }, - { - "images": { - "hda_disk_image": "chr-6.34.2.img" - }, - "name": "6.34.2 (.img)" - }, - { - "images": { - "hda_disk_image": "chr-6.34.vmdk" - }, - "name": "6.34 (.vmdk)" - }, - { - "images": { - "hda_disk_image": "chr-6.34.vdi" - }, - "name": "6.34 (.vdi)" - }, - { - "images": { - "hda_disk_image": "chr-6.34.img" - }, - "name": "6.34 (.img)" - }, - { - "images": { - "hda_disk_image": "chr-6.33.5.vmdk" - }, - "name": "6.33.5 (.vmdk)" - }, - { - "images": { - "hda_disk_image": "chr-6.33.5.vdi" - }, - "name": "6.33.5 (.vdi)" - }, - { - "images": { - "hda_disk_image": "chr-6.33.5.img" - }, - "name": "6.33.5 (.img)" - }, - { - "images": { - "hda_disk_image": "chr-6.33.3.vmdk" - }, - "name": "6.33.3 (.vmdk)" - }, - { - "images": { - "hda_disk_image": "chr-6.33.2.vmdk" - }, - "name": "6.33.2 (.vmdk)" - }, - { - "images": { - "hda_disk_image": "chr-6.33.vmdk" - }, - "name": "6.33 (.vmdk)" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "NETem emulates a network link, typically a WAN link. It supports bandwidth limitation, delay, jitter and packet loss. All this functionality is already build in the linux kernel, NETem is just a menu system to make the configuration user-friendly.", - "documentation_url": "http://www.cs.unm.edu/~crandall/netsfall13/TCtutorial.pdf", - "images": [ - { - "direct_download_url": "http://bernhard-ehlers.de/projects/netem/NETem-v4.qcow2", - "download_url": "http://bernhard-ehlers.de/projects/netem/index.html", - "filename": "NETem-v4.qcow2", - "filesize": 26476544, - "md5sum": "e678698c97804901c7a53f6b68c8b861", - "version": "0.4" - } - ], - "maintainer": "Bernhard Ehlers", - "maintainer_email": "be@bernhard-ehlers.de", - "name": "NETem", - "port_name_format": "eth{0}", - "product_name": "netem", - "qemu": { - "adapter_type": "e1000", - "adapters": 2, - "arch": "i386", - "console_type": "telnet", - "kvm": "allow", - "options": "-nographic", - "ram": 96 - }, - "registry_version": 3, - "status": "experimental", - "usage": "Insert the NETem VM between two network elements and connect it to them. NETem is fully transparent, it bridges the traffic from one interface to the other one. As NETem only bridges, it needs no IP addresses. On start a menu on the console allows a user-friendy configuration of the line parameters.", - "vendor_name": "Linux", - "vendor_url": "http://www.linuxfoundation.org/", - "versions": [ - { - "images": { - "hda_disk_image": "NETem-v4.qcow2" - }, - "name": "0.4" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "This container provides the popular tools used for network automation: Netmiko, NAPALM, Pyntc, and Ansible.", - "docker": { - "adapters": 1, - "console_type": "telnet", - "image": "gns3/network_automation:latest" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Network Automation", - "product_name": "Network Automation", - "registry_version": 3, - "status": "stable", - "symbol": "linux_guest.svg", - "vendor_name": "GNS3", - "vendor_url": "http://www.gns3.com" - }, - { - "builtin": true, - "category": "guest", - "description": "ntopng is the next generation version of the original ntop, a network traffic probe that shows the network usage, similar to what the popular top Unix command does. ntopng is based on libpcap and it has been written in a portable way in order to virtually run on every Unix platform, MacOSX and on Windows as well. ntopng users can use a a web browser to navigate through ntop (that acts as a web server) traffic information and get a dump of the network status. In the latter case, ntopng can be seen as a simple RMON-like agent with an embedded web interface.", - "docker": { - "adapters": 1, - "console_http_path": "/", - "console_http_port": 3000, - "console_type": "http", - "image": "lucaderi/ntopng-docker:latest" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "ntopng", - "product_name": "ntopng", - "registry_version": 3, - "status": "stable", - "usage": "In the web interface login as admin/admin", - "vendor_name": "ntop", - "vendor_url": "http://www.ntop.org/" - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "The Open Network Operating System (ONOS) is a software defined networking (SDN) OS for service providers that has scalability, high availability, high performance and abstractions to make it easy to create apps and services. The platform is based on a solid architecture and has quickly matured to be feature rich and production ready. The community has grown to include over 50 partners and collaborators that contribute to all aspects of the project including interesting use cases such as CORD", - "docker": { - "adapters": 1, - "image": "onosproject/onos:latest" - }, - "documentation_url": "https://wiki.onosproject.org", - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Onos", - "product_name": "Onos", - "product_url": "http://onosproject.org/", - "registry_version": 3, - "status": "stable", - "vendor_name": "Onos", - "vendor_url": "http://onosproject.org/" - }, - { - "builtin": true, - "category": "guest", - "description": "Over 200,000 IT staff across medium to large enterprises worldwide are currently using OP5 Monitor as their preferred network monitoring software.\nOP5 Monitor allows you to take control of your IT, enabling your network to be more responsive, more reliable and even faster than ever before. With unparalleled scalability, OP5 Monitor grows as your company grows, so you\u2019ll understand why we say this is the last network monitor you\u2019ll ever need to purchase.", - "documentation_url": "https://kb.op5.com/display/MAN/Documentation+Home#sthash.pohb5bis.dpbs", - "images": [ - { - "download_url": "https://www.op5.com/download/", - "filename": "op5-Monitor-Virtual-Appliance-7.3.15.x86_64.vmdk", - "filesize": 779687424, - "md5sum": "634acc6266237d99bf1bfbcf9284beca", - "version": "7.3.15" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "OP5 Monitor", - "port_name_format": "eth{0}", - "product_name": "OP5 Monitor", - "product_url": "https://www.op5.com/op5-monitor/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "symbol": "mgmt_station.svg", - "usage": "Interface eth0 is set to DHCP. Default credentials:\n- CLI: root / monitor\n- Web access: admin / monitor\n- Logserver Extension: admin / admin", - "vendor_name": "OP5", - "vendor_url": "https://www.op5.com/", - "versions": [ - { - "images": { - "hda_disk_image": "op5-Monitor-Virtual-Appliance-7.3.15.x86_64.vmdk" - }, - "name": "7.3.15" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "The OpenBSD project produces a FREE, multi-platform 4.4BSD-based UNIX-like operating system. Our efforts emphasize portability, standardization, correctness, proactive security and integrated cryptography. As an example of the effect OpenBSD has, the popular OpenSSH software comes from OpenBSD.", - "documentation_url": "http://www.openbsd.org/faq/index.html", - "first_port_name": "fxp0", - "images": [ - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/openbsd-5.8.qcow2", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "openbsd-5.8.qcow2", - "filesize": 517275648, - "md5sum": "b2488d81bbe1328ae3d6072ccd7e0bc2", - "version": "5.8" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "OpenBSD", - "port_name_format": "em{0}", - "product_name": "OpenBSD", - "qemu": { - "adapter_type": "e1000", - "adapters": 8, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "allow", - "ram": 256 - }, - "registry_version": 3, - "status": "stable", - "usage": "User root, password gns3", - "vendor_name": "OpenBSD", - "vendor_url": "http://www.openbsd.org", - "versions": [ - { - "images": { - "hda_disk_image": "openbsd-5.8.qcow2" - }, - "name": "5.8" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "openSUSE is a free and Linux-based operating system for PC, Laptop or Server. The openSUSE project is a community program sponsored by Novell. It is a general purpose operating system built on top of the Linux kernel, developed by the community-supported openSUSE Project and sponsored by SUSE and a number of other companies.", - "documentation_url": "https://en.opensuse.org/Main_Page", - "images": [ - { - "download_url": "http://www.osboxes.org/opensuse/", - "filename": "openSUSE_42.3-Leap-VM-64bit.vmdk", - "filesize": 5891293184, - "md5sum": "ab777cf90557460ff35aedfbf2befc5d", - "version": "Leap 42.3" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "openSUSE", - "port_name_format": "eth{0}", - "product_name": "openSUSE", - "product_url": "https://www.opensuse.org/#Leap", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 1, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "sata", - "kvm": "require", - "options": "-vga virtio", - "ram": 1024 - }, - "registry_version": 4, - "status": "stable", - "usage": "Username: osboxes\nPassword: osboxes.org\n\nroot password: osboxes.org", - "vendor_name": "SUSE LLC.", - "vendor_url": "https://www.opensuse.org/", - "versions": [ - { - "images": { - "hda_disk_image": "openSUSE_42.3-Leap-VM-64bit.vmdk" - }, - "name": "Leap 42.3" - } - ] - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. This is a version of the appliance with a management interface on eth0.", - "docker": { - "adapters": 16, - "environment": "MANAGEMENT_INTERFACE=1", - "image": "gns3/openvswitch:latest" - }, - "documentation_url": "http://openvswitch.org/support/", - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Open vSwitch management", - "product_name": "Open vSwitch", - "registry_version": 3, - "status": "stable", - "symbol": "mgmt_station_docker.svg", - "usage": "The eth0 is the management interface. By default all other interfaces are connected to the br0", - "vendor_name": "Open vSwitch", - "vendor_url": "http://openvswitch.org/" - }, - { - "builtin": true, - "category": "multilayer_switch", - "description": "Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.", - "docker": { - "adapters": 16, - "image": "gns3/openvswitch:latest" - }, - "documentation_url": "http://openvswitch.org/support/", - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Open vSwitch", - "product_name": "Open vSwitch", - "product_url": "http://openvswitch.org/", - "registry_version": 3, - "status": "stable", - "usage": "By default all interfaces are connected to the br0", - "vendor_name": "Open vSwitch", - "vendor_url": "http://openvswitch.org/" - }, - { - "builtin": true, - "category": "router", - "description": "OpenWrt is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers). Unlike many other distributions for these routers, OpenWrt is built from the ground up to be a full-featured, easily modifiable operating system for your router. In practice, this means that you can have all the features you need with none of the bloat, powered by a Linux kernel that's more recent than most other distributions.\n\nThe realview platform is meant for use with QEMU for emulating an ARM system.", - "documentation_url": "http://wiki.openwrt.org/doc/", - "images": [ - { - "direct_download_url": "http://downloads.openwrt.org/chaos_calmer/15.05.1/realview/generic/openwrt-15.05.1-realview-vmlinux-initramfs.elf", - "download_url": "http://downloads.openwrt.org/chaos_calmer/15.05.1/realview/generic/", - "filename": "openwrt-15.05.1-realview-vmlinux-initramfs.elf", - "filesize": 2278696, - "md5sum": "3660b9de654cf03f2a50997ae89c2daf", - "version": "15.05.1" - }, - { - "direct_download_url": "http://downloads.openwrt.org/barrier_breaker/14.07/realview/generic/openwrt-realview-vmlinux-initramfs.elf", - "download_url": "http://downloads.openwrt.org/barrier_breaker/14.07/realview/generic/", - "filename": "openwrt-realview-vmlinux-initramfs-14.07.elf", - "filesize": 2183520, - "md5sum": "2411307d0794baa618537c5dfcb19575", - "version": "14.07" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "OpenWrt Realview", - "product_name": "OpenWrt", - "product_url": "http://openwrt.org", - "qemu": { - "adapter_type": "e1000", - "adapters": 2, - "arch": "arm", - "console_type": "telnet", - "kvm": "allow", - "options": "-M realview-eb-mpcore", - "ram": 128 - }, - "registry_version": 3, - "status": "stable", - "vendor_name": "OpenWrt", - "vendor_url": "http://openwrt.org", - "versions": [ - { - "images": { - "kernel_image": "openwrt-15.05.1-realview-vmlinux-initramfs.elf" - }, - "name": "Chaos Calmer 15.05.1" - }, - { - "images": { - "kernel_image": "openwrt-realview-vmlinux-initramfs-14.07.elf" - }, - "name": "Barrier Breaker 14.07" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "OpenWrt is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers). Unlike many other distributions for these routers, OpenWrt is built from the ground up to be a full-featured, easily modifiable operating system for your router. In practice, this means that you can have all the features you need with none of the bloat, powered by a Linux kernel that's more recent than most other distributions.", - "documentation_url": "http://wiki.openwrt.org/doc/", - "images": [ - { - "compression": "gzip", - "direct_download_url": "https://downloads.openwrt.org/chaos_calmer/15.05.1/x86/kvm_guest/openwrt-15.05.1-x86-kvm_guest-combined-ext4.img.gz", - "download_url": "http://downloads.openwrt.org/chaos_calmer/15.05.1/x86/kvm_guest/", - "filename": "openwrt-15.05.1-x86-kvm_guest-combined-ext4.img", - "filesize": 55050240, - "md5sum": "d02f5224b7fbe929efa4d3f10f4dc996", - "version": "15.05.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "OpenWrt", - "product_name": "OpenWrt", - "product_url": "http://openwrt.org", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "i386", - "console_type": "telnet", - "kvm": "allow", - "ram": 64 - }, - "registry_version": 3, - "status": "stable", - "usage": "Ethernet0 is the LAN link, Ethernet1 the WAN link.", - "vendor_name": "OpenWrt", - "vendor_url": "http://openwrt.org", - "versions": [ - { - "images": { - "hda_disk_image": "openwrt-15.05.1-x86-kvm_guest-combined-ext4.img" - }, - "name": "Chaos Calmer 15.05.1" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "OPNsense is an open source, easy-to-use and easy-to-build FreeBSD based firewall and routing platform. OPNsense includes most of the features available in expensive commercial firewalls, and more in many cases. It brings the rich feature set of commercial offerings with the benefits of open and verifiable sources.\n\nOPNsense started as a fork of pfSense\u00ae and m0n0wall in 2014, with its first official release in January 2015. The project has evolved very quickly while still retaining familiar aspects of both m0n0wall and pfSense. A strong focus on security and code quality drives the development of the project.", - "documentation_url": "https://wiki.opnsense.org/", - "images": [ - { - "download_url": "https://opnsense.org/download/", - "filename": "OPNsense-17.7-OpenSSL-nano-amd64.img", - "filesize": 3221233664, - "md5sum": "14cde5c7a15b2298a242238ad3c3b65a", - "version": "17.7" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "OPNsense", - "port_name_format": "em{0}", - "product_name": "OPNsense", - "product_url": "https://opnsense.org/about/about-opnsense/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default credentials: root / opnsense\nDefault IP address: 192.168.1.1", - "vendor_name": "Deciso B.V.", - "vendor_url": "https://opnsense.org/", - "versions": [ - { - "images": { - "hda_disk_image": "OPNsense-17.7-OpenSSL-nano-amd64.img" - }, - "name": "17.7" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Ostinato is an open-source, cross-platform network packet crafter/traffic generator and analyzer with a friendly GUI. Craft and send packets of several streams with different protocols at different rates.", - "documentation_url": "http://ostinato.org/docs.html", - "images": [ - { - "direct_download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/ostinato-0.8-97c7d79.qcow2", - "download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/index.html", - "filename": "ostinato-0.8-97c7d79.qcow2", - "filesize": 98631680, - "md5sum": "5aad15c1eb7baac588a4c8c3faafa380", - "version": "0.8-97c7d79" - }, - { - "direct_download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/ostinato-0.8-1.qcow2", - "download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/index.html", - "filename": "ostinato-0.8-1.qcow2", - "filesize": 57344000, - "md5sum": "12e990ba695103cfac82f8771b8015d4", - "version": "0.8" - } - ], - "maintainer": "Bernhard Ehlers", - "maintainer_email": "be@bernhard-ehlers.de", - "name": "Ostinato", - "port_name_format": "eth{0}", - "product_name": "Ostinato", - "product_url": "http://ostinato.org/", - "qemu": { - "adapter_type": "e1000", - "adapters": 4, - "arch": "i386", - "console_type": "vnc", - "kvm": "allow", - "options": "-vga std -usbdevice tablet", - "ram": 256 - }, - "registry_version": 3, - "status": "experimental", - "symbol": "ostinato-3d-icon.svg", - "usage": "Use interfaces starting with eth1 as traffic interfaces, eth0 is only for the (optional) management of the server/drone.", - "vendor_name": "Ostinato", - "vendor_url": "http://ostinato.org/", - "versions": [ - { - "images": { - "hda_disk_image": "ostinato-0.8-97c7d79.qcow2" - }, - "name": "0.8-97c7d79" - }, - { - "images": { - "hda_disk_image": "ostinato-0.8-1.qcow2" - }, - "name": "0.8" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "PacketFence is a fully supported, trusted, Free and Open Source network access control (NAC) solution. Boasting an impressive feature set including a captive-portal for registration and remediation, centralized wired and wireless management, 802.1X support, layer-2 isolation of problematic devices, integration with the Snort IDS and the Nessus vulnerability scanner; PacketFence can be used to effectively secure networks - from small to very large heterogeneous networks.", - "documentation_url": "https://packetfence.org/support/index.html#/documentation", - "images": [ - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/7.3.0/PacketFenceZEN_USB-7.3.0.tar.bz2/download", - "download_url": "https://packetfence.org/download.html#/zen", - "filename": "PacketFenceZEN_USB-7.3.0.img", - "filesize": 3221225472, - "md5sum": "dfeb8a97bba2e475ce418b02327c0ea1", - "version": "7.3.0" - }, - { - "compression": "bzip2", - "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/7.1.0/PacketFenceZEN_USB-7.1.0.tar.bz2/download", - "download_url": "https://packetfence.org/download.html#/zen", - "filename": "PacketFenceZEN_USB-7.1.0.img", - "filesize": 3221225472, - "md5sum": "3811099f4e1eba164245e94cfa09d26f", - "version": "7.1.0" - }, - { - "compression": "bzip2", - "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/7.0.0/PacketFenceZEN_USB-7.0.0.tar.bz2/download", - "download_url": "https://packetfence.org/download.html#/zen", - "filename": "PacketFenceZEN_USB-7.0.0.img", - "filesize": 3221225472, - "md5sum": "f5d7f81b279ad286e09f3ddf29dd06c3", - "version": "7.0.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.5.1/PacketFenceZEN_USB-6.5.1.tar.bz2/download", - "download_url": "https://packetfence.org/download.html#/zen", - "filename": "PacketFenceZEN_USB-6.5.1.img", - "filesize": 3221225472, - "md5sum": "937c02640bd487889b7071e8f094a62a", - "version": "6.5.1" - }, - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.5.0/PacketFenceZEN_USB-6.5.0.tar.bz2/download", - "download_url": "https://packetfence.org/download.html#/zen", - "filename": "PacketFenceZEN_USB-6.5.0.img", - "filesize": 3221225472, - "md5sum": "5d5ff015f115e9dbcfd355f1bb22f5d9", - "version": "6.5.0" - }, - { - "compression": "bzip2", - "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.4.0/PacketFenceZEN_USB-6.4.0.tar.bz2/download", - "download_url": "https://packetfence.org/download.html#/zen", - "filename": "PacketFenceZEN_USB-6.4.0.img", - "filesize": 3221225472, - "md5sum": "7f2bea58421d094152ea71f49cc3084a", - "version": "6.4.0" - }, - { - "compression": "bzip2", - "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.3.0/PacketFenceZEN_USB-6.3.0.tar.bz2/download", - "download_url": "https://packetfence.org/download.html#/zen", - "filename": "PacketFenceZEN_USB-6.3.0.img", - "filesize": 3221225472, - "md5sum": "94e19349faedf292743fdc0ab48f8466", - "version": "6.3.0" - }, - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/6.2.1/PacketFenceZEN_USB-6.2.1.tar.bz2/download", - "download_url": "https://packetfence.org/download.html#/zen", - "filename": "PacketFenceZEN_USB-6.2.1.img", - "filesize": 3221225472, - "md5sum": "f212be7c8621b90d973f500f00ef1277", - "version": "6.2.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "PacketFence ZEN", - "product_name": "PacketFence ZEN", - "product_url": "https://packetfence.org/about.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "x86_64", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 8192 - }, - "registry_version": 3, - "status": "stable", - "usage": "Boot the live CD", - "vendor_name": "Inverse inc.", - "vendor_url": "https://packetfence.org/", - "versions": [ - { - "images": { - "hda_disk_image": "PacketFenceZEN_USB-7.3.0.img" - }, - "name": "7.3.0" - }, - { - "images": { - "hda_disk_image": "PacketFenceZEN_USB-7.1.0.img" - }, - "name": "7.1.0" - }, - { - "images": { - "hda_disk_image": "PacketFenceZEN_USB-7.0.0.img" - }, - "name": "7.0.0" - }, - { - "images": { - "hda_disk_image": "PacketFenceZEN_USB-6.5.1.img" - }, - "name": "6.5.0" - }, - { - "images": { - "hda_disk_image": "PacketFenceZEN_USB-6.5.0.img" - }, - "name": "6.5.0" - }, - { - "images": { - "hda_disk_image": "PacketFenceZEN_USB-6.4.0.img" - }, - "name": "6.4.0" - }, - { - "images": { - "hda_disk_image": "PacketFenceZEN_USB-6.3.0.img" - }, - "name": "6.3.0" - }, - { - "images": { - "hda_disk_image": "PacketFenceZEN_USB-6.2.1.img" - }, - "name": "6.2.1" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "The VM-Series combines next-generation firewall security and advanced threat prevention to protect your virtualized environments from advanced cyberthreats. The VM-Series natively analyzes all traffic in a single pass to determine the application identity, the content within, and the user identity.", - "documentation_url": "https://www.paloaltonetworks.com/documentation/80/virtualization/virtualization", - "first_port_name": "management", - "images": [ - { - "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", - "filename": "PA-VM-ESX-6.1.0-disk1.vmdk", - "filesize": 2959736832, - "md5sum": "64b1e81cd54008318235832ea6d71424", - "version": "6.1.0 (ESX)" - }, - { - "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", - "filename": "PA-VM-KVM-7.1.0.qcow2", - "filesize": 1858797568, - "md5sum": "da300253709740068927408239c2e321", - "version": "7.1.0" - }, - { - "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", - "filename": "PA-VM-ESX-7.1.0-disk1.vmdk", - "filesize": 1871149056, - "md5sum": "e044dc649b7146ee4f619edb0e5f6675", - "version": "7.1.0 (ESX)" - }, - { - "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/", - "filename": "PA-VM-KVM-8.0.0.qcow2", - "filesize": 1987444736, - "md5sum": "b6a1ddc8552aff87f05f9c0d4cb54dc3", - "version": "8.0.0" - } - ], - "maintainer": "Community", - "maintainer_email": "", - "name": "PA-VM", - "port_name_format": "ethernet1/{port1}", - "product_name": "PAN VM-Series Firewall", - "product_url": "https://www.paloaltonetworks.com/products/secure-the-network/virtualized-next-generation-firewall/vm-series", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 25, - "arch": "x86_64", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "options": "-smp 2", - "ram": 4096 - }, - "registry_version": 3, - "status": "experimental", - "symbol": "pan-vm-fw.svg", - "usage": "Default Username: admin\r\nDefault Password: admin\r\nPAN-VM goes through several iterations of host prompts during boot. This is normal and expected.\r\nLogin is available when prompt is PA-VM login:\r\n\r\nGetting Started:\r\nTo configure a static IP address at the console enter the following commands:\r\n\r\nconfigure\r\nset deviceconfig system ip-address netmask default-gateway type static\r\nset deviceconfig system dns-setting servers primary secondary \r\ncommit\r\n", - "vendor_name": "Palo Alto Networks", - "vendor_url": "http://www.paloaltonetworks.com/", - "versions": [ - { - "images": { - "hda_disk_image": "PA-VM-ESX-6.1.0-disk1.vmdk" - }, - "name": "6.1.0 (ESX)" - }, - { - "images": { - "hda_disk_image": "PA-VM-KVM-7.1.0.qcow2" - }, - "name": "7.1.0" - }, - { - "images": { - "hda_disk_image": "PA-VM-ESX-7.1.0-disk1.vmdk" - }, - "name": "7.1.0 (ESX)" - }, - { - "images": { - "hda_disk_image": "PA-VM-KVM-8.0.0.qcow2" - }, - "name": "8.0.0" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "The pfSense project is a free network firewall distribution, based on the FreeBSD operating system with a custom kernel and including third party free software packages for additional functionality. pfSense software, with the help of the package system, is able to provide the same functionality or more of common commercial firewalls, without any of the artificial limitations. It has successfully replaced every big name commercial firewall you can imagine in numerous installations around the world, including Check Point, Cisco PIX, Cisco ASA, Juniper, Sonicwall, Netgear, Watchguard, Astaro, and more.", - "documentation_url": "https://doc.pfsense.org/index.php/Main_Page", - "images": [ - { - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads", - "filename": "pfSense-CE-2.3.5-RELEASE-2g-amd64-nanobsd.img", - "filesize": 1989969408, - "md5sum": "b6cb76adba3e1113892f84ea01894228", - "version": "2.3.5" - }, - { - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads", - "filename": "pfSense-CE-2.3.4-RELEASE-2g-amd64-nanobsd.img", - "filesize": 1989969408, - "md5sum": "0c9871b54f932be2d550908f7c23b302", - "version": "2.3.4" - }, - { - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads", - "filename": "pfSense-CE-2.3.3-RELEASE-2g-amd64-nanobsd.img", - "filesize": 1989969408, - "md5sum": "200f073c4f0a4ba6690920079f23d5dd", - "version": "2.3.3" - }, - { - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads", - "filename": "pfSense-CE-2.3.2-RELEASE-2g-amd64-nanobsd.img", - "filesize": 1989969408, - "md5sum": "c91f2c8e287f4930695e65a6793cb8fe", - "version": "2.3.2" - }, - { - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads", - "filename": "pfSense-CE-2.3.1-RELEASE-2g-amd64-nanobsd.img", - "filesize": 1989969408, - "md5sum": "719149eed51e03872a8cfd235d958d2e", - "version": "2.3.1" - }, - { - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads", - "filename": "pfSense-CE-2.3-RELEASE-2g-amd64-nanobsd.img", - "filesize": 1989969408, - "md5sum": "8ab5047bd4c5bbabf71055fb75177d85", - "version": "2.3" - }, - { - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads", - "filename": "pfSense-2.2.6-RELEASE-1g-amd64-nanobsd.img", - "filesize": 997097472, - "md5sum": "7bbe39c4ec698685c9f9b615926820a9", - "version": "2.2.6" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "pfSense", - "port_name_format": "em{0}", - "product_name": "pfSense", - "qemu": { - "adapter_type": "e1000", - "adapters": 6, - "arch": "x86_64", - "boot_priority": "dc", - "console_type": "telnet", - "kvm": "allow", - "process_priority": "normal", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "vendor_name": "Electric Sheep Fencing LLC", - "vendor_url": "https://www.pfsense.org", - "versions": [ - { - "images": { - "hda_disk_image": "pfSense-CE-2.3.5-RELEASE-2g-amd64-nanobsd.img" - }, - "name": "2.3.5" - }, - { - "images": { - "hda_disk_image": "pfSense-CE-2.3.4-RELEASE-2g-amd64-nanobsd.img" - }, - "name": "2.3.4" - }, - { - "images": { - "hda_disk_image": "pfSense-CE-2.3.3-RELEASE-2g-amd64-nanobsd.img" - }, - "name": "2.3.3" - }, - { - "images": { - "hda_disk_image": "pfSense-CE-2.3.2-RELEASE-2g-amd64-nanobsd.img" - }, - "name": "2.3.2" - }, - { - "images": { - "hda_disk_image": "pfSense-CE-2.3.1-RELEASE-2g-amd64-nanobsd.img" - }, - "name": "2.3.1" - }, - { - "images": { - "hda_disk_image": "pfSense-CE-2.3-RELEASE-2g-amd64-nanobsd.img" - }, - "name": "2.3" - }, - { - "images": { - "hda_disk_image": "pfSense-2.2.6-RELEASE-1g-amd64-nanobsd.img" - }, - "name": "2.2.6" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "To ensure efficient email communication and business continuity, IT professionals depend on reliable spam and virus blocking software. With Proxmox Mail Gateway you get the job done.\n\nProxmox Mail Gateway helps you protect your business against all email threats like spam, viruses, phishing and trojans at the moment they emerge. The flexible architecture combined with the userfriendly, web-based management make it simple for you to control all incoming and outgoing emails. You maintain a professional email workflow and gain high business reputation as well as customer satisfaction.", - "documentation_url": "http://www.proxmox.com/en/downloads/category/documentation-pmg", - "images": [ - { - "direct_download_url": "http://www.proxmox.com/en/downloads?task=callelement&format=raw&item_id=201&element=f85c494b-2b32-4109-b8c1-083cca2b7db6&method=download&args[0]=1f39333ff32bef6001584670e439c842", - "download_url": "http://www.proxmox.com/en/downloads", - "filename": "proxmox-mailgateway_4.1-5.iso", - "filesize": 746586112, - "md5sum": "f0b90f525b6f0fd51889ee48e44980b7", - "version": "4.1-5" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Proxmox MG", - "port_name_format": "eth{0}", - "product_name": "Proxmox MG", - "product_url": "http://www.proxmox.com/en/proxmox-mail-gateway", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 3, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 4096 - }, - "registry_version": 3, - "status": "stable", - "usage": "User: root\nPassword: admin", - "vendor_name": "Proxmox Server Solutions GmbH", - "vendor_url": "http://www.proxmox.com/en/", - "versions": [ - { - "images": { - "cdrom_image": "proxmox-mailgateway_4.1-5.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "4.1-5" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Container with integrated Python 2 & 3, Perl, PHP, and PHP7.0 interpreters, and a Go compiler.", - "docker": { - "adapters": 1, - "image": "gns3/python-go-perl-php:latest" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Python, Go, Perl, PHP", - "product_name": "Python, Go, Perl, PHP", - "registry_version": 3, - "status": "stable", - "vendor_name": "GNS3 Team", - "vendor_url": "https://www.gns3.com" - }, - { - "builtin": true, - "category": "guest", - "description": "Riverbed SteelHead delivers not only best-in-class optimization \u2013 but essential visibility and control as companies transition to the Hybrid WAN. SteelHead CX for Virtual is available as a virtual solution on most major hypervisors including VMware vSphere, Microsoft Hyper-V and KVM. It accelerates the performance of all applications including on-premises, cloud, and SaaS across the hybrid enterprise for organizations that want to deliver the best end user experience \u2013 while leveraging the scalability and cost benefits of virtualization.\n\nSteelHead CX for Virtual uniquely delivers the best application performance along with application, network and end user visibility, and simplified control management of users, applications and networks based on business requirements and decisions.", - "documentation_url": "https://support.riverbed.com/content/support/software/steelhead/cx-appliance.html", - "images": [ - { - "download_url": "http://www.riverbed.com/products/steelhead/Free-90-day-Evaluation-SteelHead-CX-Virtual-Edition.html", - "filename": "mgmt-9.2.0.img", - "filesize": 2555772928, - "md5sum": "ca20a76b2556c0cd313d0b0de528e94d", - "version": "9.2.0" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty100G.qcow2", - "filesize": 198656, - "md5sum": "1e6409a4523ada212dea2ebc50e50a65", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "SteelHead CX 555V", - "product_name": "SteelHead CX 555V", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "usage": "You don't need to run the installer script when using GNS3 VM. Uncompress the downloaded archive using this command: tar xzSf \nDefault credentials: admin / password", - "vendor_name": "Riverbed Technology", - "vendor_url": "http://www.riverbed.com", - "versions": [ - { - "images": { - "hda_disk_image": "mgmt-9.2.0.img", - "hdb_disk_image": "empty100G.qcow2" - }, - "name": "9.2.0" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Security Onion is a Linux distro for intrusion detection, network security monitoring, and log management. It\u2019s based on Ubuntu and contains Snort, Suricata, Bro, OSSEC, Sguil, Squert, ELSA, Xplico, NetworkMiner, and many other security tools. The easy-to-use Setup wizard allows you to build an army of distributed sensors for your enterprise in minutes!", - "documentation_url": "https://github.com/Security-Onion-Solutions/security-onion/wiki", - "images": [ - { - "direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.4.iso", - "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.4.iso", - "filename": "securityonion-14.04.5.4.iso", - "filesize": 1874853888, - "md5sum": "9c7cab756b675beb10de4274a3ad3bc6", - "version": "14.04.5.4" - }, - { - "direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.3.iso", - "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.3.iso", - "filename": "securityonion-14.04.5.3.iso", - "filesize": 1889533952, - "md5sum": "fb80ccb2d3c0f3f511823fa5858f87d1", - "version": "14.04.5.3" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%30disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "Brent Stewart", - "maintainer_email": "brent@stewart.tc", - "name": "Security Onion", - "product_name": "Security Onion", - "product_url": "https://securityonion.net/", - "qemu": { - "adapter_type": "e1000", - "adapters": 2, - "arch": "i386", - "console_type": "telnet", - "kvm": "allow", - "ram": 3072 - }, - "registry_version": 3, - "status": "stable", - "symbol": "securityonion-logo.png", - "usage": "Your default account will have sudo priviledges. Squil and Squert username and password are configured in the Setup wizard. MySQL root is set to null. For more info see https://github.com/Security-Onion-Solutions/security-onion/wiki/Passwords.", - "vendor_name": "Security Onion Solutions, LLC", - "vendor_url": "https://securityonion.net/", - "versions": [ - { - "images": { - "cdrom_image": "securityonion-14.04.5.4.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "14.04.5.4" - }, - { - "images": { - "cdrom_image": "securityonion-14.04.5.3.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "14.04.5.3" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "A Free firewall that includes its own security-hardened GNU/Linux operating system and an easy-to-use web interface.", - "documentation_url": "https://sourceforge.net/projects/smoothwall/files/SmoothWall%20Manuals/", - "images": [ - { - "direct_download_url": "http://sourceforge.net/projects/smoothwall/files/SmoothWall/3.1/Express-3.1-x86_64.iso/download", - "download_url": "http://www.smoothwall.org/download/", - "filename": "Express-3.1-x86_64.iso", - "filesize": 214206464, - "md5sum": "cfaf7f11901a164cd00c07518c7311ba", - "version": "3.1" - }, - { - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty8G.qcow2", - "filesize": 197120, - "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Smoothwall Express", - "port_name_format": "eth{0}", - "product_name": "Smoothwall Express", - "product_url": "http://www.smoothwall.org/about/", - "qemu": { - "adapter_type": "e1000", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "dc", - "console_type": "vnc", - "hda_disk_interface": "ide", - "kvm": "allow", - "ram": 256 - }, - "registry_version": 3, - "status": "stable", - "usage": "WebUI can be accessed at https://GREEN_IP:441/ after installation. GREEN interface is used for the LAN, RED for the WAN connections. ORANGE and PURPLE can be used for DMZ.", - "vendor_name": "Smoothwall Ltd.", - "vendor_url": "http://www.smoothwall.org/", - "versions": [ - { - "images": { - "cdrom_image": "Express-3.1-x86_64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "3.1" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Monitoring a distributed network across multiple locations can be a challenge. That\u2019s where Sophos iView can help. It provides you with an intelligent, uninterrupted view of your network from a single pane of glass. If you have multiple appliances, need consolidated reporting, or could just use help with log management or compliance, Sophos iView is the ideal solution.", - "documentation_url": "https://www.sophos.com/en-us/support/documentation/sophos-iview.aspx", - "images": [ - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SIVOS_02.00.0_MR-2.KVM-776-PRIMARY.qcow2", - "filesize": 493289472, - "md5sum": "d78c6f0c42186a4c606d7e57f2f3a6d7", - "version": "2.0.0 MR2" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SIVOS_02.00.0_MR-2.KVM-776-AUXILARY.qcow2", - "filesize": 204800, - "md5sum": "a52d8cedb1ccd4b5b9f2723dfb41588b", - "version": "2.0.0 MR2" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Sophos iView", - "product_name": "Sophos iView", - "product_url": "https://www.sophos.com/en-us/products/next-gen-firewall.aspx", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "require", - "ram": 4096 - }, - "registry_version": 3, - "status": "experimental", - "symbol": "mgmt_station.svg", - "usage": "Default CLI password: admin\nDefault WebUI address: http://172.16.16.18\nDefault WebUI credentials: admin / admin", - "vendor_name": "Sophos", - "vendor_url": "https://www.sophos.com", - "versions": [ - { - "images": { - "hda_disk_image": "VI-SIVOS_02.00.0_MR-2.KVM-776-PRIMARY.qcow2", - "hdb_disk_image": "VI-SIVOS_02.00.0_MR-2.KVM-776-AUXILARY.qcow2" - }, - "name": "2.0.0 MR2" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "Sophos Free Home Use Firewall is a fully equipped software version of the Sophos UTM firewall, available at no cost for home users \u2013 no strings attached. It features full Network, Web, Mail and Web Application Security with VPN functionality and protects up to 50 IP addresses. The Sophos UTM Free Home Use firewall contains its own operating system and will overwrite all data on the computer during the installation process. Therefore, a separate, dedicated computer or VM is needed, which will change into a fully functional security appliance.", - "documentation_url": "https://community.sophos.com/products/unified-threat-management/", - "images": [ - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.500-9.1.iso", - "filesize": 981612544, - "md5sum": "8531349cdb7f07c94596b19f8e08081a", - "version": "9.500-9.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.413-4.1.iso", - "filesize": 965146624, - "md5sum": "decdccf0fbb1c809c0d3ad1dd322ca5d", - "version": "9.413-4.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.411-3.1.iso", - "filesize": 947019776, - "md5sum": "0940197daccb5993a419b667c71fb341", - "version": "9.411-3.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.409-9.1.iso", - "filesize": 910178304, - "md5sum": "71e9261ac77d230f85d8066f8efef710", - "version": "9.409-9.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.408-4.1.iso", - "filesize": 892516352, - "md5sum": "b10aab2d3dd4d7f6424b9c64a075e550", - "version": "9.408-4.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.407-3.1.iso", - "filesize": 879738880, - "md5sum": "19f736d0766a960a1d37edf98daaf01d", - "version": "9.407-3.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.406-3.1.iso", - "filesize": 873408512, - "md5sum": "b79fb0fd04654068897961ab0594297c", - "version": "9.406-3.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.405-5.1.iso", - "filesize": 864020480, - "md5sum": "cc1687ea73dd7363212c0db5ad784bc6", - "version": "9.405-5.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.403-4.1.iso", - "filesize": 850329600, - "md5sum": "631f2a017deb284705d653905de51604", - "version": "9.403-4.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.358-3.1.iso", - "filesize": 868235264, - "md5sum": "883176415be49e12ab63b46ca749c7b2", - "version": "9.358-3.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.357-1.1.iso", - "filesize": 848300032, - "md5sum": "c34061e770f26a994b725b4b92fe56dc", - "version": "9.357-1.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.356-3.1.iso", - "filesize": 820531200, - "md5sum": "bd155ed98a477d1182367b302bb480f3", - "version": "9.356-3.1" - }, - { - "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx", - "filename": "asg-9.217-3.1.iso", - "filesize": 747606016, - "md5sum": "77bae7dcad422dac428984417573acad", - "version": "9.217-3.1" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Sophos UTM Home Edition", - "port_name_format": "eth{0}", - "product_name": "Sophos UTM Home Edition", - "product_url": "https://www.sophos.com/en-us/products/free-tools/sophos-utm-home-edition.aspx", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "allow", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "usage": "Connect to VNC console for installation, everything else can be set on the WebUI.", - "vendor_name": "Sophos Ltd.", - "vendor_url": "https://www.sophos.com/", - "versions": [ - { - "images": { - "cdrom_image": "asg-9.500-9.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.500-9.1" - }, - { - "images": { - "cdrom_image": "asg-9.413-4.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.413-4.1" - }, - { - "images": { - "cdrom_image": "asg-9.411-3.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.411-3.1" - }, - { - "images": { - "cdrom_image": "asg-9.409-9.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.409-9.1" - }, - { - "images": { - "cdrom_image": "asg-9.408-4.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.408-4.1" - }, - { - "images": { - "cdrom_image": "asg-9.407-3.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.407-3.1" - }, - { - "images": { - "cdrom_image": "asg-9.406-3.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.406-3.1" - }, - { - "images": { - "cdrom_image": "asg-9.405-5.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.405-5.1" - }, - { - "images": { - "cdrom_image": "asg-9.403-4.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.403-4.1" - }, - { - "images": { - "cdrom_image": "asg-9.358-3.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.358-3.1" - }, - { - "images": { - "cdrom_image": "asg-9.357-1.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.357-1.1" - }, - { - "images": { - "cdrom_image": "asg-9.356-3.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.356-3.1" - }, - { - "images": { - "cdrom_image": "asg-9.217-3.1.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "9.217-3.1" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "Sophos XG Firewall delivers the ultimate enterprise firewall performance, security, and control.\n\nFastpath packet optimization technology with up to 140Gbps throughput\nRevolutionary Security Heartbeat\u2122 for improved Advanced Threat Protection (ATP) and response\nPatented Layer-8 user identity control and visibility\nUnified App, Web, QoS, and IPS Policy simplifies management\nApp risk factor and user threat quotient monitors risk levels", - "documentation_url": "https://www.sophos.com/en-us/support/documentation/sophos-xg-firewall.aspx", - "images": [ - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFOS_16.05.4_MR-4.KVM-215-PRIMARY.qcow2", - "filesize": 287113216, - "md5sum": "20535c9e624f42e1977f1e407fbc565e", - "version": "16.05.4 MR4" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFOS_16.05.4_MR-4.KVM-215-AUXILARY.qcow2", - "filesize": 59441152, - "md5sum": "cafac2d997a3ead087d5823b86ce6cb4", - "version": "16.05.1 MR1" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFOS_16.05.1_MR-1.KVM-139-PRIMARY.qcow2", - "filesize": 285671424, - "md5sum": "3d81cf163fb0f4c5c9ba26e92a0ddc13", - "version": "16.05.1 MR1" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFOS_16.05.1_MR-1.KVM-139-AUXILARY.qcow2", - "filesize": 59441152, - "md5sum": "499541728460331a6b68b9e60c8207a3", - "version": "16.05.1 MR1" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFOS_16.05.0_RC-1.KVM-098-PRIMARY.qcow2", - "filesize": 285736960, - "md5sum": "1826ca8a34945de5251876dc3fc7fe63", - "version": "16.05.1 RC1" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFOS_16.05.0_RC-1.KVM-098-AUXILARY.qcow2", - "filesize": 59441152, - "md5sum": "a9c60a65c1e7b5be8369e5ceaeb358f9", - "version": "16.05.1 RC1" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFOS_16.01.1.KVM-202-PRIMARY.qcow2", - "filesize": 277479424, - "md5sum": "818d9f973b7a32c50d9b84814c6f1ee3", - "version": "16.01.1" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFOS_16.01.1.KVM-202-AUXILARY.qcow2", - "filesize": 59441152, - "md5sum": "1f6fc0b751aaec9bfd4401b0e0cbc6dc", - "version": "16.01.1" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFMOS_15.01.0.KVM-301-PRIMARY.qcow2", - "filesize": 706412544, - "md5sum": "a2cb14ed93de1550afef49984b11b56f", - "version": "15.01" - }, - { - "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx", - "filename": "VI-SFMOS_15.01.0.KVM-301-AUXILARY.qcow2", - "filesize": 199168, - "md5sum": "43cf82ac1f7b0eb6550f0e203daa6b96", - "version": "15.01" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Sophos XG Firewall", - "product_name": "Sophos XG Firewall", - "product_url": "https://www.sophos.com/en-us/products/next-gen-firewall.aspx", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "hdb_disk_interface": "virtio", - "kvm": "require", - "ram": 1024 - }, - "registry_version": 3, - "status": "experimental", - "usage": "Port 0 => You computer for the configurtation\nPort 1 => WAN\n\n1. You need a serial number. You can get a trial from Sophos for free.\nUpon starting for the first time, access the setup screen at https://172.16.16.16 (Note: it may take a few minutes for the necessary services to start before the setup screen is ready).\n3. When you are prompted the default administrator credentials are:\nUsername: admin\nPassword: admin\n\n4. Make sure the device is setup for internet access (required for activation): change the network settings from the Basic Setup screen if necessary.\n5. Enter your serial number (provided below) into the setup screen and click \"Activate Device\".\n6. Then register your device with your MySophos ID by clicking \"Register Device\" and entering your MySophos ID and password that you used to download the software.\\\n7. Once the device is registered, you can initiate License Synchronization and proceed with the rest of the configuration.", - "vendor_name": "Sophos", - "vendor_url": "https://www.sophos.com", - "versions": [ - { - "images": { - "hda_disk_image": "VI-SFOS_16.05.4_MR-4.KVM-215-PRIMARY.qcow2", - "hdb_disk_image": "VI-SFOS_16.05.4_MR-4.KVM-215-AUXILARY.qcow2" - }, - "name": "16.05.4 MR4" - }, - { - "images": { - "hda_disk_image": "VI-SFOS_16.05.1_MR-1.KVM-139-PRIMARY.qcow2", - "hdb_disk_image": "VI-SFOS_16.05.1_MR-1.KVM-139-AUXILARY.qcow2" - }, - "name": "16.05.1 MR1" - }, - { - "images": { - "hda_disk_image": "VI-SFOS_16.05.0_RC-1.KVM-098-PRIMARY.qcow2", - "hdb_disk_image": "VI-SFOS_16.05.0_RC-1.KVM-098-AUXILARY.qcow2" - }, - "name": "16.05.1 MR1" - }, - { - "images": { - "hda_disk_image": "VI-SFOS_16.01.1.KVM-202-PRIMARY.qcow2", - "hdb_disk_image": "VI-SFOS_16.01.1.KVM-202-AUXILARY.qcow2" - }, - "name": "16.01.1" - }, - { - "images": { - "hda_disk_image": "VI-SFMOS_15.01.0.KVM-301-PRIMARY.qcow2", - "hdb_disk_image": "VI-SFMOS_15.01.0.KVM-301-AUXILARY.qcow2" - }, - "name": "15.01" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Core Linux is a smaller variant of Tiny Core without a graphical desktop.\n\nIt's provide a complete Linux system in few MB.", - "documentation_url": "http://wiki.tinycorelinux.net/", - "images": [ - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-tinycore-linux-6.4-2.img", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "linux-tinycore-6.4-2.img", - "filesize": 36503552, - "md5sum": "dcbb5318c3e18ab085088d4474d8de85", - "version": "6.4" - }, - { - "direct_download_url": "http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-tinycore-linux-6.4.img", - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "filename": "linux-tinycore-6.4.img", - "filesize": 22544384, - "md5sum": "e3de478780c0acb76ef92f872fe734c4", - "version": "6.4" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Tiny Core Linux", - "product_name": "Tiny Core Linux", - "product_url": "http://distro.ibiblio.org/tinycorelinux", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "i386", - "console_type": "vnc", - "kvm": "allow", - "options": "-vga std -usbdevice tablet", - "ram": 96 - }, - "registry_version": 3, - "status": "stable", - "symbol": "linux_guest.svg", - "usage": "Login is gns3/gns3. sudo works without password", - "vendor_name": "Team Tiny Core", - "vendor_url": "http://distro.ibiblio.org/tinycorelinux", - "versions": [ - { - "images": { - "hda_disk_image": "linux-tinycore-6.4-2.img" - }, - "name": "6.4~2" - }, - { - "images": { - "hda_disk_image": "linux-tinycore-6.4.img" - }, - "name": "6.4~1" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "Trend Micro InterScan Messaging Security stops email threats in the cloud with global threat intelligence, protects your data with data loss prevention and encryption, and identifies targeted email attacks,ransomware, and APTs as part of the Trend Micro Network Defense Solution. The hybrid SaaS deployment combines the privacy and control of an on-premises virtual appliance with the proactive protection of a cloud-based pre-filter service. It\u2019s the enterprise-level protection you need with the highest spam and phishing detection rates\u2014consistently #1 in quarterly Opus One competitive tests since 2011.", - "documentation_url": "https://success.trendmicro.com/product-support/interscan-messaging-security", - "images": [ - { - "direct_download_url": "http://files.trendmicro.com/products/imsva/9.1/IMSVA-9.1-1600-x86_64-r1.iso", - "download_url": "http://downloadcenter.trendmicro.com/index.php?regs=NABU&clk=latest&clkval=4913&lang_loc=1", - "filename": "IMSVA-9.1-1600-x86-64-r1.iso", - "filesize": 797560832, - "md5sum": "581278e8ddb25486539dfe3ad0b3ac94", - "version": "9.1" - }, - { - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty200G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty200G.qcow2", - "filesize": 200192, - "md5sum": "d1686d2f25695dee32eab9a6f4652c7c", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "IMS VA", - "port_name_format": "eth{0}", - "product_name": "IMS VA", - "product_url": "http://www.trendmicro.com/enterprise/network-security/interscan-message-security/index.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 2, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 4096 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default credentials: admin / imsva", - "vendor_name": "Trend Micro Inc.", - "vendor_url": "http://www.trendmicro.com/", - "versions": [ - { - "images": { - "cdrom_image": "IMSVA-9.1-1600-x86-64-r1.iso", - "hda_disk_image": "empty200G.qcow2" - }, - "name": "9.1" - } - ] - }, - { - "builtin": true, - "category": "firewall", - "description": "Trend Micro InterScan Web Security Virtual Appliance is a secure web gateway that combines application control with zero-day exploit detection, advanced anti-malware and ransomware scanning, real-time web reputation, and flexible URL filtering to provide superior Internet threat protection.", - "documentation_url": "https://success.trendmicro.com/product-support/interscan-web-security-virtual-appliance", - "images": [ - { - "direct_download_url": "http://files.trendmicro.com/products/iwsva/IWSVA-6.5-1200-x86_64.iso", - "download_url": "http://downloadcenter.trendmicro.com/index.php?regs=NABU&clk=latest&clkval=4599&lang_loc=1", - "filename": "IWSVA-6.5-1200-x86_64.iso", - "filesize": 1004965888, - "md5sum": "7eb0d2a44e20b69ae0c3ce73d6cc1182", - "version": "6.5" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty100G.qcow2", - "filesize": 198656, - "md5sum": "1e6409a4523ada212dea2ebc50e50a65", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "IWS VA", - "port_name_format": "eth{0}", - "product_name": "IWS VA", - "product_url": "http://www.trendmicro.com/enterprise/network-security/interscan-web-security/virtual-appliance/index.html", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 4096 - }, - "registry_version": 3, - "status": "stable", - "vendor_name": "Trend Micro Inc.", - "vendor_url": "http://www.trendmicro.com/", - "versions": [ - { - "images": { - "cdrom_image": "IWSVA-6.5-1200-x86_64.iso", - "hda_disk_image": "empty100G.qcow2" - }, - "name": "6.5" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "WordPress is a state-of-the-art publishing platform with a focus on aesthetics, web standards, and usability. It is one of the worlds most popular blog publishing applications, includes tons of powerful core functionality, extendable via literally thousands of plugins, and supports full theming. This appliance includes all the standard features in TurnKey Core too.", - "docker": { - "adapters": 1, - "console_type": "telnet", - "image": "turnkeylinux/wordpress-14.2:latest" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "WordPress", - "product_name": "TurnKey Linux WordPress", - "product_url": "https://www.turnkeylinux.org/wordpress", - "registry_version": 3, - "status": "stable", - "usage": "For security reasons there are no default passwords. All passwords are set at system initialization time.", - "vendor_name": "Turnkey Linux", - "vendor_url": "https://www.turnkeylinux.org/" - }, - { - "builtin": true, - "category": "guest", - "description": "Ubuntu is a full-featured Linux operating system which is based on Debian distribution and freely available with both community and professional support, it comes with Unity as its default desktop environment. There are other flavors of Ubuntu available with other desktops as default like Ubuntu Gnome, Lubuntu, Xubuntu, and so on. A tightly-integrated selection of excellent applications is included, and an incredible variety of add-on software is just a few clicks away. A default installation of Ubuntu contains a wide range of software that includes LibreOffice, Firefox, Empathy, Transmission, etc.", - "documentation_url": "https://help.ubuntu.com", - "images": [ - { - "download_url": "http://www.osboxes.org/ubuntu/", - "filename": "Ubuntu_17.04-VM-64bit.vmdk", - "filesize": 4792123392, - "md5sum": "5c82d69c49ba08179e9a94901f67da1f", - "version": "17.04" - }, - { - "download_url": "http://www.osboxes.org/ubuntu/", - "filename": "Ubuntu_16.10_Yakkety-VM-64bit.vmdk", - "filesize": 9133293568, - "md5sum": "c835f24dbb86f5f61c78d992ed38b6b1", - "version": "16.10" - }, - { - "download_url": "http://www.osboxes.org/ubuntu/", - "filename": "Ubuntu_16.04.3-VM-64bit.vmdk", - "filesize": 4302110720, - "md5sum": "45bccf63f2777e492f022dbf025f67d0", - "version": "16.04" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Ubuntu", - "port_name_format": "eth{0}", - "product_name": "Ubuntu", - "product_url": "https://www.ubuntu.com/desktop", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 1, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "options": "-vga virtio", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "usage": "Username: osboxes\nPassword: osboxes.org", - "vendor_name": "Canonical Inc.", - "vendor_url": "https://www.ubuntu.com", - "versions": [ - { - "images": { - "hda_disk_image": "Ubuntu_17.04-VM-64bit.vmdk" - }, - "name": "17.04" - }, - { - "images": { - "hda_disk_image": "Ubuntu_16.10_Yakkety-VM-64bit.vmdk" - }, - "name": "16.10" - }, - { - "images": { - "hda_disk_image": "Ubuntu_16.04.3-VM-64bit.vmdk" - }, - "name": "16.04" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Ubuntu is a Debian-based Linux operating system, with Unity as its default desktop environment. It is based on free software and named after the Southern African philosophy of ubuntu (literally, \"human-ness\"), which often is translated as \"humanity towards others\" or \"the belief in a universal bond of sharing that connects all humanity\".", - "docker": { - "adapters": 1, - "console_type": "telnet", - "image": "gns3/ubuntu:xenial" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Ubuntu", - "product_name": "Ubuntu", - "registry_version": 3, - "status": "stable", - "symbol": "linux_guest.svg", - "vendor_name": "Canonical", - "vendor_url": "http://www.ubuntu.com" - }, - { - "builtin": true, - "category": "firewall", - "description": "Untangle\u2019s NG Firewall enables you to quickly and easily create the network policies that deliver the perfect balance between security and productivity. Untangle combines Unified Threat Management (UTM)\u2014to address all of the key network threats\u2014with policy management tools that enable you to define access and control by individuals, groups or company-wide. And with industry-leading reports, you\u2019ll have complete visibility into and control over everything that\u2019s happening on your network.", - "documentation_url": "http://wiki.untangle.com/index.php/Main_Page", - "images": [ - { - "download_url": "https://www.untangle.com/get-untangle/", - "filename": "untangle_1310_x64.iso", - "filesize": 588251136, - "md5sum": "dc35aa96e954992e53a8cb244a932ae6", - "version": "13.1.0" - }, - { - "download_url": "https://www.untangle.com/get-untangle/", - "filename": "untangle_1300_x64.iso", - "filesize": 576716800, - "md5sum": "74dcb5c8e0fb400dbd3a9582fc472033", - "version": "13.0.0" - }, - { - "download_url": "https://www.untangle.com/get-untangle/", - "filename": "untangle_1221_x64.iso", - "filesize": 580911104, - "md5sum": "6735942441d487d339b92c1499b0052b", - "version": "12.2.1" - }, - { - "download_url": "https://www.untangle.com/get-untangle/", - "filename": "untangle_1220_x64.iso", - "filesize": 585105408, - "md5sum": "56947f059774f2f0015b6326cf5c63ac", - "version": "12.2.0" - }, - { - "download_url": "https://www.untangle.com/get-untangle/", - "filename": "untangle_1212_x64.iso", - "filesize": 575668224, - "md5sum": "2f48873316725b1f709015dfeb73d666", - "version": "12.1.2" - }, - { - "download_url": "https://www.untangle.com/get-untangle/", - "filename": "untangle_1211_x64.iso", - "filesize": 574619648, - "md5sum": "c7f38df4cbba72fa472a49454e476522", - "version": "12.1.1" - }, - { - "download_url": "https://www.untangle.com/get-untangle/", - "filename": "untangle_1210_x64.iso", - "filesize": 573571072, - "md5sum": "d511cbbd34aac7678c34a111c791806f", - "version": "12.1.0" - }, - { - "download_url": "https://www.untangle.com/get-untangle/", - "filename": "untangle_1201_x64.iso", - "filesize": 611319808, - "md5sum": "905171d04d2f029b193fe76b02ef9e11", - "version": "12.0.1" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty30G.qcow2", - "filesize": 197120, - "md5sum": "3411a599e822f2ac6be560a26405821a", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Untangle NG", - "port_name_format": "eth{0}", - "product_name": "Untangle NG", - "product_url": "https://www.untangle.com/untangle-ng-firewall/", - "qemu": { - "adapter_type": "e1000", - "adapters": 4, - "arch": "x86_64", - "boot_priority": "dc", - "console_type": "vnc", - "hda_disk_interface": "ide", - "kvm": "allow", - "ram": 1024 - }, - "registry_version": 3, - "status": "stable", - "usage": "Run the graphical or text based installer using VNC. The installer warns about insufficient memory but the provided 1G is enough, the installation will be successful.", - "vendor_name": "Untangle", - "vendor_url": "https://www.untangle.com/", - "versions": [ - { - "images": { - "cdrom_image": "untangle_1310_x64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "13.1.0" - }, - { - "images": { - "cdrom_image": "untangle_1300_x64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "13.0.0" - }, - { - "images": { - "cdrom_image": "untangle_1221_x64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "12.2.1" - }, - { - "images": { - "cdrom_image": "untangle_1220_x64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "12.2.0" - }, - { - "images": { - "cdrom_image": "untangle_1212_x64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "12.1.2" - }, - { - "images": { - "cdrom_image": "untangle_1211_x64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "12.1.1" - }, - { - "images": { - "cdrom_image": "untangle_1210_x64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "12.1.0" - }, - { - "images": { - "cdrom_image": "untangle_1201_x64.iso", - "hda_disk_image": "empty30G.qcow2" - }, - "name": "12.0.1" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "vRIN is a VM appliance capable to inject high number of routes into a network. It was tested on GNS3 topologies using VirtualBox and Qemu with up to 1M BGP routes. Runs Quagga. Supported protocols: BGP (IPv4/6), OSPF, OSPFv3, RIP v2, RIPng", - "images": [ - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.9.2.qcow2.bz2/download", - "download_url": "https://sourceforge.net/projects/vrin/files", - "filename": "vRIN-0.9.2.qcow2", - "filesize": 957087744, - "md5sum": "40afad2f5136e56f0cb45466847eae63", - "version": "0.9.2" - }, - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.9.1.qcow2.bz2/download", - "download_url": "https://sourceforge.net/projects/vrin/files", - "filename": "vRIN-0.9.1.qcow2", - "filesize": 1008926720, - "md5sum": "9f09f104917e19649598d9e2a5a3476b", - "version": "0.9.1" - }, - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.9.qcow2.bz2/download", - "download_url": "https://sourceforge.net/projects/vrin/files", - "filename": "vRIN-0.9.qcow2", - "filesize": 922943488, - "md5sum": "b9ec187d7a4743bb02339cf262767959", - "version": "0.9" - }, - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.8.qcow2.bz2/download", - "download_url": "https://sourceforge.net/projects/vrin/files", - "filename": "vRIN-0.8.qcow2", - "filesize": 625999872, - "md5sum": "38eb48d098d3e465422347f7983b9d86", - "version": "0.8" - }, - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.7.qcow2.bz2/download", - "download_url": "https://sourceforge.net/projects/vrin/files", - "filename": "vRIN-0.7.qcow2", - "filesize": 614268928, - "md5sum": "2e9802c403e34a91871922b9a26592ad", - "version": "0.7" - }, - { - "compression": "bzip2", - "direct_download_url": "http://sourceforge.net/projects/vrin/files/vRIN-0.6.qcow2.bz2/download", - "download_url": "https://sourceforge.net/projects/vrin/files", - "filename": "vRIN-0.6.qcow2", - "filesize": 609681408, - "md5sum": "6c763f609c05b5b9a3b1d422ab89dbac", - "version": "0.6" - } - ], - "maintainer": "Andras Dosztal", - "maintainer_email": "developers@gns3.net", - "name": "vRIN", - "product_name": "vRIN", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "x86_64", - "console_type": "telnet", - "kvm": "allow", - "ram": 256 - }, - "registry_version": 3, - "status": "stable", - "symbol": "vRIN.svg", - "usage": "Connect eth0 to the network where you want vRIN to inject routes into then start the VM. You can either run the VM in normal or headless mode; in the latter case you can access vRIN through serial console. User input is not checked; it's your responsibility to enter valid information.\n\nAfter generating the routes, each Quagga process can be reached through eth0 using their default ports:\n - zebra: 2601\n - rip: 2602\n - ripng: 2603\n - ospf: 2604\n - bgp: 2605\n - ospf6d: 2606\nVTY password: vrin\n\nNotes:\n\n - Route generation may take a while when creating lots of routes (i.e. 10k+).\n - Login (serial / VM window): root / vrin", - "vendor_name": "Andras Dosztal", - "vendor_url": "https://sourceforge.net/projects/vrin/", - "versions": [ - { - "images": { - "hda_disk_image": "vRIN-0.9.2.qcow2" - }, - "name": "0.9.2" - }, - { - "images": { - "hda_disk_image": "vRIN-0.9.1.qcow2" - }, - "name": "0.9.1" - }, - { - "images": { - "hda_disk_image": "vRIN-0.9.qcow2" - }, - "name": "0.9" - }, - { - "images": { - "hda_disk_image": "vRIN-0.8.qcow2" - }, - "name": "0.8" - }, - { - "images": { - "hda_disk_image": "vRIN-0.7.qcow2" - }, - "name": "0.7" - }, - { - "images": { - "hda_disk_image": "vRIN-0.6.qcow2" - }, - "name": "0.6" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "VyOS is a community fork of Vyatta, a Linux-based network operating system that provides software-based network routing, firewall, and VPN functionality.", - "documentation_url": "http://vyos.net/wiki/User_Guide", - "images": [ - { - "direct_download_url": "http://dev.packages.vyos.net/iso/preview/1.2.0-beta1/vyos-1.2.0-beta1-amd64.iso", - "download_url": "http://dev.packages.vyos.net/iso/preview/1.2.0-beta1/", - "filename": "vyos-1.2.0-beta1-amd64.iso", - "filesize": 243269632, - "md5sum": "c2906532d4c7a0d29b61e8eab326d6c7", - "version": "1.2.0-beta1" - }, - { - "direct_download_url": "http://mirror.vyos.net/iso/release/1.1.7/vyos-1.1.7-amd64.iso", - "download_url": "http://mirror.vyos.net/iso/release/1.1.7/", - "filename": "vyos-1.1.7-amd64.iso", - "filesize": 245366784, - "md5sum": "9a7f745a0b0db0d4f1d9eee2a437fb54", - "version": "1.1.7" - }, - { - "direct_download_url": "http://mirror.vyos.net/iso/release/1.1.6/vyos-1.1.6-amd64.iso", - "download_url": "http://mirror.vyos.net/iso/release/1.1.6/", - "filename": "vyos-1.1.6-amd64.iso", - "filesize": 245366784, - "md5sum": "3128954d026e567402a924c2424ce2bf", - "version": "1.1.6" - }, - { - "direct_download_url": "http://mirror.vyos.net/iso/release/1.1.5/vyos-1.1.5-amd64.iso", - "download_url": "http://mirror.vyos.net/iso/release/1.1.5/", - "filename": "vyos-1.1.5-amd64.iso", - "filesize": 247463936, - "md5sum": "193179532011ceaa87ee725bd8f22022", - "version": "1.1.5" - }, - { - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty8G.qcow2", - "filesize": 197120, - "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "VyOS", - "port_name_format": "eth{0}", - "product_name": "VyOS", - "product_url": "http://vyos.net/", - "qemu": { - "adapter_type": "e1000", - "adapters": 3, - "arch": "x86_64", - "boot_priority": "dc", - "console_type": "telnet", - "kvm": "allow", - "ram": 512 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default username/password is vyos/vyos. At first boot the router will start from the cdrom, login and then type install system and follow the instructions.", - "vendor_name": "Linux", - "vendor_url": "http://vyos.net/", - "versions": [ - { - "images": { - "cdrom_image": "vyos-1.2.0-beta1-amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "1.2.0-beta1" - }, - { - "images": { - "cdrom_image": "vyos-1.1.7-amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "1.1.7" - }, - { - "images": { - "cdrom_image": "vyos-1.1.6-amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "1.1.6" - }, - { - "images": { - "cdrom_image": "vyos-1.1.5-amd64.iso", - "hda_disk_image": "empty8G.qcow2" - }, - "name": "1.1.5" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "webterm is a debian based networking toolbox.\nIt contains the firefox web browser plus the following utilities: net-tools, iproute2, ping, traceroute, curl, host, iperf3, mtr, socat, ssh client, tcpdump, ab(apache benchmark) and the multicast testing tools msend/mreceive.", - "docker": { - "adapters": 1, - "console_type": "vnc", - "image": "gns3/webterm:latest" - }, - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "webterm", - "product_name": "webterm", - "registry_version": 3, - "status": "stable", - "symbol": "firefox.svg", - "usage": "The /root directory is persistent.", - "vendor_name": "webterm", - "vendor_url": "https://www.debian.org" - }, - { - "builtin": true, - "category": "guest", - "description": "Microsoft Windows, or simply Windows, is a metafamily of graphical operating systems developed, marketed, and sold by Microsoft. It consists of several families of operating systems, each of which cater to a certain sector of the computing industry with the OS typically associated with IBM PC compatible architecture.", - "documentation_url": "https://technet.microsoft.com/en-us/library/cc498727.aspx", - "images": [ - { - "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", - "filename": "MSEdge_-_Win10_preview.vmdk", - "filesize": 10907287552, - "md5sum": "e06d97b871581d91b7363bf72a81553d", - "version": "10 w/ Edge" - }, - { - "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", - "filename": "IE11_-_Win8.1-disk1.vmdk", - "filesize": 5704344064, - "md5sum": "6c8691c7d58bf2c33f6ca242ace6b9bd", - "version": "8.1 w/ IE11" - }, - { - "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", - "filename": "IE11_-_Win7-disk1.vmdk", - "filesize": 4101495296, - "md5sum": "5733cc93a6ed756c2358f0a383b411a8", - "version": "7 w/ IE11" - }, - { - "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", - "filename": "IE10_-_Win7-disk1.vmdk", - "filesize": 4062174208, - "md5sum": "ed18b5903fb7d778b847c8d1cef807c4", - "version": "7 w/ IE10" - }, - { - "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", - "filename": "IE9_-_Win7-disk1.vmdk", - "filesize": 4040829440, - "md5sum": "82370cfa215002a49651b773a3a569f2", - "version": "7 w/ IE9" - }, - { - "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/", - "filename": "IE8_-_Win7-disk1.vmdk", - "filesize": 4228026368, - "md5sum": "63456b42eb8e184b3e7c675645a3c32c", - "version": "7 w/ IE8" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Windows", - "port_name_format": "NIC{port1}", - "product_name": "Windows", - "product_url": "https://www.microsoft.com/en-us/windows", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "sata", - "kvm": "require", - "ram": 1024 - }, - "registry_version": 4, - "status": "stable", - "symbol": "microsoft.svg", - "usage": "These virtual machines expire after 90 days; i.e. you have to re-create them in your project after this time but you don't have to re-import the appliance.\n\nDefault credentials: IEUser / Passw0rd!", - "vendor_name": "Microsoft", - "vendor_url": "http://www.microsoft.com/", - "versions": [ - { - "images": { - "hda_disk_image": "MSEdge_-_Win10_preview.vmdk" - }, - "name": "10 w/ Edge" - }, - { - "images": { - "hda_disk_image": "IE11_-_Win8.1-disk1.vmdk" - }, - "name": "8.1 w/ IE11" - }, - { - "images": { - "hda_disk_image": "IE11_-_Win7-disk1.vmdk" - }, - "name": "7 w/ IE11" - }, - { - "images": { - "hda_disk_image": "IE10_-_Win7-disk1.vmdk" - }, - "name": "7 w/ IE10" - }, - { - "images": { - "hda_disk_image": "IE9_-_Win7-disk1.vmdk" - }, - "name": "7 w/ IE9" - }, - { - "images": { - "hda_disk_image": "IE8_-_Win7-disk1.vmdk" - }, - "name": "7 w/ IE8" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "Microsoft Windows, or simply Windows, is a metafamily of graphical operating systems developed, marketed, and sold by Microsoft. It consists of several families of operating systems, each of which cater to a certain sector of the computing industry with the OS typically associated with IBM PC compatible architecture.", - "documentation_url": "https://technet.microsoft.com/en-us/library/cc498727.aspx", - "images": [ - { - "download_url": "https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2016", - "filename": "Win2k16_14393.0.161119-1705.RS1_REFRESH_SERVER_EVAL_X64FRE_EN-US.ISO", - "filesize": 6972221440, - "md5sum": "70721288bbcdfe3239d8f8c0fae55f1f", - "version": "2016" - }, - { - "download_url": "https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2012-r2", - "filename": "Win2k12_9600.16415.amd64fre.winblue_refresh.130928-2229_server_serverdatacentereval_en-us.vhd", - "filesize": 8024756224, - "md5sum": "b0a988a2e1f401c99c7c18a00391c4cc", - "version": "2012 R2" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty100G.qcow2", - "filesize": 198656, - "md5sum": "1e6409a4523ada212dea2ebc50e50a65", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Windows Server", - "port_name_format": "NIC{port1}", - "product_name": "Windows Server", - "product_url": "https://www.microsoft.com/en-us/windows", - "qemu": { - "adapter_type": "e1000", - "adapters": 1, - "arch": "x86_64", - "boot_priority": "c", - "console_type": "vnc", - "hda_disk_interface": "sata", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 4, - "status": "stable", - "symbol": "microsoft.svg", - "vendor_name": "Microsoft", - "vendor_url": "http://www.microsoft.com/", - "versions": [ - { - "images": { - "cdrom_image": "Win2k16_14393.0.161119-1705.RS1_REFRESH_SERVER_EVAL_X64FRE_EN-US.ISO", - "hda_disk_image": "empty100G.qcow2" - }, - "name": "2016" - }, - { - "images": { - "hda_disk_image": "Win2k12_9600.16415.amd64fre.winblue_refresh.130928-2229_server_serverdatacentereval_en-us.vhd" - }, - "name": "2012 R2" - } - ] - }, - { - "builtin": true, - "category": "guest", - "description": "The on-premise Mail and Directory server. Native compatibility with Microsoft Active Directory. You can control your IT infrastructure from a single point of user management, regardless of the different offices and locations your business has. True Microsoft Outlook compatibility. Your users can continue using their favorite email clients, without any service interruptions and without having to install any plug-in or connector.", - "documentation_url": "https://wiki.zentyal.org/wiki/Zentyal_Wiki", - "images": [ - { - "direct_download_url": "http://download.zentyal.com/zentyal-5.0.1-development-amd64.iso", - "download_url": "http://download.zentyal.com/", - "filename": "zentyal-5.0.1-development-amd64.iso", - "filesize": 953155584, - "md5sum": "1ac74be6563f0b21b337c274e62cdd32", - "version": "5.0.1" - }, - { - "direct_download_url": "http://download.zentyal.com/zentyal-5.0-development-amd64.iso", - "download_url": "http://download.zentyal.com/", - "filename": "zentyal-5.0-development-amd64.iso", - "filesize": 914565120, - "md5sum": "ddaa3b2bf2cd6cae8bcfbcb88ca636a8", - "version": "5.0" - }, - { - "direct_download_url": "http://download.zentyal.com/zentyal-4.2-development-amd64.iso", - "download_url": "http://download.zentyal.com/", - "filename": "zentyal-4.2-development-amd64.iso", - "filesize": 629284864, - "md5sum": "22b165a49adbc4eff033ced01e71fe3a", - "version": "4.2" - }, - { - "direct_download_url": "http://download.zentyal.com/zentyal-4.1-development-amd64.iso", - "download_url": "http://download.zentyal.com/", - "filename": "zentyal-4.1-development-amd64.iso", - "filesize": 612206592, - "md5sum": "40a8ff15a60ff862a110a17f941edf2a", - "version": "4.1" - }, - { - "direct_download_url": "http://download.zentyal.com/zentyal-4.0-amd64.iso", - "download_url": "http://download.zentyal.com/", - "filename": "zentyal-4.0-amd64.iso", - "filesize": 666370048, - "md5sum": "d63b15f1edcd2c3c03ab3a36e833e211", - "version": "4.0" - }, - { - "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download", - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "filename": "empty100G.qcow2", - "filesize": 198656, - "md5sum": "1e6409a4523ada212dea2ebc50e50a65", - "version": "1.0" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "Zentyal Server", - "port_name_format": "eth{0}", - "product_name": "Zentyal Server", - "product_url": "http://www.zentyal.com/zentyal-server/", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 3, - "arch": "x86_64", - "boot_priority": "cd", - "console_type": "vnc", - "hda_disk_interface": "virtio", - "kvm": "require", - "ram": 2048 - }, - "registry_version": 3, - "status": "stable", - "usage": "Follow installation instructions. Once the installation process is done, you can access the web interface using a web browser: https://:8443/", - "vendor_name": "Zentyal S.L.", - "vendor_url": "http://www.zentyal.com/", - "versions": [ - { - "images": { - "cdrom_image": "zentyal-5.0.1-development-amd64.iso", - "hda_disk_image": "empty100G.qcow2" - }, - "name": "5.0.1" - }, - { - "images": { - "cdrom_image": "zentyal-5.0-development-amd64.iso", - "hda_disk_image": "empty100G.qcow2" - }, - "name": "5.0" - }, - { - "images": { - "cdrom_image": "zentyal-4.2-development-amd64.iso", - "hda_disk_image": "empty100G.qcow2" - }, - "name": "4.2" - }, - { - "images": { - "cdrom_image": "zentyal-4.1-development-amd64.iso", - "hda_disk_image": "empty100G.qcow2" - }, - "name": "4.1" - }, - { - "images": { - "cdrom_image": "zentyal-4.0-amd64.iso", - "hda_disk_image": "empty100G.qcow2" - }, - "name": "4.0" - } - ] - }, - { - "builtin": true, - "category": "router", - "description": "Zeroshell is a Linux distribution for servers and embedded devices aimed at providing the main network services a LAN requires. It is available in the form of Live CD or Compact Flash image and you can configure and administer it using your web browser.", - "documentation_url": "http://www.zeroshell.org/documentation/", - "images": [ - { - "compression": "gzip", - "direct_download_url": "http://www.zeroshell.net/listing/ZeroShell-3.8.0-X86-USB.img.gz", - "download_url": "http://www.zeroshell.org/download/", - "filename": "ZeroShell-3.8.0-X86-USB.img", - "filesize": 1992294400, - "md5sum": "a16d584c831f3e88ea442a2343d71cfa", - "version": "3.8.0" - }, - { - "compression": "gzip", - "direct_download_url": "http://www.zeroshell.net/listing/ZeroShell-3.7.1-USB.img.gz", - "download_url": "http://www.zeroshell.org/download/", - "filename": "ZeroShell-3.7.1-USB.img", - "filesize": 1992294400, - "md5sum": "22e739a24dc1c233d3eca5d8fedc97c8", - "version": "3.7.1" - } - ], - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "name": "ZeroShell", - "product_name": "ZeroShell", - "qemu": { - "adapter_type": "e1000", - "adapters": 4, - "arch": "x86_64", - "console_type": "vnc", - "kvm": "allow", - "ram": 256 - }, - "registry_version": 3, - "status": "stable", - "usage": "Default WebUI credentials: admin / zeroshell", - "vendor_name": "Fulvio Ricciardi", - "vendor_url": "http://www.zeroshell.org", - "versions": [ - { - "images": { - "hda_disk_image": "ZeroShell-3.8.0-X86-USB.img" - }, - "name": "3.8.0" - }, - { - "images": { - "hda_disk_image": "ZeroShell-3.7.1-USB.img" - }, - "name": "3.7.1" - } - ] - } -] diff --git a/docs/api/examples/controller_get_computes.txt b/docs/api/examples/controller_get_computes.txt index 51ea9fbd..fb7ab126 100644 --- a/docs/api/examples/controller_get_computes.txt +++ b/docs/api/examples/controller_get_computes.txt @@ -6,10 +6,10 @@ GET /v2/computes HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 387 +Content-Length: 415 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:22 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:46 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/computes [ @@ -22,6 +22,7 @@ X-Route: /v2/computes "connected": false, "cpu_usage_percent": null, "host": "localhost", + "last_error": null, "memory_usage_percent": null, "name": "My super server", "port": 84, diff --git a/docs/api/examples/controller_get_computescomputeid.txt b/docs/api/examples/controller_get_computescomputeid.txt index 4ed46759..83ed8f69 100644 --- a/docs/api/examples/controller_get_computescomputeid.txt +++ b/docs/api/examples/controller_get_computescomputeid.txt @@ -6,10 +6,10 @@ GET /v2/computes/my_compute_id HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 334 +Content-Length: 358 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:17 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:46 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/computes/{compute_id} { @@ -21,6 +21,7 @@ X-Route: /v2/computes/{compute_id} "connected": false, "cpu_usage_percent": null, "host": "localhost", + "last_error": null, "memory_usage_percent": null, "name": "http://julien@localhost:84", "port": 84, diff --git a/docs/api/examples/controller_get_computescomputeidemulatoraction.txt b/docs/api/examples/controller_get_computescomputeidemulatoraction.txt index 1c479214..c33b1eee 100644 --- a/docs/api/examples/controller_get_computescomputeidemulatoraction.txt +++ b/docs/api/examples/controller_get_computescomputeidemulatoraction.txt @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 2 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:28 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:47 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/computes/{compute_id}/{emulator}/{action:.+} [] diff --git a/docs/api/examples/controller_get_computescomputeidemulatorimages.txt b/docs/api/examples/controller_get_computescomputeidemulatorimages.txt index 29023922..612fea3a 100644 --- a/docs/api/examples/controller_get_computescomputeidemulatorimages.txt +++ b/docs/api/examples/controller_get_computescomputeidemulatorimages.txt @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 95 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:27 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:47 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/computes/{compute_id}/{emulator}/images [ diff --git a/docs/api/examples/controller_get_gns3vm.txt b/docs/api/examples/controller_get_gns3vm.txt index c4219632..46d418e9 100644 --- a/docs/api/examples/controller_get_gns3vm.txt +++ b/docs/api/examples/controller_get_gns3vm.txt @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 148 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:49 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/gns3vm { diff --git a/docs/api/examples/controller_get_gns3vmengines.txt b/docs/api/examples/controller_get_gns3vmengines.txt index 738fc178..e7df471c 100644 --- a/docs/api/examples/controller_get_gns3vmengines.txt +++ b/docs/api/examples/controller_get_gns3vmengines.txt @@ -6,23 +6,23 @@ GET /v2/gns3vm/engines HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 1106 +Content-Length: 1134 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/gns3vm/engines [ { - "description": "VMware is the recommended choice for best performances.
The GNS3 VM can be downloaded here.", + "description": "VMware is the recommended choice for best performances.
The GNS3 VM can be downloaded here.", "engine_id": "vmware", - "name": "VMware Fusion", + "name": "VMware Workstation / Player (recommended)", "support_headless": true, "support_ram": true, "support_when_exit": true }, { - "description": "VirtualBox doesn't support nested virtualization, this means running Qemu based VM could be very slow.
The GNS3 VM can be downloaded here", + "description": "VirtualBox doesn't support nested virtualization, this means Qemu based VMs will run extremely slowly.
The GNS3 VM can be downloaded here", "engine_id": "virtualbox", "name": "VirtualBox", "support_headless": true, diff --git a/docs/api/examples/controller_get_gns3vmenginesenginevms.txt b/docs/api/examples/controller_get_gns3vmenginesenginevms.txt index 841363aa..7f3155e7 100644 --- a/docs/api/examples/controller_get_gns3vmenginesenginevms.txt +++ b/docs/api/examples/controller_get_gns3vmenginesenginevms.txt @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 40 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/gns3vm/engines/{engine}/vms [ diff --git a/docs/api/examples/controller_get_projects.txt b/docs/api/examples/controller_get_projects.txt index a4e0c19c..133ddb61 100644 --- a/docs/api/examples/controller_get_projects.txt +++ b/docs/api/examples/controller_get_projects.txt @@ -6,10 +6,10 @@ GET /v2/projects HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 578 +Content-Length: 637 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:38 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:00 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects [ @@ -17,9 +17,11 @@ X-Route: /v2/projects "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "test.gns3", + "grid_size": 75, "name": "test", - "path": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_list_projects1", + "path": "/tmp/pytest-of-grossmj/pytest-0/test_list_projects1", "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f", "scene_height": 1000, "scene_width": 2000, @@ -28,6 +30,8 @@ X-Route: /v2/projects "show_layers": false, "snap_to_grid": false, "status": "opened", + "supplier": null, + "variables": null, "zoom": 100 } ] diff --git a/docs/api/examples/controller_get_projectsprojectid.txt b/docs/api/examples/controller_get_projectsprojectid.txt index bf3373d9..3280cbee 100644 --- a/docs/api/examples/controller_get_projectsprojectid.txt +++ b/docs/api/examples/controller_get_projectsprojectid.txt @@ -1,25 +1,27 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/0f1cab8c-a85f-46a7-b2d8-360aacffe2f2' +curl -i -X GET 'http://localhost:3080/v2/projects/e169fb2d-2000-416a-b305-8867e9705061' -GET /v2/projects/0f1cab8c-a85f-46a7-b2d8-360aacffe2f2 HTTP/1.1 +GET /v2/projects/e169fb2d-2000-416a-b305-8867e9705061 HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 509 +Content-Length: 560 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:38 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:00 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id} { "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "test.gns3", + "grid_size": 75, "name": "test", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp5gvzxbg_/projects/0f1cab8c-a85f-46a7-b2d8-360aacffe2f2", - "project_id": "0f1cab8c-a85f-46a7-b2d8-360aacffe2f2", + "path": "/tmp/tmpgib4zai7/projects/e169fb2d-2000-416a-b305-8867e9705061", + "project_id": "e169fb2d-2000-416a-b305-8867e9705061", "scene_height": 1000, "scene_width": 2000, "show_grid": false, @@ -27,5 +29,7 @@ X-Route: /v2/projects/{project_id} "show_layers": false, "snap_to_grid": false, "status": "opened", + "supplier": null, + "variables": null, "zoom": 100 } diff --git a/docs/api/examples/controller_get_projectsprojectiddrawings.txt b/docs/api/examples/controller_get_projectsprojectiddrawings.txt index 88a474e8..9e7f1919 100644 --- a/docs/api/examples/controller_get_projectsprojectiddrawings.txt +++ b/docs/api/examples/controller_get_projectsprojectiddrawings.txt @@ -1,21 +1,22 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/6170501f-a3d6-4ab7-82e7-57b4394538f8/drawings' +curl -i -X GET 'http://localhost:3080/v2/projects/a962f4d7-b5dd-4db2-8a73-ca8c30418fce/drawings' -GET /v2/projects/6170501f-a3d6-4ab7-82e7-57b4394538f8/drawings HTTP/1.1 +GET /v2/projects/a962f4d7-b5dd-4db2-8a73-ca8c30418fce/drawings HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 363 +Content-Length: 388 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/drawings [ { - "drawing_id": "b6e1dcb4-442c-4c55-a1eb-537f57ee7974", - "project_id": "6170501f-a3d6-4ab7-82e7-57b4394538f8", + "drawing_id": "250e1fbb-2a72-43c5-8398-eea0b3df9b74", + "locked": false, + "project_id": "a962f4d7-b5dd-4db2-8a73-ca8c30418fce", "rotation": 0, "svg": "", "x": 10, diff --git a/docs/api/examples/controller_get_projectsprojectiddrawingsdrawingid.txt b/docs/api/examples/controller_get_projectsprojectiddrawingsdrawingid.txt index 9f62f817..47905d83 100644 --- a/docs/api/examples/controller_get_projectsprojectiddrawingsdrawingid.txt +++ b/docs/api/examples/controller_get_projectsprojectiddrawingsdrawingid.txt @@ -1,20 +1,21 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/b1310dc0-c0f9-43ca-b1b6-dca48187ca20/drawings/571eda2c-6b71-4d1f-bff7-92a1c63c6622' +curl -i -X GET 'http://localhost:3080/v2/projects/43ecb128-b584-4900-9da6-020cf1b0fa46/drawings/1453d6ed-bfac-4ddc-a495-ff3ecfac03de' -GET /v2/projects/b1310dc0-c0f9-43ca-b1b6-dca48187ca20/drawings/571eda2c-6b71-4d1f-bff7-92a1c63c6622 HTTP/1.1 +GET /v2/projects/43ecb128-b584-4900-9da6-020cf1b0fa46/drawings/1453d6ed-bfac-4ddc-a495-ff3ecfac03de HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 323 +Content-Length: 344 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/drawings/{drawing_id} { - "drawing_id": "571eda2c-6b71-4d1f-bff7-92a1c63c6622", - "project_id": "b1310dc0-c0f9-43ca-b1b6-dca48187ca20", + "drawing_id": "1453d6ed-bfac-4ddc-a495-ff3ecfac03de", + "locked": false, + "project_id": "43ecb128-b584-4900-9da6-020cf1b0fa46", "rotation": 0, "svg": "", "x": 10, diff --git a/docs/api/examples/controller_get_projectsprojectidlinks.txt b/docs/api/examples/controller_get_projectsprojectidlinks.txt index ed574f78..2603bfc3 100644 --- a/docs/api/examples/controller_get_projectsprojectidlinks.txt +++ b/docs/api/examples/controller_get_projectsprojectidlinks.txt @@ -1,6 +1,6 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/9ca80ee5-8396-4c65-a477-874532d42ed3/links' +curl -i -X GET 'http://localhost:3080/v2/projects/42ee96fe-5802-4164-86d7-f4b8fec50eea/links' -GET /v2/projects/9ca80ee5-8396-4c65-a477-874532d42ed3/links HTTP/1.1 +GET /v2/projects/42ee96fe-5802-4164-86d7-f4b8fec50eea/links HTTP/1.1 @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 1293 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:36 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:50 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/links [ @@ -25,7 +25,7 @@ X-Route: /v2/projects/{project_id}/links 10 ] }, - "link_id": "d61729b0-e4c8-4d29-9e37-ed7997d2fcd8", + "link_id": "423fceec-5297-4fa4-8ae7-be7abfeef98e", "link_type": "ethernet", "nodes": [ { @@ -37,7 +37,7 @@ X-Route: /v2/projects/{project_id}/links "x": -10, "y": -10 }, - "node_id": "2384cb6c-1783-4872-9c9e-91f015dee027", + "node_id": "2d322416-e9af-4665-8a85-13fbde3b100d", "port_number": 3 }, { @@ -49,11 +49,11 @@ X-Route: /v2/projects/{project_id}/links "x": -10, "y": -10 }, - "node_id": "a679eb04-b702-4353-baa2-3554e49396b1", + "node_id": "69dae8da-bded-4b8b-baea-e1bb280432bf", "port_number": 4 } ], - "project_id": "9ca80ee5-8396-4c65-a477-874532d42ed3", + "project_id": "42ee96fe-5802-4164-86d7-f4b8fec50eea", "suspend": false } ] diff --git a/docs/api/examples/controller_get_projectsprojectidlinkslinkid.txt b/docs/api/examples/controller_get_projectsprojectidlinkslinkid.txt index 8689f8b6..51b94a91 100644 --- a/docs/api/examples/controller_get_projectsprojectidlinkslinkid.txt +++ b/docs/api/examples/controller_get_projectsprojectidlinkslinkid.txt @@ -1,6 +1,6 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/23093d79-3767-40fa-a4d2-d6cb9b8b3ad6/links/5ef12b17-0fcd-41c3-b14d-ac9a123fd260' +curl -i -X GET 'http://localhost:3080/v2/projects/2ad49559-0d08-4538-8d06-a6b69c5e57d2/links/44dc3840-41ab-4357-9f50-20e6291d873a' -GET /v2/projects/23093d79-3767-40fa-a4d2-d6cb9b8b3ad6/links/5ef12b17-0fcd-41c3-b14d-ac9a123fd260 HTTP/1.1 +GET /v2/projects/2ad49559-0d08-4538-8d06-a6b69c5e57d2/links/44dc3840-41ab-4357-9f50-20e6291d873a HTTP/1.1 @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 916 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:36 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:49 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/links/{link_id} { @@ -17,7 +17,7 @@ X-Route: /v2/projects/{project_id}/links/{link_id} "capture_file_path": null, "capturing": false, "filters": {}, - "link_id": "5ef12b17-0fcd-41c3-b14d-ac9a123fd260", + "link_id": "44dc3840-41ab-4357-9f50-20e6291d873a", "link_type": "ethernet", "nodes": [ { @@ -27,7 +27,7 @@ X-Route: /v2/projects/{project_id}/links/{link_id} "x": 42, "y": 0 }, - "node_id": "ad56b649-841c-4212-ad67-47e8637f86ca", + "node_id": "6a004c91-7ec6-4b13-aec2-c5744331ecb7", "port_number": 3 }, { @@ -39,10 +39,10 @@ X-Route: /v2/projects/{project_id}/links/{link_id} "x": -10, "y": -10 }, - "node_id": "4f2ca049-53e8-4cd1-bd81-396e2b2b40d1", + "node_id": "b7d6ea4c-64c7-4c40-8283-01d8bfc8d1c4", "port_number": 4 } ], - "project_id": "23093d79-3767-40fa-a4d2-d6cb9b8b3ad6", + "project_id": "2ad49559-0d08-4538-8d06-a6b69c5e57d2", "suspend": false } diff --git a/docs/api/examples/controller_get_projectsprojectidlinkslinkidavailablefilters.txt b/docs/api/examples/controller_get_projectsprojectidlinkslinkidavailablefilters.txt index e7749078..93339498 100644 --- a/docs/api/examples/controller_get_projectsprojectidlinkslinkidavailablefilters.txt +++ b/docs/api/examples/controller_get_projectsprojectidlinkslinkidavailablefilters.txt @@ -1,6 +1,6 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/e727375f-2f2b-4f23-9077-d73059f35e3a/links/cfb0fcc4-a5b2-4b53-9c56-487b297c8681/available_filters' +curl -i -X GET 'http://localhost:3080/v2/projects/82293170-31f4-437b-ab35-d7c6fda93f68/links/9a99a02e-07b4-4f07-8851-526be5a41276/available_filters' -GET /v2/projects/e727375f-2f2b-4f23-9077-d73059f35e3a/links/cfb0fcc4-a5b2-4b53-9c56-487b297c8681/available_filters HTTP/1.1 +GET /v2/projects/82293170-31f4-437b-ab35-d7c6fda93f68/links/9a99a02e-07b4-4f07-8851-526be5a41276/available_filters HTTP/1.1 @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 2119 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:36 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/links/{link_id}/available_filters [ diff --git a/docs/api/examples/controller_get_projectsprojectidnodes.txt b/docs/api/examples/controller_get_projectsprojectidnodes.txt index df433eb4..d3d7412a 100644 --- a/docs/api/examples/controller_get_projectsprojectidnodes.txt +++ b/docs/api/examples/controller_get_projectsprojectidnodes.txt @@ -1,15 +1,15 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/33278936-718c-4161-8fc3-7af4aa39581f/nodes' +curl -i -X GET 'http://localhost:3080/v2/projects/08c7f9e8-6ef5-4793-8edc-0898d49c25f9/nodes' -GET /v2/projects/33278936-718c-4161-8fc3-7af4aa39581f/nodes HTTP/1.1 +GET /v2/projects/08c7f9e8-6ef5-4793-8edc-0898d49c25f9/nodes HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 1303 +Content-Length: 1397 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes [ @@ -17,20 +17,23 @@ X-Route: /v2/projects/{project_id}/nodes "command_line": null, "compute_id": "example.com", "console": 2048, - "console_host": "", + "console_auto_start": false, + "console_host": "", "console_type": null, + "custom_adapters": [], "first_port_name": null, "height": 59, "label": { "rotation": 0, - "style": "font-size: 10;font-familly: Verdana", + "style": null, "text": "test", "x": null, "y": -40 }, + "locked": false, "name": "test", "node_directory": null, - "node_id": "30a2bfff-f287-4a2e-97e6-880b13667fab", + "node_id": "76bc2602-3c9c-42ac-9384-36d7777da1e8", "node_type": "vpcs", "port_name_format": "Ethernet{0}", "port_segment_size": 0, @@ -46,15 +49,16 @@ X-Route: /v2/projects/{project_id}/nodes "short_name": "e0" } ], - "project_id": "33278936-718c-4161-8fc3-7af4aa39581f", + "project_id": "08c7f9e8-6ef5-4793-8edc-0898d49c25f9", "properties": { "startup_script": "echo test" }, "status": "stopped", "symbol": ":/symbols/computer.svg", + "template_id": null, "width": 65, "x": 0, "y": 0, - "z": 0 + "z": 1 } ] diff --git a/docs/api/examples/controller_get_projectsprojectidnodesnodeid.txt b/docs/api/examples/controller_get_projectsprojectidnodesnodeid.txt index 4f9a6cf7..73e8975d 100644 --- a/docs/api/examples/controller_get_projectsprojectidnodesnodeid.txt +++ b/docs/api/examples/controller_get_projectsprojectidnodesnodeid.txt @@ -1,35 +1,38 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/27d4fc3f-0c57-4b34-bee2-497f1216f9b1/nodes/ef78b006-21e6-4b82-a0db-c259c3e59fda' +curl -i -X GET 'http://localhost:3080/v2/projects/31b54242-47e7-4288-a034-8bb89d032187/nodes/ab5c3daa-86fc-417d-ac70-51023ede22de' -GET /v2/projects/27d4fc3f-0c57-4b34-bee2-497f1216f9b1/nodes/ef78b006-21e6-4b82-a0db-c259c3e59fda HTTP/1.1 +GET /v2/projects/31b54242-47e7-4288-a034-8bb89d032187/nodes/ab5c3daa-86fc-417d-ac70-51023ede22de HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 1123 +Content-Length: 1201 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id} { "command_line": null, "compute_id": "example.com", "console": 2048, - "console_host": "", + "console_auto_start": false, + "console_host": "", "console_type": null, + "custom_adapters": [], "first_port_name": null, "height": 59, "label": { "rotation": 0, - "style": "font-size: 10;font-familly: Verdana", + "style": null, "text": "test", "x": null, "y": -40 }, + "locked": false, "name": "test", "node_directory": null, - "node_id": "ef78b006-21e6-4b82-a0db-c259c3e59fda", + "node_id": "ab5c3daa-86fc-417d-ac70-51023ede22de", "node_type": "vpcs", "port_name_format": "Ethernet{0}", "port_segment_size": 0, @@ -45,14 +48,15 @@ X-Route: /v2/projects/{project_id}/nodes/{node_id} "short_name": "e0" } ], - "project_id": "27d4fc3f-0c57-4b34-bee2-497f1216f9b1", + "project_id": "31b54242-47e7-4288-a034-8bb89d032187", "properties": { "startup_script": "echo test" }, "status": "stopped", "symbol": ":/symbols/computer.svg", + "template_id": null, "width": 65, "x": 0, "y": 0, - "z": 0 + "z": 1 } diff --git a/docs/api/examples/controller_get_projectsprojectidnodesnodeiddynamipsautoidlepc.txt b/docs/api/examples/controller_get_projectsprojectidnodesnodeiddynamipsautoidlepc.txt index 0c6c1c88..a7e440b9 100644 --- a/docs/api/examples/controller_get_projectsprojectidnodesnodeiddynamipsautoidlepc.txt +++ b/docs/api/examples/controller_get_projectsprojectidnodesnodeiddynamipsautoidlepc.txt @@ -1,6 +1,6 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/4d318c14-2a43-4578-98ef-8f5cf2de34fb/nodes/2cfc89cf-7cbf-45a2-8085-446f9adc3513/dynamips/auto_idlepc' +curl -i -X GET 'http://localhost:3080/v2/projects/c7608e88-332a-436a-9a95-8038b5c76298/nodes/95991a30-8a89-469e-a70d-1ca248bb326d/dynamips/auto_idlepc' -GET /v2/projects/4d318c14-2a43-4578-98ef-8f5cf2de34fb/nodes/2cfc89cf-7cbf-45a2-8085-446f9adc3513/dynamips/auto_idlepc HTTP/1.1 +GET /v2/projects/c7608e88-332a-436a-9a95-8038b5c76298/nodes/95991a30-8a89-469e-a70d-1ca248bb326d/dynamips/auto_idlepc HTTP/1.1 @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 30 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:38 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:57 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id}/dynamips/auto_idlepc { diff --git a/docs/api/examples/controller_get_projectsprojectidnodesnodeiddynamipsidlepcproposals.txt b/docs/api/examples/controller_get_projectsprojectidnodesnodeiddynamipsidlepcproposals.txt index 9f0dfb9a..c1dbc3f6 100644 --- a/docs/api/examples/controller_get_projectsprojectidnodesnodeiddynamipsidlepcproposals.txt +++ b/docs/api/examples/controller_get_projectsprojectidnodesnodeiddynamipsidlepcproposals.txt @@ -1,6 +1,6 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/ad96a777-6236-456f-94f6-6036c7b5e822/nodes/aaadc419-18e6-4c89-967e-a71648fd4bc6/dynamips/idlepc_proposals' +curl -i -X GET 'http://localhost:3080/v2/projects/aadaa1da-7533-4343-ac63-f8344b182ae2/nodes/2b6de34a-b825-44ad-a5d5-c2ca34387e2f/dynamips/idlepc_proposals' -GET /v2/projects/ad96a777-6236-456f-94f6-6036c7b5e822/nodes/aaadc419-18e6-4c89-967e-a71648fd4bc6/dynamips/idlepc_proposals HTTP/1.1 +GET /v2/projects/aadaa1da-7533-4343-ac63-f8344b182ae2/nodes/2b6de34a-b825-44ad-a5d5-c2ca34387e2f/dynamips/idlepc_proposals HTTP/1.1 @@ -8,8 +8,8 @@ HTTP/1.1 200 Connection: close Content-Length: 38 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:38 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:57 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id}/dynamips/idlepc_proposals [ diff --git a/docs/api/examples/controller_get_projectsprojectidsnapshots.txt b/docs/api/examples/controller_get_projectsprojectidsnapshots.txt index f9d92e06..920862e7 100644 --- a/docs/api/examples/controller_get_projectsprojectidsnapshots.txt +++ b/docs/api/examples/controller_get_projectsprojectidsnapshots.txt @@ -1,6 +1,6 @@ -curl -i -X GET 'http://localhost:3080/v2/projects/fedc2620-5424-4a08-9cb5-8bc1f288df0d/snapshots' +curl -i -X GET 'http://localhost:3080/v2/projects/71690581-7c74-4d65-b8a9-267b42d02146/snapshots' -GET /v2/projects/fedc2620-5424-4a08-9cb5-8bc1f288df0d/snapshots HTTP/1.1 +GET /v2/projects/71690581-7c74-4d65-b8a9-267b42d02146/snapshots HTTP/1.1 @@ -8,15 +8,15 @@ HTTP/1.1 200 Connection: close Content-Length: 197 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:40 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:09 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/snapshots [ { - "created_at": 1515399400, + "created_at": 1553935808, "name": "test", - "project_id": "fedc2620-5424-4a08-9cb5-8bc1f288df0d", - "snapshot_id": "31310a98-d0b3-4739-8889-c3e0a7c1432e" + "project_id": "71690581-7c74-4d65-b8a9-267b42d02146", + "snapshot_id": "588a161b-22eb-4002-b603-44dece2ba060" } ] diff --git a/docs/api/examples/controller_get_settings.txt b/docs/api/examples/controller_get_settings.txt deleted file mode 100644 index c12b7bc8..00000000 --- a/docs/api/examples/controller_get_settings.txt +++ /dev/null @@ -1,18 +0,0 @@ -curl -i -X GET 'http://localhost:3080/v2/settings' - -GET /v2/settings HTTP/1.1 - - - -HTTP/1.1 200 -Connection: close -Content-Length: 85 -Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:40 GMT -Server: Python/3.6 GNS3/2.1.2dev1 -X-Route: /v2/settings - -{ - "modification_uuid": "c1aaa5d1-ce63-49f4-bfcc-e67dfac60ce3", - "test": true -} diff --git a/docs/api/examples/controller_get_symbols.txt b/docs/api/examples/controller_get_symbols.txt index f3b75885..4e9edf60 100644 --- a/docs/api/examples/controller_get_symbols.txt +++ b/docs/api/examples/controller_get_symbols.txt @@ -6,216 +6,2045 @@ GET /v2/symbols HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 5174 +Content-Length: 60126 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:40 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:11 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/symbols [ { "builtin": true, "filename": "PBX.svg", - "symbol_id": ":/symbols/PBX.svg" + "symbol_id": ":/symbols/classic/PBX.svg", + "theme": "Classic" }, { "builtin": true, "filename": "PIX_firewall.svg", - "symbol_id": ":/symbols/PIX_firewall.svg" + "symbol_id": ":/symbols/classic/PIX_firewall.svg", + "theme": "Classic" }, { "builtin": true, "filename": "access_point.svg", - "symbol_id": ":/symbols/access_point.svg" + "symbol_id": ":/symbols/classic/access_point.svg", + "theme": "Classic" }, { "builtin": true, "filename": "access_server.svg", - "symbol_id": ":/symbols/access_server.svg" + "symbol_id": ":/symbols/classic/access_server.svg", + "theme": "Classic" }, { "builtin": true, "filename": "asa.svg", - "symbol_id": ":/symbols/asa.svg" + "symbol_id": ":/symbols/classic/asa.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "atm.svg", + "symbol_id": ":/symbols/affinity/square/red/atm.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "atm.svg", + "symbol_id": ":/symbols/affinity/square/blue/atm.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "atm.svg", + "symbol_id": ":/symbols/affinity/square/gray/atm.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "atm.svg", + "symbol_id": ":/symbols/affinity/circle/red/atm.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "atm.svg", + "symbol_id": ":/symbols/affinity/circle/blue/atm.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "atm.svg", + "symbol_id": ":/symbols/affinity/circle/gray/atm.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "atm_bridge.svg", - "symbol_id": ":/symbols/atm_bridge.svg" + "symbol_id": ":/symbols/classic/atm_bridge.svg", + "theme": "Classic" }, { "builtin": true, "filename": "atm_switch.svg", - "symbol_id": ":/symbols/atm_switch.svg" + "symbol_id": ":/symbols/classic/atm_switch.svg", + "theme": "Classic" }, { "builtin": true, "filename": "call_manager.svg", - "symbol_id": ":/symbols/call_manager.svg" + "symbol_id": ":/symbols/classic/call_manager.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "camera.svg", + "symbol_id": ":/symbols/affinity/square/red/camera.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "camera.svg", + "symbol_id": ":/symbols/affinity/square/blue/camera.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "camera.svg", + "symbol_id": ":/symbols/affinity/square/gray/camera.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "camera.svg", + "symbol_id": ":/symbols/affinity/circle/red/camera.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "camera.svg", + "symbol_id": ":/symbols/affinity/circle/blue/camera.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "camera.svg", + "symbol_id": ":/symbols/affinity/circle/gray/camera.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "camera_dome.svg", + "symbol_id": ":/symbols/affinity/square/red/camera_dome.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "camera_dome.svg", + "symbol_id": ":/symbols/affinity/square/blue/camera_dome.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "camera_dome.svg", + "symbol_id": ":/symbols/affinity/square/gray/camera_dome.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "camera_dome.svg", + "symbol_id": ":/symbols/affinity/circle/red/camera_dome.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "camera_dome.svg", + "symbol_id": ":/symbols/affinity/circle/blue/camera_dome.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "camera_dome.svg", + "symbol_id": ":/symbols/affinity/circle/gray/camera_dome.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "circle.svg", + "symbol_id": ":/symbols/affinity/circle/red/circle.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "circle.svg", + "symbol_id": ":/symbols/affinity/circle/blue/circle.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "circle.svg", + "symbol_id": ":/symbols/affinity/circle/gray/circle.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "client.svg", + "symbol_id": ":/symbols/affinity/square/red/client.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "client.svg", + "symbol_id": ":/symbols/affinity/square/blue/client.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "client.svg", + "symbol_id": ":/symbols/affinity/square/gray/client.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "client.svg", + "symbol_id": ":/symbols/affinity/circle/red/client.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "client.svg", + "symbol_id": ":/symbols/affinity/circle/blue/client.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "client.svg", + "symbol_id": ":/symbols/affinity/circle/gray/client.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "client_vm.svg", + "symbol_id": ":/symbols/affinity/square/red/client_vm.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "client_vm.svg", + "symbol_id": ":/symbols/affinity/square/blue/client_vm.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "client_vm.svg", + "symbol_id": ":/symbols/affinity/square/gray/client_vm.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "client_vm.svg", + "symbol_id": ":/symbols/affinity/circle/red/client_vm.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "client_vm.svg", + "symbol_id": ":/symbols/affinity/circle/blue/client_vm.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "client_vm.svg", + "symbol_id": ":/symbols/affinity/circle/gray/client_vm.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "cloud.svg", - "symbol_id": ":/symbols/cloud.svg" + "symbol_id": ":/symbols/affinity/square/red/cloud.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "cloud.svg", + "symbol_id": ":/symbols/affinity/square/blue/cloud.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "cloud.svg", + "symbol_id": ":/symbols/affinity/square/gray/cloud.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "cloud.svg", + "symbol_id": ":/symbols/affinity/circle/red/cloud.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "cloud.svg", + "symbol_id": ":/symbols/affinity/circle/blue/cloud.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "cloud.svg", + "symbol_id": ":/symbols/affinity/circle/gray/cloud.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "cloud.svg", + "symbol_id": ":/symbols/classic/cloud.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "cog.svg", + "symbol_id": ":/symbols/affinity/square/red/cog.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "cog.svg", + "symbol_id": ":/symbols/affinity/square/blue/cog.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "cog.svg", + "symbol_id": ":/symbols/affinity/square/gray/cog.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "cog.svg", + "symbol_id": ":/symbols/affinity/circle/red/cog.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "cog.svg", + "symbol_id": ":/symbols/affinity/circle/blue/cog.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "cog.svg", + "symbol_id": ":/symbols/affinity/circle/gray/cog.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "communications.svg", + "symbol_id": ":/symbols/affinity/square/red/communications.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "communications.svg", + "symbol_id": ":/symbols/affinity/square/blue/communications.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "communications.svg", + "symbol_id": ":/symbols/affinity/square/gray/communications.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "communications.svg", + "symbol_id": ":/symbols/affinity/circle/red/communications.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "communications.svg", + "symbol_id": ":/symbols/affinity/circle/blue/communications.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "communications.svg", + "symbol_id": ":/symbols/affinity/circle/gray/communications.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "computer.svg", - "symbol_id": ":/symbols/computer.svg" + "symbol_id": ":/symbols/classic/computer.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "conversation.svg", + "symbol_id": ":/symbols/affinity/square/red/conversation.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "conversation.svg", + "symbol_id": ":/symbols/affinity/square/blue/conversation.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "conversation.svg", + "symbol_id": ":/symbols/affinity/square/gray/conversation.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "conversation.svg", + "symbol_id": ":/symbols/affinity/circle/red/conversation.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "conversation.svg", + "symbol_id": ":/symbols/affinity/circle/blue/conversation.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "conversation.svg", + "symbol_id": ":/symbols/affinity/circle/gray/conversation.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "docker.svg", + "symbol_id": ":/symbols/affinity/square/red/docker.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "docker.svg", + "symbol_id": ":/symbols/affinity/square/blue/docker.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "docker.svg", + "symbol_id": ":/symbols/affinity/square/gray/docker.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "docker.svg", + "symbol_id": ":/symbols/affinity/circle/red/docker.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "docker.svg", + "symbol_id": ":/symbols/affinity/circle/blue/docker.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "docker.svg", + "symbol_id": ":/symbols/affinity/circle/gray/docker.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "docker_guest.svg", - "symbol_id": ":/symbols/docker_guest.svg" + "symbol_id": ":/symbols/classic/docker_guest.svg", + "theme": "Classic" }, { "builtin": true, "filename": "dslam.svg", - "symbol_id": ":/symbols/dslam.svg" + "symbol_id": ":/symbols/affinity/square/red/dslam.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "dslam.svg", + "symbol_id": ":/symbols/affinity/square/blue/dslam.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "dslam.svg", + "symbol_id": ":/symbols/affinity/square/gray/dslam.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "dslam.svg", + "symbol_id": ":/symbols/affinity/circle/red/dslam.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "dslam.svg", + "symbol_id": ":/symbols/affinity/circle/blue/dslam.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "dslam.svg", + "symbol_id": ":/symbols/affinity/circle/gray/dslam.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "dslam.svg", + "symbol_id": ":/symbols/classic/dslam.svg", + "theme": "Classic" }, { "builtin": true, "filename": "edge_label_switch_router.svg", - "symbol_id": ":/symbols/edge_label_switch_router.svg" + "symbol_id": ":/symbols/classic/edge_label_switch_router.svg", + "theme": "Classic" }, { "builtin": true, "filename": "ethernet_switch.svg", - "symbol_id": ":/symbols/ethernet_switch.svg" + "symbol_id": ":/symbols/classic/ethernet_switch.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "fingerprint.svg", + "symbol_id": ":/symbols/affinity/square/red/fingerprint.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "fingerprint.svg", + "symbol_id": ":/symbols/affinity/square/blue/fingerprint.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "fingerprint.svg", + "symbol_id": ":/symbols/affinity/square/gray/fingerprint.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "fingerprint.svg", + "symbol_id": ":/symbols/affinity/circle/red/fingerprint.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "fingerprint.svg", + "symbol_id": ":/symbols/affinity/circle/blue/fingerprint.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "fingerprint.svg", + "symbol_id": ":/symbols/affinity/circle/gray/fingerprint.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "firewall.svg", - "symbol_id": ":/symbols/firewall.svg" + "symbol_id": ":/symbols/affinity/square/red/firewall.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "firewall.svg", + "symbol_id": ":/symbols/affinity/square/blue/firewall.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "firewall.svg", + "symbol_id": ":/symbols/affinity/square/gray/firewall.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "firewall.svg", + "symbol_id": ":/symbols/affinity/circle/red/firewall.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "firewall.svg", + "symbol_id": ":/symbols/affinity/circle/blue/firewall.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "firewall.svg", + "symbol_id": ":/symbols/affinity/circle/gray/firewall.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "firewall.svg", + "symbol_id": ":/symbols/classic/firewall.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "firewall3.svg", + "symbol_id": ":/symbols/affinity/square/red/firewall3.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "firewall3.svg", + "symbol_id": ":/symbols/affinity/square/blue/firewall3.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "firewall3.svg", + "symbol_id": ":/symbols/affinity/square/gray/firewall3.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "firewall3.svg", + "symbol_id": ":/symbols/affinity/circle/red/firewall3.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "firewall3.svg", + "symbol_id": ":/symbols/affinity/circle/blue/firewall3.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "firewall3.svg", + "symbol_id": ":/symbols/affinity/circle/gray/firewall3.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "frame_relay_switch.svg", - "symbol_id": ":/symbols/frame_relay_switch.svg" + "symbol_id": ":/symbols/classic/frame_relay_switch.svg", + "theme": "Classic" }, { "builtin": true, "filename": "gateway.svg", - "symbol_id": ":/symbols/gateway.svg" + "symbol_id": ":/symbols/classic/gateway.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "grid.svg", + "symbol_id": ":/symbols/affinity/square/red/grid.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "grid.svg", + "symbol_id": ":/symbols/affinity/square/blue/grid.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "grid.svg", + "symbol_id": ":/symbols/affinity/square/gray/grid.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "grid.svg", + "symbol_id": ":/symbols/affinity/circle/red/grid.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "grid.svg", + "symbol_id": ":/symbols/affinity/circle/blue/grid.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "grid.svg", + "symbol_id": ":/symbols/affinity/circle/gray/grid.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "grid2.svg", + "symbol_id": ":/symbols/affinity/square/red/grid2.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "grid2.svg", + "symbol_id": ":/symbols/affinity/square/blue/grid2.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "grid2.svg", + "symbol_id": ":/symbols/affinity/square/gray/grid2.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "grid2.svg", + "symbol_id": ":/symbols/affinity/circle/red/grid2.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "grid2.svg", + "symbol_id": ":/symbols/affinity/circle/blue/grid2.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "grid2.svg", + "symbol_id": ":/symbols/affinity/circle/gray/grid2.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "hub.svg", - "symbol_id": ":/symbols/hub.svg" + "symbol_id": ":/symbols/affinity/square/red/hub.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "hub.svg", + "symbol_id": ":/symbols/affinity/square/blue/hub.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "hub.svg", + "symbol_id": ":/symbols/affinity/square/gray/hub.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "hub.svg", + "symbol_id": ":/symbols/affinity/circle/red/hub.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "hub.svg", + "symbol_id": ":/symbols/affinity/circle/blue/hub.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "hub.svg", + "symbol_id": ":/symbols/affinity/circle/gray/hub.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "hub.svg", + "symbol_id": ":/symbols/classic/hub.svg", + "theme": "Classic" }, { "builtin": true, "filename": "ids.svg", - "symbol_id": ":/symbols/ids.svg" + "symbol_id": ":/symbols/classic/ids.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "inspect.svg", + "symbol_id": ":/symbols/affinity/circle/red/inspect.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "inspect.svg", + "symbol_id": ":/symbols/affinity/circle/blue/inspect.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "inspect.svg", + "symbol_id": ":/symbols/affinity/circle/gray/inspect.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "inspect2.svg", + "symbol_id": ":/symbols/affinity/square/red/inspect2.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "inspect2.svg", + "symbol_id": ":/symbols/affinity/square/blue/inspect2.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "inspect2.svg", + "symbol_id": ":/symbols/affinity/square/gray/inspect2.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "inspect3.svg", + "symbol_id": ":/symbols/affinity/square/red/inspect3.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "inspect3.svg", + "symbol_id": ":/symbols/affinity/square/blue/inspect3.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "inspect3.svg", + "symbol_id": ":/symbols/affinity/square/gray/inspect3.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "inspect3.svg", + "symbol_id": ":/symbols/affinity/circle/red/inspect3.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "inspect3.svg", + "symbol_id": ":/symbols/affinity/circle/blue/inspect3.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "inspect3.svg", + "symbol_id": ":/symbols/affinity/circle/gray/inspect3.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "interconnect.svg", + "symbol_id": ":/symbols/affinity/square/red/interconnect.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "interconnect.svg", + "symbol_id": ":/symbols/affinity/square/blue/interconnect.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "interconnect.svg", + "symbol_id": ":/symbols/affinity/square/gray/interconnect.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "interconnect.svg", + "symbol_id": ":/symbols/affinity/circle/red/interconnect.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "interconnect.svg", + "symbol_id": ":/symbols/affinity/circle/blue/interconnect.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "interconnect.svg", + "symbol_id": ":/symbols/affinity/circle/gray/interconnect.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "iosv_l2_virl.svg", - "symbol_id": ":/symbols/iosv_l2_virl.svg" + "symbol_id": ":/symbols/classic/iosv_l2_virl.svg", + "theme": "Classic" }, { "builtin": true, "filename": "iosv_virl.svg", - "symbol_id": ":/symbols/iosv_virl.svg" + "symbol_id": ":/symbols/classic/iosv_virl.svg", + "theme": "Classic" }, { "builtin": true, "filename": "ip_phone.svg", - "symbol_id": ":/symbols/ip_phone.svg" + "symbol_id": ":/symbols/classic/ip_phone.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "isdn.svg", + "symbol_id": ":/symbols/affinity/square/red/isdn.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "isdn.svg", + "symbol_id": ":/symbols/affinity/square/blue/isdn.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "isdn.svg", + "symbol_id": ":/symbols/affinity/square/gray/isdn.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "isdn.svg", + "symbol_id": ":/symbols/affinity/circle/red/isdn.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "isdn.svg", + "symbol_id": ":/symbols/affinity/circle/blue/isdn.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "isdn.svg", + "symbol_id": ":/symbols/affinity/circle/gray/isdn.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "label_switch_router.svg", - "symbol_id": ":/symbols/label_switch_router.svg" + "symbol_id": ":/symbols/classic/label_switch_router.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "ldap.svg", + "symbol_id": ":/symbols/affinity/square/red/ldap.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "ldap.svg", + "symbol_id": ":/symbols/affinity/square/blue/ldap.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "ldap.svg", + "symbol_id": ":/symbols/affinity/square/gray/ldap.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "ldap.svg", + "symbol_id": ":/symbols/affinity/circle/red/ldap.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "ldap.svg", + "symbol_id": ":/symbols/affinity/circle/blue/ldap.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "ldap.svg", + "symbol_id": ":/symbols/affinity/circle/gray/ldap.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "light_bulb.svg", + "symbol_id": ":/symbols/affinity/square/red/light_bulb.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "light_bulb.svg", + "symbol_id": ":/symbols/affinity/square/blue/light_bulb.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "light_bulb.svg", + "symbol_id": ":/symbols/affinity/square/gray/light_bulb.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "light_bulb.svg", + "symbol_id": ":/symbols/affinity/circle/red/light_bulb.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "light_bulb.svg", + "symbol_id": ":/symbols/affinity/circle/blue/light_bulb.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "light_bulb.svg", + "symbol_id": ":/symbols/affinity/circle/gray/light_bulb.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "lightweight_ap.svg", - "symbol_id": ":/symbols/lightweight_ap.svg" + "symbol_id": ":/symbols/classic/lightweight_ap.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "link.svg", + "symbol_id": ":/symbols/affinity/square/red/link.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "link.svg", + "symbol_id": ":/symbols/affinity/square/blue/link.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "link.svg", + "symbol_id": ":/symbols/affinity/square/gray/link.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "link.svg", + "symbol_id": ":/symbols/affinity/circle/red/link.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "link.svg", + "symbol_id": ":/symbols/affinity/circle/blue/link.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "link.svg", + "symbol_id": ":/symbols/affinity/circle/gray/link.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "loadbalancer.svg", + "symbol_id": ":/symbols/affinity/circle/red/loadbalancer.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "loadbalancer.svg", + "symbol_id": ":/symbols/affinity/circle/blue/loadbalancer.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "loadbalancer.svg", + "symbol_id": ":/symbols/affinity/circle/gray/loadbalancer.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "multilayer_switch.svg", - "symbol_id": ":/symbols/multilayer_switch.svg" + "symbol_id": ":/symbols/classic/multilayer_switch.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "nas.svg", + "symbol_id": ":/symbols/affinity/square/red/nas.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "nas.svg", + "symbol_id": ":/symbols/affinity/square/blue/nas.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "nas.svg", + "symbol_id": ":/symbols/affinity/square/gray/nas.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "nas.svg", + "symbol_id": ":/symbols/affinity/circle/red/nas.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "nas.svg", + "symbol_id": ":/symbols/affinity/circle/blue/nas.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "nas.svg", + "symbol_id": ":/symbols/affinity/circle/gray/nas.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "optical_router.svg", - "symbol_id": ":/symbols/optical_router.svg" + "symbol_id": ":/symbols/classic/optical_router.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "pinpoint.svg", + "symbol_id": ":/symbols/affinity/square/red/pinpoint.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "pinpoint.svg", + "symbol_id": ":/symbols/affinity/square/blue/pinpoint.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "pinpoint.svg", + "symbol_id": ":/symbols/affinity/square/gray/pinpoint.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "pinpoint.svg", + "symbol_id": ":/symbols/affinity/circle/red/pinpoint.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "pinpoint.svg", + "symbol_id": ":/symbols/affinity/circle/blue/pinpoint.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "pinpoint.svg", + "symbol_id": ":/symbols/affinity/circle/gray/pinpoint.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "printer.svg", - "symbol_id": ":/symbols/printer.svg" + "symbol_id": ":/symbols/affinity/square/red/printer.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "printer.svg", + "symbol_id": ":/symbols/affinity/square/blue/printer.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "printer.svg", + "symbol_id": ":/symbols/affinity/square/gray/printer.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "printer.svg", + "symbol_id": ":/symbols/affinity/circle/red/printer.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "printer.svg", + "symbol_id": ":/symbols/affinity/circle/blue/printer.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "printer.svg", + "symbol_id": ":/symbols/affinity/circle/gray/printer.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "printer.svg", + "symbol_id": ":/symbols/classic/printer.svg", + "theme": "Classic" }, { "builtin": true, "filename": "qemu_guest.svg", - "symbol_id": ":/symbols/qemu_guest.svg" + "symbol_id": ":/symbols/classic/qemu_guest.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "rj45.svg", + "symbol_id": ":/symbols/affinity/square/red/rj45.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "rj45.svg", + "symbol_id": ":/symbols/affinity/square/blue/rj45.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "rj45.svg", + "symbol_id": ":/symbols/affinity/square/gray/rj45.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "rj45.svg", + "symbol_id": ":/symbols/affinity/circle/red/rj45.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "rj45.svg", + "symbol_id": ":/symbols/affinity/circle/blue/rj45.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "rj45.svg", + "symbol_id": ":/symbols/affinity/circle/gray/rj45.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "route_switch_processor.svg", - "symbol_id": ":/symbols/route_switch_processor.svg" + "symbol_id": ":/symbols/classic/route_switch_processor.svg", + "theme": "Classic" }, { "builtin": true, "filename": "router.awp.svg", - "symbol_id": ":/symbols/router.awp.svg" + "symbol_id": ":/symbols/classic/router.awp.svg", + "theme": "Classic" }, { "builtin": true, "filename": "router.svg", - "symbol_id": ":/symbols/router.svg" + "symbol_id": ":/symbols/affinity/square/red/router.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "router.svg", + "symbol_id": ":/symbols/affinity/square/blue/router.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "router.svg", + "symbol_id": ":/symbols/affinity/square/gray/router.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "router.svg", + "symbol_id": ":/symbols/affinity/circle/red/router.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "router.svg", + "symbol_id": ":/symbols/affinity/circle/blue/router.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "router.svg", + "symbol_id": ":/symbols/affinity/circle/gray/router.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "router.svg", + "symbol_id": ":/symbols/classic/router.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "router_cloud.svg", + "symbol_id": ":/symbols/affinity/square/red/router_cloud.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "router_cloud.svg", + "symbol_id": ":/symbols/affinity/square/blue/router_cloud.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "router_cloud.svg", + "symbol_id": ":/symbols/affinity/square/gray/router_cloud.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "router_cloud.svg", + "symbol_id": ":/symbols/affinity/circle/red/router_cloud.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "router_cloud.svg", + "symbol_id": ":/symbols/affinity/circle/blue/router_cloud.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "router_cloud.svg", + "symbol_id": ":/symbols/affinity/circle/gray/router_cloud.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "router_firewall.svg", - "symbol_id": ":/symbols/router_firewall.svg" + "symbol_id": ":/symbols/classic/router_firewall.svg", + "theme": "Classic" }, { "builtin": true, "filename": "router_netflow.svg", - "symbol_id": ":/symbols/router_netflow.svg" + "symbol_id": ":/symbols/classic/router_netflow.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "satellite.svg", + "symbol_id": ":/symbols/affinity/square/red/satellite.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "satellite.svg", + "symbol_id": ":/symbols/affinity/square/blue/satellite.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "satellite.svg", + "symbol_id": ":/symbols/affinity/square/gray/satellite.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "satellite.svg", + "symbol_id": ":/symbols/affinity/circle/red/satellite.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "satellite.svg", + "symbol_id": ":/symbols/affinity/circle/blue/satellite.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "satellite.svg", + "symbol_id": ":/symbols/affinity/circle/gray/satellite.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "satellite_dish.svg", + "symbol_id": ":/symbols/affinity/square/red/satellite_dish.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "satellite_dish.svg", + "symbol_id": ":/symbols/affinity/square/blue/satellite_dish.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "satellite_dish.svg", + "symbol_id": ":/symbols/affinity/square/gray/satellite_dish.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "satellite_dish.svg", + "symbol_id": ":/symbols/affinity/circle/red/satellite_dish.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "satellite_dish.svg", + "symbol_id": ":/symbols/affinity/circle/blue/satellite_dish.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "satellite_dish.svg", + "symbol_id": ":/symbols/affinity/circle/gray/satellite_dish.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "scull.svg", + "symbol_id": ":/symbols/affinity/square/red/scull.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "scull.svg", + "symbol_id": ":/symbols/affinity/square/blue/scull.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "scull.svg", + "symbol_id": ":/symbols/affinity/square/gray/scull.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "scull.svg", + "symbol_id": ":/symbols/affinity/circle/red/scull.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "scull.svg", + "symbol_id": ":/symbols/affinity/circle/blue/scull.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "scull.svg", + "symbol_id": ":/symbols/affinity/circle/gray/scull.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "server-cluster.svg", + "symbol_id": ":/symbols/affinity/square/red/server-cluster.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "server-cluster.svg", + "symbol_id": ":/symbols/affinity/square/blue/server-cluster.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "server-cluster.svg", + "symbol_id": ":/symbols/affinity/square/gray/server-cluster.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "server-cluster.svg", + "symbol_id": ":/symbols/affinity/circle/red/server-cluster.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "server-cluster.svg", + "symbol_id": ":/symbols/affinity/circle/blue/server-cluster.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "server-cluster.svg", + "symbol_id": ":/symbols/affinity/circle/gray/server-cluster.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "server.svg", - "symbol_id": ":/symbols/server.svg" + "symbol_id": ":/symbols/affinity/square/red/server.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "server.svg", + "symbol_id": ":/symbols/affinity/square/blue/server.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "server.svg", + "symbol_id": ":/symbols/affinity/square/gray/server.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "server.svg", + "symbol_id": ":/symbols/affinity/circle/red/server.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "server.svg", + "symbol_id": ":/symbols/affinity/circle/blue/server.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "server.svg", + "symbol_id": ":/symbols/affinity/circle/gray/server.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "server.svg", + "symbol_id": ":/symbols/classic/server.svg", + "theme": "Classic" }, { "builtin": true, "filename": "sip_server.svg", - "symbol_id": ":/symbols/sip_server.svg" + "symbol_id": ":/symbols/classic/sip_server.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "square.svg", + "symbol_id": ":/symbols/affinity/square/red/square.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "square.svg", + "symbol_id": ":/symbols/affinity/square/blue/square.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "square.svg", + "symbol_id": ":/symbols/affinity/square/gray/square.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "statistics.svg", + "symbol_id": ":/symbols/affinity/square/red/statistics.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "statistics.svg", + "symbol_id": ":/symbols/affinity/square/blue/statistics.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "statistics.svg", + "symbol_id": ":/symbols/affinity/square/gray/statistics.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "statistics.svg", + "symbol_id": ":/symbols/affinity/circle/red/statistics.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "statistics.svg", + "symbol_id": ":/symbols/affinity/circle/blue/statistics.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "statistics.svg", + "symbol_id": ":/symbols/affinity/circle/gray/statistics.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "storage.svg", + "symbol_id": ":/symbols/affinity/square/red/storage.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "storage.svg", + "symbol_id": ":/symbols/affinity/square/blue/storage.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "storage.svg", + "symbol_id": ":/symbols/affinity/square/gray/storage.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "storage.svg", + "symbol_id": ":/symbols/affinity/circle/red/storage.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "storage.svg", + "symbol_id": ":/symbols/affinity/circle/blue/storage.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "storage.svg", + "symbol_id": ":/symbols/affinity/circle/gray/storage.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "switch.svg", + "symbol_id": ":/symbols/affinity/square/red/switch.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "switch.svg", + "symbol_id": ":/symbols/affinity/square/blue/switch.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "switch.svg", + "symbol_id": ":/symbols/affinity/square/gray/switch.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "switch.svg", + "symbol_id": ":/symbols/affinity/circle/red/switch.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "switch.svg", + "symbol_id": ":/symbols/affinity/circle/blue/switch.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "switch.svg", + "symbol_id": ":/symbols/affinity/circle/gray/switch.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "switch_multilayer.svg", + "symbol_id": ":/symbols/affinity/square/red/switch_multilayer.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "switch_multilayer.svg", + "symbol_id": ":/symbols/affinity/square/blue/switch_multilayer.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "switch_multilayer.svg", + "symbol_id": ":/symbols/affinity/square/gray/switch_multilayer.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "switch_multilayer.svg", + "symbol_id": ":/symbols/affinity/circle/red/switch_multilayer.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "switch_multilayer.svg", + "symbol_id": ":/symbols/affinity/circle/blue/switch_multilayer.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "switch_multilayer.svg", + "symbol_id": ":/symbols/affinity/circle/gray/switch_multilayer.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "tablet.svg", + "symbol_id": ":/symbols/affinity/square/red/tablet.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "tablet.svg", + "symbol_id": ":/symbols/affinity/square/blue/tablet.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "tablet.svg", + "symbol_id": ":/symbols/affinity/square/gray/tablet.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "tablet.svg", + "symbol_id": ":/symbols/affinity/circle/red/tablet.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "tablet.svg", + "symbol_id": ":/symbols/affinity/circle/blue/tablet.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "tablet.svg", + "symbol_id": ":/symbols/affinity/circle/gray/tablet.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "traceng.svg", + "symbol_id": ":/symbols/classic/traceng.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "tree.svg", + "symbol_id": ":/symbols/affinity/square/red/tree.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "tree.svg", + "symbol_id": ":/symbols/affinity/square/blue/tree.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "tree.svg", + "symbol_id": ":/symbols/affinity/square/gray/tree.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "tree.svg", + "symbol_id": ":/symbols/affinity/circle/red/tree.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "tree.svg", + "symbol_id": ":/symbols/affinity/circle/blue/tree.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "tree.svg", + "symbol_id": ":/symbols/affinity/circle/gray/tree.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "user.svg", + "symbol_id": ":/symbols/affinity/square/red/user.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "user.svg", + "symbol_id": ":/symbols/affinity/square/blue/user.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "user.svg", + "symbol_id": ":/symbols/affinity/square/gray/user.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "user.svg", + "symbol_id": ":/symbols/affinity/circle/red/user.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "user.svg", + "symbol_id": ":/symbols/affinity/circle/blue/user.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "user.svg", + "symbol_id": ":/symbols/affinity/circle/gray/user.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "vbox_guest.svg", - "symbol_id": ":/symbols/vbox_guest.svg" + "symbol_id": ":/symbols/classic/vbox_guest.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "virtualbox.svg", + "symbol_id": ":/symbols/affinity/square/red/virtualbox.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "virtualbox.svg", + "symbol_id": ":/symbols/affinity/square/blue/virtualbox.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "virtualbox.svg", + "symbol_id": ":/symbols/affinity/square/gray/virtualbox.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "virtualbox.svg", + "symbol_id": ":/symbols/affinity/circle/red/virtualbox.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "virtualbox.svg", + "symbol_id": ":/symbols/affinity/circle/blue/virtualbox.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "virtualbox.svg", + "symbol_id": ":/symbols/affinity/circle/gray/virtualbox.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "vm.svg", + "symbol_id": ":/symbols/affinity/square/red/vm.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "vm.svg", + "symbol_id": ":/symbols/affinity/square/blue/vm.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "vm.svg", + "symbol_id": ":/symbols/affinity/square/gray/vm.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "vm.svg", + "symbol_id": ":/symbols/affinity/circle/red/vm.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "vm.svg", + "symbol_id": ":/symbols/affinity/circle/blue/vm.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "vm.svg", + "symbol_id": ":/symbols/affinity/circle/gray/vm.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "vmware.svg", + "symbol_id": ":/symbols/affinity/square/red/vmware.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "vmware.svg", + "symbol_id": ":/symbols/affinity/square/blue/vmware.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "vmware.svg", + "symbol_id": ":/symbols/affinity/square/gray/vmware.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "vmware.svg", + "symbol_id": ":/symbols/affinity/circle/red/vmware.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "vmware.svg", + "symbol_id": ":/symbols/affinity/circle/blue/vmware.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "vmware.svg", + "symbol_id": ":/symbols/affinity/circle/gray/vmware.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "vmware_guest.svg", - "symbol_id": ":/symbols/vmware_guest.svg" + "symbol_id": ":/symbols/classic/vmware_guest.svg", + "theme": "Classic" }, { "builtin": true, "filename": "voice_access_server.svg", - "symbol_id": ":/symbols/voice_access_server.svg" + "symbol_id": ":/symbols/classic/voice_access_server.svg", + "theme": "Classic" }, { "builtin": true, "filename": "voice_router.svg", - "symbol_id": ":/symbols/voice_router.svg" + "symbol_id": ":/symbols/classic/voice_router.svg", + "theme": "Classic" }, { "builtin": true, "filename": "vpcs_guest.svg", - "symbol_id": ":/symbols/vpcs_guest.svg" + "symbol_id": ":/symbols/classic/vpcs_guest.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "wifi.svg", + "symbol_id": ":/symbols/affinity/square/red/wifi.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "wifi.svg", + "symbol_id": ":/symbols/affinity/square/blue/wifi.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "wifi.svg", + "symbol_id": ":/symbols/affinity/square/gray/wifi.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "wifi.svg", + "symbol_id": ":/symbols/affinity/circle/red/wifi.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "wifi.svg", + "symbol_id": ":/symbols/affinity/circle/blue/wifi.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "wifi.svg", + "symbol_id": ":/symbols/affinity/circle/gray/wifi.svg", + "theme": "Affinity-circle-gray" }, { "builtin": true, "filename": "wlan_controller.svg", - "symbol_id": ":/symbols/wlan_controller.svg" + "symbol_id": ":/symbols/classic/wlan_controller.svg", + "theme": "Classic" + }, + { + "builtin": true, + "filename": "wlc.svg", + "symbol_id": ":/symbols/affinity/square/red/wlc.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "wlc.svg", + "symbol_id": ":/symbols/affinity/square/blue/wlc.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "wlc.svg", + "symbol_id": ":/symbols/affinity/square/gray/wlc.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "wlc.svg", + "symbol_id": ":/symbols/affinity/circle/red/wlc.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "wlc.svg", + "symbol_id": ":/symbols/affinity/circle/blue/wlc.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "wlc.svg", + "symbol_id": ":/symbols/affinity/circle/gray/wlc.svg", + "theme": "Affinity-circle-gray" + }, + { + "builtin": true, + "filename": "xml.svg", + "symbol_id": ":/symbols/affinity/square/red/xml.svg", + "theme": "Affinity-square-red" + }, + { + "builtin": true, + "filename": "xml.svg", + "symbol_id": ":/symbols/affinity/square/blue/xml.svg", + "theme": "Affinity-square-blue" + }, + { + "builtin": true, + "filename": "xml.svg", + "symbol_id": ":/symbols/affinity/square/gray/xml.svg", + "theme": "Affinity-square-gray" + }, + { + "builtin": true, + "filename": "xml.svg", + "symbol_id": ":/symbols/affinity/circle/red/xml.svg", + "theme": "Affinity-circle-red" + }, + { + "builtin": true, + "filename": "xml.svg", + "symbol_id": ":/symbols/affinity/circle/blue/xml.svg", + "theme": "Affinity-circle-blue" + }, + { + "builtin": true, + "filename": "xml.svg", + "symbol_id": ":/symbols/affinity/circle/gray/xml.svg", + "theme": "Affinity-circle-gray" } ] diff --git a/docs/api/examples/controller_get_templates.txt b/docs/api/examples/controller_get_templates.txt new file mode 100644 index 00000000..03eb4d39 --- /dev/null +++ b/docs/api/examples/controller_get_templates.txt @@ -0,0 +1,121 @@ +curl -i -X GET 'http://localhost:3080/v2/templates' + +GET /v2/templates HTTP/1.1 + + + +HTTP/1.1 200 +Connection: close +Content-Length: 3193 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:50:13 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/templates + +[ + { + "builtin": true, + "category": "guest", + "name": "Cloud", + "symbol": ":/symbols/cloud.svg", + "template_id": "39e257dc-8412-3174-b6b3-0ee3ed6a43e9", + "template_type": "cloud" + }, + { + "builtin": true, + "category": "guest", + "name": "NAT", + "symbol": ":/symbols/cloud.svg", + "template_id": "df8f4ea9-33b7-3e96-86a2-c39bc9bb649c", + "template_type": "nat" + }, + { + "builtin": true, + "category": "guest", + "default_name_format": "PC-{0}", + "name": "VPCS", + "properties": { + "base_script_file": "vpcs_base_config.txt" + }, + "symbol": ":/symbols/vpcs_guest.svg", + "template_id": "19021f99-e36f-394d-b4a1-8aaa902ab9cc", + "template_type": "vpcs" + }, + { + "builtin": true, + "category": "switch", + "console_type": "telnet", + "name": "Ethernet switch", + "symbol": ":/symbols/ethernet_switch.svg", + "template_id": "1966b864-93e7-32d5-965f-001384eec461", + "template_type": "ethernet_switch" + }, + { + "builtin": true, + "category": "switch", + "name": "Ethernet hub", + "symbol": ":/symbols/hub.svg", + "template_id": "b4503ea9-d6b6-3695-9fe4-1db3b39290b0", + "template_type": "ethernet_hub" + }, + { + "builtin": true, + "category": "switch", + "name": "Frame Relay switch", + "symbol": ":/symbols/frame_relay_switch.svg", + "template_id": "dd0f6f3a-ba58-3249-81cb-a1dd88407a47", + "template_type": "frame_relay_switch" + }, + { + "builtin": true, + "category": "switch", + "name": "ATM switch", + "symbol": ":/symbols/atm_switch.svg", + "template_id": "aaa764e2-b383-300f-8a0e-3493bbfdb7d2", + "template_type": "atm_switch" + }, + { + "adapter_type": "e1000", + "adapters": 1, + "bios_image": "", + "boot_priority": "c", + "builtin": false, + "category": "router", + "cdrom_image": "", + "compute_id": "local", + "console_auto_start": false, + "console_type": "telnet", + "cpu_throttling": 0, + "cpus": 1, + "custom_adapters": [], + "default_name_format": "{name}-{0}", + "first_port_name": "", + "hda_disk_image": "", + "hda_disk_interface": "ide", + "hdb_disk_image": "", + "hdb_disk_interface": "ide", + "hdc_disk_image": "", + "hdc_disk_interface": "ide", + "hdd_disk_image": "", + "hdd_disk_interface": "ide", + "initrd": "", + "kernel_command_line": "", + "kernel_image": "", + "legacy_networking": false, + "linked_clone": true, + "mac_address": "", + "name": "test", + "on_close": "power_off", + "options": "", + "platform": "i386", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "process_priority": "normal", + "qemu_path": "", + "ram": 256, + "symbol": "guest.svg", + "template_id": "0a86391f-9355-4f47-a047-e9eb3b8fc115", + "template_type": "qemu", + "usage": "" + } +] diff --git a/docs/api/examples/controller_get_templatestemplateid.txt b/docs/api/examples/controller_get_templatestemplateid.txt new file mode 100644 index 00000000..77fb73bc --- /dev/null +++ b/docs/api/examples/controller_get_templatestemplateid.txt @@ -0,0 +1,28 @@ +curl -i -X GET 'http://localhost:3080/v2/templates/c0c6bb37-68d5-4900-bb18-ee69a524593f' + +GET /v2/templates/c0c6bb37-68d5-4900-bb18-ee69a524593f HTTP/1.1 + + + +HTTP/1.1 200 +Connection: close +Content-Length: 378 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:50:14 GMT +Etag: "01987f11368dfc5e0c95ee6cb5cf059c" +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/templates/{template_id} + +{ + "base_script_file": "vpcs_base_config.txt", + "builtin": false, + "category": "guest", + "compute_id": "local", + "console_auto_start": false, + "console_type": "telnet", + "default_name_format": "PC{0}", + "name": "VPCS_TEST", + "symbol": ":/symbols/vpcs_guest.svg", + "template_id": "c0c6bb37-68d5-4900-bb18-ee69a524593f", + "template_type": "vpcs" +} diff --git a/docs/api/examples/controller_get_version.txt b/docs/api/examples/controller_get_version.txt index d6a57646..eb2773b7 100644 --- a/docs/api/examples/controller_get_version.txt +++ b/docs/api/examples/controller_get_version.txt @@ -8,11 +8,11 @@ HTTP/1.1 200 Connection: close Content-Length: 49 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:41 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:16 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/version { "local": true, - "version": "2.1.2dev1" + "version": "2.2.0dev8" } diff --git a/docs/api/examples/controller_post_computes.txt b/docs/api/examples/controller_post_computes.txt index 34439959..7b5eeb96 100644 --- a/docs/api/examples/controller_post_computes.txt +++ b/docs/api/examples/controller_post_computes.txt @@ -13,10 +13,10 @@ POST /v2/computes HTTP/1.1 HTTP/1.1 201 Connection: close -Content-Length: 334 +Content-Length: 358 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:15 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:46 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/computes { @@ -28,6 +28,7 @@ X-Route: /v2/computes "connected": false, "cpu_usage_percent": null, "host": "localhost", + "last_error": null, "memory_usage_percent": null, "name": "http://julien@localhost:84", "port": 84, diff --git a/docs/api/examples/controller_post_computescomputeidautoidlepc.txt b/docs/api/examples/controller_post_computescomputeidautoidlepc.txt index dad1d6e6..2186ef85 100644 --- a/docs/api/examples/controller_post_computescomputeidautoidlepc.txt +++ b/docs/api/examples/controller_post_computescomputeidautoidlepc.txt @@ -12,8 +12,8 @@ HTTP/1.1 200 Connection: close Content-Length: 30 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:32 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/computes/{compute_id}/auto_idlepc { diff --git a/docs/api/examples/controller_post_computescomputeidemulatoraction.txt b/docs/api/examples/controller_post_computescomputeidemulatoraction.txt index 05cdbb7d..a759ca79 100644 --- a/docs/api/examples/controller_post_computescomputeidemulatoraction.txt +++ b/docs/api/examples/controller_post_computescomputeidemulatoraction.txt @@ -10,8 +10,8 @@ HTTP/1.1 200 Connection: close Content-Length: 2 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:30 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:47 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/computes/{compute_id}/{emulator}/{action:.+} [] diff --git a/docs/api/examples/controller_post_projects.txt b/docs/api/examples/controller_post_projects.txt index 108a918f..b4dfe175 100644 --- a/docs/api/examples/controller_post_projects.txt +++ b/docs/api/examples/controller_post_projects.txt @@ -9,19 +9,21 @@ POST /v2/projects HTTP/1.1 HTTP/1.1 201 Connection: close -Content-Length: 509 +Content-Length: 560 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:38 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:58 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects { "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "test.gns3", + "grid_size": 75, "name": "test", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp0kdf6pg5/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", + "path": "/tmp/tmpw253kdn9/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f", "scene_height": 1000, "scene_width": 2000, @@ -30,5 +32,7 @@ X-Route: /v2/projects "show_layers": false, "snap_to_grid": false, "status": "opened", + "supplier": null, + "variables": null, "zoom": 100 } diff --git a/docs/api/examples/controller_post_projectsload.txt b/docs/api/examples/controller_post_projectsload.txt index 7f9da785..0a7e25dd 100644 --- a/docs/api/examples/controller_post_projectsload.txt +++ b/docs/api/examples/controller_post_projectsload.txt @@ -8,20 +8,22 @@ POST /v2/projects/load HTTP/1.1 HTTP/1.1 201 Connection: close -Content-Length: 509 +Content-Length: 560 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:39 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:01 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/load { "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "test.gns3", + "grid_size": 75, "name": "test", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp86igc52s/projects/4ab2077c-0fe8-45f5-a82e-2a8a742b4026", - "project_id": "4ab2077c-0fe8-45f5-a82e-2a8a742b4026", + "path": "/tmp/tmpy8wy3fkc/projects/207d76b1-f1c6-4885-a95c-e3a0d21d22ab", + "project_id": "207d76b1-f1c6-4885-a95c-e3a0d21d22ab", "scene_height": 1000, "scene_width": 2000, "show_grid": false, @@ -29,5 +31,7 @@ X-Route: /v2/projects/load "show_layers": false, "snap_to_grid": false, "status": "opened", + "supplier": null, + "variables": null, "zoom": 100 } diff --git a/docs/api/examples/controller_post_projectsprojectidclose.txt b/docs/api/examples/controller_post_projectsprojectidclose.txt index 2a257a5d..d6538ae7 100644 --- a/docs/api/examples/controller_post_projectsprojectidclose.txt +++ b/docs/api/examples/controller_post_projectsprojectidclose.txt @@ -1,25 +1,27 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/8747d42d-da0d-4d8a-b2d6-3b569894a2ac/close' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/bbb4edb8-e383-406f-b124-e203cac41ef1/close' -d '{}' -POST /v2/projects/8747d42d-da0d-4d8a-b2d6-3b569894a2ac/close HTTP/1.1 +POST /v2/projects/bbb4edb8-e383-406f-b124-e203cac41ef1/close HTTP/1.1 {} HTTP/1.1 201 Connection: close -Content-Length: 509 +Content-Length: 560 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:39 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:00 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/close { "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "test.gns3", + "grid_size": 75, "name": "test", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmprp4q67em/projects/8747d42d-da0d-4d8a-b2d6-3b569894a2ac", - "project_id": "8747d42d-da0d-4d8a-b2d6-3b569894a2ac", + "path": "/tmp/tmppndv7ate/projects/bbb4edb8-e383-406f-b124-e203cac41ef1", + "project_id": "bbb4edb8-e383-406f-b124-e203cac41ef1", "scene_height": 1000, "scene_width": 2000, "show_grid": false, @@ -27,5 +29,7 @@ X-Route: /v2/projects/{project_id}/close "show_layers": false, "snap_to_grid": false, "status": "opened", + "supplier": null, + "variables": null, "zoom": 100 } diff --git a/docs/api/examples/controller_post_projectsprojectiddrawings.txt b/docs/api/examples/controller_post_projectsprojectiddrawings.txt index 6f48a69f..5ec78c9f 100644 --- a/docs/api/examples/controller_post_projectsprojectiddrawings.txt +++ b/docs/api/examples/controller_post_projectsprojectiddrawings.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/d714ad44-8fe3-45b1-9ed6-57814a581e3c/drawings' -d '{"svg": "", "x": 10, "y": 20, "z": 0}' +curl -i -X POST 'http://localhost:3080/v2/projects/a04cc336-6b66-4b14-89a7-7776444e9ef1/drawings' -d '{"svg": "", "x": 10, "y": 20, "z": 0}' -POST /v2/projects/d714ad44-8fe3-45b1-9ed6-57814a581e3c/drawings HTTP/1.1 +POST /v2/projects/a04cc336-6b66-4b14-89a7-7776444e9ef1/drawings HTTP/1.1 { "svg": "", "x": 10, @@ -11,15 +11,16 @@ POST /v2/projects/d714ad44-8fe3-45b1-9ed6-57814a581e3c/drawings HTTP/1.1 HTTP/1.1 201 Connection: close -Content-Length: 323 +Content-Length: 344 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/drawings { - "drawing_id": "af7cf5e1-9ebd-4478-aec6-2c8e05993587", - "project_id": "d714ad44-8fe3-45b1-9ed6-57814a581e3c", + "drawing_id": "5969ab3c-c4f3-44db-876f-9b9045848c65", + "locked": false, + "project_id": "a04cc336-6b66-4b14-89a7-7776444e9ef1", "rotation": 0, "svg": "", "x": 10, diff --git a/docs/api/examples/controller_post_projectsprojectidduplicate.txt b/docs/api/examples/controller_post_projectsprojectidduplicate.txt index 6633e521..2b61d206 100644 --- a/docs/api/examples/controller_post_projectsprojectidduplicate.txt +++ b/docs/api/examples/controller_post_projectsprojectidduplicate.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/ddcb0c7a-e706-4278-88fa-95d4d92146a1/duplicate' -d '{"name": "hello"}' +curl -i -X POST 'http://localhost:3080/v2/projects/5d81264e-f289-4d9f-8091-c5c84106fcef/duplicate' -d '{"name": "hello"}' -POST /v2/projects/ddcb0c7a-e706-4278-88fa-95d4d92146a1/duplicate HTTP/1.1 +POST /v2/projects/5d81264e-f289-4d9f-8091-c5c84106fcef/duplicate HTTP/1.1 { "name": "hello" } @@ -8,20 +8,22 @@ POST /v2/projects/ddcb0c7a-e706-4278-88fa-95d4d92146a1/duplicate HTTP/1.1 HTTP/1.1 201 Connection: close -Content-Length: 511 +Content-Length: 562 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:39 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:08 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/duplicate { "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "hello.gns3", + "grid_size": 75, "name": "hello", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpl3bk7hol/projects/c1e2c66f-f922-4848-b9c3-d06ee0a84fba", - "project_id": "c1e2c66f-f922-4848-b9c3-d06ee0a84fba", + "path": "/tmp/tmprex3077g/projects/2467a730-94e3-4882-a75d-173106babe17", + "project_id": "2467a730-94e3-4882-a75d-173106babe17", "scene_height": 1000, "scene_width": 2000, "show_grid": false, @@ -29,5 +31,7 @@ X-Route: /v2/projects/{project_id}/duplicate "show_layers": false, "snap_to_grid": false, "status": "closed", + "supplier": null, + "variables": null, "zoom": 100 } diff --git a/docs/api/examples/controller_post_projectsprojectidlinks.txt b/docs/api/examples/controller_post_projectsprojectidlinks.txt index ec2fd11f..ccc619ab 100644 --- a/docs/api/examples/controller_post_projectsprojectidlinks.txt +++ b/docs/api/examples/controller_post_projectsprojectidlinks.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/1be6903e-2a33-456c-acac-0ce09f4bee53/links' -d '{"nodes": [{"adapter_number": 0, "label": {"text": "Text", "x": 42, "y": 0}, "node_id": "7fd37d81-3c9e-42af-a5a1-04c859278b2b", "port_number": 3}, {"adapter_number": 0, "node_id": "7fd37d81-3c9e-42af-a5a1-04c859278b2b", "port_number": 4}]}' +curl -i -X POST 'http://localhost:3080/v2/projects/bc535a6b-2209-45fe-8e2c-9c0108585568/links' -d '{"nodes": [{"adapter_number": 0, "label": {"text": "Text", "x": 42, "y": 0}, "node_id": "f612dca3-278d-46b3-a0a2-f69e37611763", "port_number": 3}, {"adapter_number": 0, "node_id": "f612dca3-278d-46b3-a0a2-f69e37611763", "port_number": 4}]}' -POST /v2/projects/1be6903e-2a33-456c-acac-0ce09f4bee53/links HTTP/1.1 +POST /v2/projects/bc535a6b-2209-45fe-8e2c-9c0108585568/links HTTP/1.1 { "nodes": [ { @@ -10,12 +10,12 @@ POST /v2/projects/1be6903e-2a33-456c-acac-0ce09f4bee53/links HTTP/1.1 "x": 42, "y": 0 }, - "node_id": "7fd37d81-3c9e-42af-a5a1-04c859278b2b", + "node_id": "f612dca3-278d-46b3-a0a2-f69e37611763", "port_number": 3 }, { "adapter_number": 0, - "node_id": "7fd37d81-3c9e-42af-a5a1-04c859278b2b", + "node_id": "f612dca3-278d-46b3-a0a2-f69e37611763", "port_number": 4 } ] @@ -26,8 +26,8 @@ HTTP/1.1 409 Connection: close Content-Length: 64 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:49 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/links { diff --git a/docs/api/examples/controller_post_projectsprojectidlinkslinkidstartcapture.txt b/docs/api/examples/controller_post_projectsprojectidlinkslinkidstartcapture.txt index dc3d71af..6ee342a9 100644 --- a/docs/api/examples/controller_post_projectsprojectidlinkslinkidstartcapture.txt +++ b/docs/api/examples/controller_post_projectsprojectidlinkslinkidstartcapture.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/b743b3a3-845f-4604-9459-d673fb3bc9c3/links/57a8d659-29a9-4cbd-888c-090d69a9eb35/start_capture' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/7a8ddb7e-cae5-4ac9-9505-adc88059c21e/links/a4184444-37b6-4fe0-87ff-edec49e81e6c/start_capture' -d '{}' -POST /v2/projects/b743b3a3-845f-4604-9459-d673fb3bc9c3/links/57a8d659-29a9-4cbd-888c-090d69a9eb35/start_capture HTTP/1.1 +POST /v2/projects/7a8ddb7e-cae5-4ac9-9505-adc88059c21e/links/a4184444-37b6-4fe0-87ff-edec49e81e6c/start_capture HTTP/1.1 {} @@ -8,8 +8,8 @@ HTTP/1.1 201 Connection: close Content-Length: 288 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:36 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:50 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/links/{link_id}/start_capture { @@ -17,9 +17,9 @@ X-Route: /v2/projects/{project_id}/links/{link_id}/start_capture "capture_file_path": null, "capturing": false, "filters": {}, - "link_id": "57a8d659-29a9-4cbd-888c-090d69a9eb35", + "link_id": "a4184444-37b6-4fe0-87ff-edec49e81e6c", "link_type": "ethernet", "nodes": [], - "project_id": "b743b3a3-845f-4604-9459-d673fb3bc9c3", + "project_id": "7a8ddb7e-cae5-4ac9-9505-adc88059c21e", "suspend": false } diff --git a/docs/api/examples/controller_post_projectsprojectidlinkslinkidstopcapture.txt b/docs/api/examples/controller_post_projectsprojectidlinkslinkidstopcapture.txt index 0aac297e..861a6aea 100644 --- a/docs/api/examples/controller_post_projectsprojectidlinkslinkidstopcapture.txt +++ b/docs/api/examples/controller_post_projectsprojectidlinkslinkidstopcapture.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/ea22fe63-fea5-47ed-b4a9-49072d7af9b1/links/b9f26c10-ff89-406d-92b4-cce143fe1fa4/stop_capture' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/e13946a5-749d-40a6-8812-5233a3e920e0/links/eb41a4a3-9dcb-49ac-b24f-86b90b50a050/stop_capture' -d '{}' -POST /v2/projects/ea22fe63-fea5-47ed-b4a9-49072d7af9b1/links/b9f26c10-ff89-406d-92b4-cce143fe1fa4/stop_capture HTTP/1.1 +POST /v2/projects/e13946a5-749d-40a6-8812-5233a3e920e0/links/eb41a4a3-9dcb-49ac-b24f-86b90b50a050/stop_capture HTTP/1.1 {} @@ -8,8 +8,8 @@ HTTP/1.1 201 Connection: close Content-Length: 288 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:36 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:51 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/links/{link_id}/stop_capture { @@ -17,9 +17,9 @@ X-Route: /v2/projects/{project_id}/links/{link_id}/stop_capture "capture_file_path": null, "capturing": false, "filters": {}, - "link_id": "b9f26c10-ff89-406d-92b4-cce143fe1fa4", + "link_id": "eb41a4a3-9dcb-49ac-b24f-86b90b50a050", "link_type": "ethernet", "nodes": [], - "project_id": "ea22fe63-fea5-47ed-b4a9-49072d7af9b1", + "project_id": "e13946a5-749d-40a6-8812-5233a3e920e0", "suspend": false } diff --git a/docs/api/examples/controller_post_projectsprojectidnodes.txt b/docs/api/examples/controller_post_projectsprojectidnodes.txt index 88e956da..e224fc95 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodes.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodes.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/654bb44c-a307-4d20-9117-3ed831d71524/nodes' -d '{"compute_id": "example.com", "name": "test", "node_type": "vpcs", "properties": {"startup_script": "echo test"}}' +curl -i -X POST 'http://localhost:3080/v2/projects/e23ce3f1-02a6-4351-9590-48e412c31050/nodes' -d '{"compute_id": "example.com", "name": "test", "node_type": "vpcs", "properties": {"startup_script": "echo test"}}' -POST /v2/projects/654bb44c-a307-4d20-9117-3ed831d71524/nodes HTTP/1.1 +POST /v2/projects/e23ce3f1-02a6-4351-9590-48e412c31050/nodes HTTP/1.1 { "compute_id": "example.com", "name": "test", @@ -13,30 +13,33 @@ POST /v2/projects/654bb44c-a307-4d20-9117-3ed831d71524/nodes HTTP/1.1 HTTP/1.1 201 Connection: close -Content-Length: 1123 +Content-Length: 1201 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:36 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:52 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes { "command_line": null, "compute_id": "example.com", "console": 2048, - "console_host": "", + "console_auto_start": false, + "console_host": "", "console_type": null, + "custom_adapters": [], "first_port_name": null, "height": 59, "label": { "rotation": 0, - "style": "font-size: 10;font-familly: Verdana", + "style": null, "text": "test", "x": null, "y": -40 }, + "locked": false, "name": "test", "node_directory": null, - "node_id": "be9b41b1-6ebb-4351-8f85-88c84b6aeb3f", + "node_id": "3af49712-947f-4764-b960-cf18fa342128", "node_type": "vpcs", "port_name_format": "Ethernet{0}", "port_segment_size": 0, @@ -52,14 +55,15 @@ X-Route: /v2/projects/{project_id}/nodes "short_name": "e0" } ], - "project_id": "654bb44c-a307-4d20-9117-3ed831d71524", + "project_id": "e23ce3f1-02a6-4351-9590-48e412c31050", "properties": { "startup_script": "echo test" }, "status": "stopped", "symbol": ":/symbols/computer.svg", + "template_id": null, "width": 65, "x": 0, "y": 0, - "z": 0 + "z": 1 } diff --git a/docs/api/examples/controller_post_projectsprojectidnodesnodeidduplicate.txt b/docs/api/examples/controller_post_projectsprojectidnodesnodeidduplicate.txt index 5b2bdcb5..3c7fc673 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodesnodeidduplicate.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodesnodeidduplicate.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/00ed3048-63b6-4604-ba0b-fa3eb364b75c/nodes/d945d390-4538-40f4-857c-d6c9bd9577ca/duplicate' -d '{"x": 10, "y": 5, "z": 0}' +curl -i -X POST 'http://localhost:3080/v2/projects/91f18aa5-56b2-4649-b755-e31557c8ff85/nodes/ed49bdc6-41bf-4339-ab59-8e3994d25f6f/duplicate' -d '{"x": 10, "y": 5, "z": 0}' -POST /v2/projects/00ed3048-63b6-4604-ba0b-fa3eb364b75c/nodes/d945d390-4538-40f4-857c-d6c9bd9577ca/duplicate HTTP/1.1 +POST /v2/projects/91f18aa5-56b2-4649-b755-e31557c8ff85/nodes/ed49bdc6-41bf-4339-ab59-8e3994d25f6f/duplicate HTTP/1.1 { "x": 10, "y": 5, @@ -10,30 +10,33 @@ POST /v2/projects/00ed3048-63b6-4604-ba0b-fa3eb364b75c/nodes/d945d390-4538-40f4- HTTP/1.1 201 Connection: close -Content-Length: 1083 +Content-Length: 1161 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:56 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id}/duplicate { "command_line": null, "compute_id": "example.com", "console": null, - "console_host": "", + "console_auto_start": false, + "console_host": "", "console_type": null, + "custom_adapters": [], "first_port_name": null, "height": 59, "label": { "rotation": 0, - "style": "font-size: 10;font-familly: Verdana", + "style": null, "text": "test1", "x": null, "y": -40 }, + "locked": false, "name": "test1", "node_directory": null, - "node_id": "d59096fb-688e-4c7d-9ee2-1de524b97688", + "node_id": "f224b3f7-c59f-471a-9242-ce506289eeff", "node_type": "vpcs", "port_name_format": "Ethernet{0}", "port_segment_size": 0, @@ -49,10 +52,11 @@ X-Route: /v2/projects/{project_id}/nodes/{node_id}/duplicate "short_name": "e0" } ], - "project_id": "00ed3048-63b6-4604-ba0b-fa3eb364b75c", + "project_id": "91f18aa5-56b2-4649-b755-e31557c8ff85", "properties": {}, "status": "stopped", "symbol": ":/symbols/computer.svg", + "template_id": null, "width": 65, "x": 10, "y": 5, diff --git a/docs/api/examples/controller_post_projectsprojectidnodesnodeidreload.txt b/docs/api/examples/controller_post_projectsprojectidnodesnodeidreload.txt index 9e649aba..bea0788e 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodesnodeidreload.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodesnodeidreload.txt @@ -1,35 +1,38 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/23eb0cbc-0923-46c7-9e28-4b5ff829c26b/nodes/9d4f5903-e448-4e92-a2a8-be2e1e3c2390/reload' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/12755712-2549-49c3-adea-bb31849a5704/nodes/d7ff2caa-80ab-47e6-9684-acbb8cb2eb02/reload' -d '{}' -POST /v2/projects/23eb0cbc-0923-46c7-9e28-4b5ff829c26b/nodes/9d4f5903-e448-4e92-a2a8-be2e1e3c2390/reload HTTP/1.1 +POST /v2/projects/12755712-2549-49c3-adea-bb31849a5704/nodes/d7ff2caa-80ab-47e6-9684-acbb8cb2eb02/reload HTTP/1.1 {} -HTTP/1.1 201 +HTTP/1.1 200 Connection: close -Content-Length: 1080 +Content-Length: 1158 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:55 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id}/reload { "command_line": null, "compute_id": "example.com", "console": null, - "console_host": "", + "console_auto_start": false, + "console_host": "", "console_type": null, + "custom_adapters": [], "first_port_name": null, "height": 59, "label": { "rotation": 0, - "style": "font-size: 10;font-familly: Verdana", + "style": null, "text": "test", "x": null, "y": -40 }, + "locked": false, "name": "test", "node_directory": null, - "node_id": "9d4f5903-e448-4e92-a2a8-be2e1e3c2390", + "node_id": "d7ff2caa-80ab-47e6-9684-acbb8cb2eb02", "node_type": "vpcs", "port_name_format": "Ethernet{0}", "port_segment_size": 0, @@ -45,12 +48,13 @@ X-Route: /v2/projects/{project_id}/nodes/{node_id}/reload "short_name": "e0" } ], - "project_id": "23eb0cbc-0923-46c7-9e28-4b5ff829c26b", + "project_id": "12755712-2549-49c3-adea-bb31849a5704", "properties": {}, "status": "stopped", "symbol": ":/symbols/computer.svg", + "template_id": null, "width": 65, "x": 0, "y": 0, - "z": 0 + "z": 1 } diff --git a/docs/api/examples/controller_post_projectsprojectidnodesnodeidstart.txt b/docs/api/examples/controller_post_projectsprojectidnodesnodeidstart.txt index 97c34a72..782ae89e 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodesnodeidstart.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodesnodeidstart.txt @@ -1,35 +1,38 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/8fd130cb-cdc9-4be2-ade1-61a0ed6307c6/nodes/70696eea-870e-4b9f-a43f-727bd5c144c9/start' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/73f003df-a084-4bad-a675-2d5893694242/nodes/eae75346-6f84-44be-b4d1-047120b4683c/start' -d '{}' -POST /v2/projects/8fd130cb-cdc9-4be2-ade1-61a0ed6307c6/nodes/70696eea-870e-4b9f-a43f-727bd5c144c9/start HTTP/1.1 +POST /v2/projects/73f003df-a084-4bad-a675-2d5893694242/nodes/eae75346-6f84-44be-b4d1-047120b4683c/start HTTP/1.1 {} -HTTP/1.1 201 +HTTP/1.1 200 Connection: close -Content-Length: 1080 +Content-Length: 1158 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:54 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id}/start { "command_line": null, "compute_id": "example.com", "console": null, - "console_host": "", + "console_auto_start": false, + "console_host": "", "console_type": null, + "custom_adapters": [], "first_port_name": null, "height": 59, "label": { "rotation": 0, - "style": "font-size: 10;font-familly: Verdana", + "style": null, "text": "test", "x": null, "y": -40 }, + "locked": false, "name": "test", "node_directory": null, - "node_id": "70696eea-870e-4b9f-a43f-727bd5c144c9", + "node_id": "eae75346-6f84-44be-b4d1-047120b4683c", "node_type": "vpcs", "port_name_format": "Ethernet{0}", "port_segment_size": 0, @@ -45,12 +48,13 @@ X-Route: /v2/projects/{project_id}/nodes/{node_id}/start "short_name": "e0" } ], - "project_id": "8fd130cb-cdc9-4be2-ade1-61a0ed6307c6", + "project_id": "73f003df-a084-4bad-a675-2d5893694242", "properties": {}, "status": "stopped", "symbol": ":/symbols/computer.svg", + "template_id": null, "width": 65, "x": 0, "y": 0, - "z": 0 + "z": 1 } diff --git a/docs/api/examples/controller_post_projectsprojectidnodesnodeidstop.txt b/docs/api/examples/controller_post_projectsprojectidnodesnodeidstop.txt index 408da116..96ee094e 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodesnodeidstop.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodesnodeidstop.txt @@ -1,35 +1,38 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/4e05f8d5-3885-4de2-b7fb-cacd9231856c/nodes/432aeaf4-baca-489b-8c01-6bd1a6f8474f/stop' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/4e74b9b1-1702-4e87-96ff-c0f3825260ea/nodes/b25c8412-f660-4257-9d46-9afa2807164d/stop' -d '{}' -POST /v2/projects/4e05f8d5-3885-4de2-b7fb-cacd9231856c/nodes/432aeaf4-baca-489b-8c01-6bd1a6f8474f/stop HTTP/1.1 +POST /v2/projects/4e74b9b1-1702-4e87-96ff-c0f3825260ea/nodes/b25c8412-f660-4257-9d46-9afa2807164d/stop HTTP/1.1 {} -HTTP/1.1 201 +HTTP/1.1 200 Connection: close -Content-Length: 1080 +Content-Length: 1158 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:54 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id}/stop { "command_line": null, "compute_id": "example.com", "console": null, - "console_host": "", + "console_auto_start": false, + "console_host": "", "console_type": null, + "custom_adapters": [], "first_port_name": null, "height": 59, "label": { "rotation": 0, - "style": "font-size: 10;font-familly: Verdana", + "style": null, "text": "test", "x": null, "y": -40 }, + "locked": false, "name": "test", "node_directory": null, - "node_id": "432aeaf4-baca-489b-8c01-6bd1a6f8474f", + "node_id": "b25c8412-f660-4257-9d46-9afa2807164d", "node_type": "vpcs", "port_name_format": "Ethernet{0}", "port_segment_size": 0, @@ -45,12 +48,13 @@ X-Route: /v2/projects/{project_id}/nodes/{node_id}/stop "short_name": "e0" } ], - "project_id": "4e05f8d5-3885-4de2-b7fb-cacd9231856c", + "project_id": "4e74b9b1-1702-4e87-96ff-c0f3825260ea", "properties": {}, "status": "stopped", "symbol": ":/symbols/computer.svg", + "template_id": null, "width": 65, "x": 0, "y": 0, - "z": 0 + "z": 1 } diff --git a/docs/api/examples/controller_post_projectsprojectidnodesnodeidsuspend.txt b/docs/api/examples/controller_post_projectsprojectidnodesnodeidsuspend.txt index 2897f10d..c731e932 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodesnodeidsuspend.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodesnodeidsuspend.txt @@ -1,35 +1,38 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/85b77222-5d34-4012-8f19-ceb3261913a3/nodes/64607fac-75cf-49ca-ac0f-21a22fb72374/suspend' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/87d2ca72-8c4c-42ef-89c9-4ad6c6d085a1/nodes/bc87d11c-4dae-46e9-af45-dd726090b46a/suspend' -d '{}' -POST /v2/projects/85b77222-5d34-4012-8f19-ceb3261913a3/nodes/64607fac-75cf-49ca-ac0f-21a22fb72374/suspend HTTP/1.1 +POST /v2/projects/87d2ca72-8c4c-42ef-89c9-4ad6c6d085a1/nodes/bc87d11c-4dae-46e9-af45-dd726090b46a/suspend HTTP/1.1 {} -HTTP/1.1 201 +HTTP/1.1 200 Connection: close -Content-Length: 1080 +Content-Length: 1158 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:55 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id}/suspend { "command_line": null, "compute_id": "example.com", "console": null, - "console_host": "", + "console_auto_start": false, + "console_host": "", "console_type": null, + "custom_adapters": [], "first_port_name": null, "height": 59, "label": { "rotation": 0, - "style": "font-size: 10;font-familly: Verdana", + "style": null, "text": "test", "x": null, "y": -40 }, + "locked": false, "name": "test", "node_directory": null, - "node_id": "64607fac-75cf-49ca-ac0f-21a22fb72374", + "node_id": "bc87d11c-4dae-46e9-af45-dd726090b46a", "node_type": "vpcs", "port_name_format": "Ethernet{0}", "port_segment_size": 0, @@ -45,12 +48,13 @@ X-Route: /v2/projects/{project_id}/nodes/{node_id}/suspend "short_name": "e0" } ], - "project_id": "85b77222-5d34-4012-8f19-ceb3261913a3", + "project_id": "87d2ca72-8c4c-42ef-89c9-4ad6c6d085a1", "properties": {}, "status": "stopped", "symbol": ":/symbols/computer.svg", + "template_id": null, "width": 65, "x": 0, "y": 0, - "z": 0 + "z": 1 } diff --git a/docs/api/examples/controller_post_projectsprojectidnodesreload.txt b/docs/api/examples/controller_post_projectsprojectidnodesreload.txt index 53c2ac96..7be54494 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodesreload.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodesreload.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/9f29082c-a385-4d54-87e9-8a6d400e207a/nodes/reload' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/66a2dab9-4501-4ed0-88cc-004acc7a4ee0/nodes/reload' -d '{}' -POST /v2/projects/9f29082c-a385-4d54-87e9-8a6d400e207a/nodes/reload HTTP/1.1 +POST /v2/projects/66a2dab9-4501-4ed0-88cc-004acc7a4ee0/nodes/reload HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:54 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/reload diff --git a/docs/api/examples/controller_post_projectsprojectidnodesstart.txt b/docs/api/examples/controller_post_projectsprojectidnodesstart.txt index 8d0150a8..8ae69263 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodesstart.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodesstart.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/227b7712-8d97-402f-bd92-7a31fcc57384/nodes/start' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/692ab096-8860-45b2-b813-18c06c7635fd/nodes/start' -d '{}' -POST /v2/projects/227b7712-8d97-402f-bd92-7a31fcc57384/nodes/start HTTP/1.1 +POST /v2/projects/692ab096-8860-45b2-b813-18c06c7635fd/nodes/start HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/start diff --git a/docs/api/examples/controller_post_projectsprojectidnodesstop.txt b/docs/api/examples/controller_post_projectsprojectidnodesstop.txt index 50766aec..c7dd8dee 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodesstop.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodesstop.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/50a86076-8e3b-4659-971c-4572f570529d/nodes/stop' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/27012621-6c1e-40e6-95c4-525b95650a5c/nodes/stop' -d '{}' -POST /v2/projects/50a86076-8e3b-4659-971c-4572f570529d/nodes/stop HTTP/1.1 +POST /v2/projects/27012621-6c1e-40e6-95c4-525b95650a5c/nodes/stop HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/stop diff --git a/docs/api/examples/controller_post_projectsprojectidnodessuspend.txt b/docs/api/examples/controller_post_projectsprojectidnodessuspend.txt index 60c54cd1..fde6b0dc 100644 --- a/docs/api/examples/controller_post_projectsprojectidnodessuspend.txt +++ b/docs/api/examples/controller_post_projectsprojectidnodessuspend.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/69e261f4-033b-45c5-b7ab-7f013e9bc4b6/nodes/suspend' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/70e72209-64ee-4c30-a42e-7cd9118eeedc/nodes/suspend' -d '{}' -POST /v2/projects/69e261f4-033b-45c5-b7ab-7f013e9bc4b6/nodes/suspend HTTP/1.1 +POST /v2/projects/70e72209-64ee-4c30-a42e-7cd9118eeedc/nodes/suspend HTTP/1.1 {} @@ -8,7 +8,7 @@ HTTP/1.1 204 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/suspend diff --git a/docs/api/examples/controller_post_projectsprojectidopen.txt b/docs/api/examples/controller_post_projectsprojectidopen.txt index 578be069..0f922883 100644 --- a/docs/api/examples/controller_post_projectsprojectidopen.txt +++ b/docs/api/examples/controller_post_projectsprojectidopen.txt @@ -1,25 +1,27 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/adbff87f-85f7-4b0d-af50-6b1fcaba5b4f/open' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/2d710039-622b-4539-b96d-124c2f106730/open' -d '{}' -POST /v2/projects/adbff87f-85f7-4b0d-af50-6b1fcaba5b4f/open HTTP/1.1 +POST /v2/projects/2d710039-622b-4539-b96d-124c2f106730/open HTTP/1.1 {} HTTP/1.1 201 Connection: close -Content-Length: 509 +Content-Length: 560 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:39 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:01 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/open { "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "test.gns3", + "grid_size": 75, "name": "test", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp5pvhkyby/projects/adbff87f-85f7-4b0d-af50-6b1fcaba5b4f", - "project_id": "adbff87f-85f7-4b0d-af50-6b1fcaba5b4f", + "path": "/tmp/tmpl5wx5e9z/projects/2d710039-622b-4539-b96d-124c2f106730", + "project_id": "2d710039-622b-4539-b96d-124c2f106730", "scene_height": 1000, "scene_width": 2000, "show_grid": false, @@ -27,5 +29,7 @@ X-Route: /v2/projects/{project_id}/open "show_layers": false, "snap_to_grid": false, "status": "opened", + "supplier": null, + "variables": null, "zoom": 100 } diff --git a/docs/api/examples/controller_post_projectsprojectidsnapshots.txt b/docs/api/examples/controller_post_projectsprojectidsnapshots.txt index 35fcd5c6..71f85f4c 100644 --- a/docs/api/examples/controller_post_projectsprojectidsnapshots.txt +++ b/docs/api/examples/controller_post_projectsprojectidsnapshots.txt @@ -1,6 +1,6 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/4fbbc572-fcc6-440a-9bc3-d8cd080c22e6/snapshots' -d '{"name": "snap1"}' +curl -i -X POST 'http://localhost:3080/v2/projects/6b02daca-6b3b-4349-a874-af2259c033fa/snapshots' -d '{"name": "snap1"}' -POST /v2/projects/4fbbc572-fcc6-440a-9bc3-d8cd080c22e6/snapshots HTTP/1.1 +POST /v2/projects/6b02daca-6b3b-4349-a874-af2259c033fa/snapshots HTTP/1.1 { "name": "snap1" } @@ -10,13 +10,13 @@ HTTP/1.1 201 Connection: close Content-Length: 170 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:40 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:11 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/snapshots { - "created_at": 1515399400, + "created_at": 1553935810, "name": "snap1", - "project_id": "4fbbc572-fcc6-440a-9bc3-d8cd080c22e6", - "snapshot_id": "b99084ad-7093-46ea-af8a-45f30f2ccaee" + "project_id": "6b02daca-6b3b-4349-a874-af2259c033fa", + "snapshot_id": "252d6561-fc64-4e13-8313-639777f1c525" } diff --git a/docs/api/examples/controller_post_projectsprojectidsnapshotssnapshotidrestore.txt b/docs/api/examples/controller_post_projectsprojectidsnapshotssnapshotidrestore.txt index 2ce17dda..9fe53733 100644 --- a/docs/api/examples/controller_post_projectsprojectidsnapshotssnapshotidrestore.txt +++ b/docs/api/examples/controller_post_projectsprojectidsnapshotssnapshotidrestore.txt @@ -1,25 +1,27 @@ -curl -i -X POST 'http://localhost:3080/v2/projects/eb0c9744-0882-440d-aeb0-f7e136989c30/snapshots/7782fde0-310f-4eed-8899-0fba6189999c/restore' -d '{}' +curl -i -X POST 'http://localhost:3080/v2/projects/55292fcb-7ff8-4c4a-b16e-423fe9cc4abf/snapshots/7c972c42-cec8-48d2-931a-154c9ab32836/restore' -d '{}' -POST /v2/projects/eb0c9744-0882-440d-aeb0-f7e136989c30/snapshots/7782fde0-310f-4eed-8899-0fba6189999c/restore HTTP/1.1 +POST /v2/projects/55292fcb-7ff8-4c4a-b16e-423fe9cc4abf/snapshots/7c972c42-cec8-48d2-931a-154c9ab32836/restore HTTP/1.1 {} HTTP/1.1 201 Connection: close -Content-Length: 509 +Content-Length: 560 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:40 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:10 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/snapshots/{snapshot_id}/restore { "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "test.gns3", + "grid_size": 75, "name": "test", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp20r65_qe/projects/eb0c9744-0882-440d-aeb0-f7e136989c30", - "project_id": "eb0c9744-0882-440d-aeb0-f7e136989c30", + "path": "/tmp/tmpn5uwt778/projects/55292fcb-7ff8-4c4a-b16e-423fe9cc4abf", + "project_id": "55292fcb-7ff8-4c4a-b16e-423fe9cc4abf", "scene_height": 1000, "scene_width": 2000, "show_grid": false, @@ -27,5 +29,7 @@ X-Route: /v2/projects/{project_id}/snapshots/{snapshot_id}/restore "show_layers": false, "snap_to_grid": false, "status": "opened", + "supplier": null, + "variables": null, "zoom": 100 } diff --git a/docs/api/examples/controller_post_settings.txt b/docs/api/examples/controller_post_settings.txt deleted file mode 100644 index a72d3147..00000000 --- a/docs/api/examples/controller_post_settings.txt +++ /dev/null @@ -1,20 +0,0 @@ -curl -i -X POST 'http://localhost:3080/v2/settings' -d '{"test": true}' - -POST /v2/settings HTTP/1.1 -{ - "test": true -} - - -HTTP/1.1 201 -Connection: close -Content-Length: 85 -Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:40 GMT -Server: Python/3.6 GNS3/2.1.2dev1 -X-Route: /v2/settings - -{ - "modification_uuid": "c1aaa5d1-ce63-49f4-bfcc-e67dfac60ce3", - "test": true -} diff --git a/docs/api/examples/controller_post_shutdown.txt b/docs/api/examples/controller_post_shutdown.txt index 3793cfdf..4e1efbb4 100644 --- a/docs/api/examples/controller_post_shutdown.txt +++ b/docs/api/examples/controller_post_shutdown.txt @@ -8,7 +8,7 @@ HTTP/1.1 201 Connection: close Content-Length: 0 Content-Type: application/octet-stream -Date: Mon, 08 Jan 2018 08:16:40 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:08 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/shutdown diff --git a/docs/api/examples/controller_post_templates.txt b/docs/api/examples/controller_post_templates.txt new file mode 100644 index 00000000..fed4b2de --- /dev/null +++ b/docs/api/examples/controller_post_templates.txt @@ -0,0 +1,65 @@ +curl -i -X POST 'http://localhost:3080/v2/templates' -d '{"compute_id": "local", "hda_disk_image": "IOSvL2-15.2.4.0.55E.qcow2", "name": "Qemu template", "platform": "i386", "ram": 512, "template_type": "qemu"}' + +POST /v2/templates HTTP/1.1 +{ + "compute_id": "local", + "hda_disk_image": "IOSvL2-15.2.4.0.55E.qcow2", + "name": "Qemu template", + "platform": "i386", + "ram": 512, + "template_type": "qemu" +} + + +HTTP/1.1 201 +Connection: close +Content-Length: 1194 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:50:15 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/templates + +{ + "adapter_type": "e1000", + "adapters": 1, + "bios_image": "", + "boot_priority": "c", + "builtin": false, + "category": "guest", + "cdrom_image": "", + "compute_id": "local", + "console_auto_start": false, + "console_type": "telnet", + "cpu_throttling": 0, + "cpus": 1, + "custom_adapters": [], + "default_name_format": "{name}-{0}", + "first_port_name": "", + "hda_disk_image": "IOSvL2-15.2.4.0.55E.qcow2", + "hda_disk_interface": "ide", + "hdb_disk_image": "", + "hdb_disk_interface": "ide", + "hdc_disk_image": "", + "hdc_disk_interface": "ide", + "hdd_disk_image": "", + "hdd_disk_interface": "ide", + "initrd": "", + "kernel_command_line": "", + "kernel_image": "", + "legacy_networking": false, + "linked_clone": true, + "mac_address": "", + "name": "Qemu template", + "on_close": "power_off", + "options": "", + "platform": "i386", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "process_priority": "normal", + "qemu_path": "", + "ram": 512, + "symbol": ":/symbols/qemu_guest.svg", + "template_id": "fd090867-490f-4310-b903-df7821da6943", + "template_type": "qemu", + "usage": "" +} diff --git a/docs/api/examples/controller_post_templatestemplateidduplicate.txt b/docs/api/examples/controller_post_templatestemplateidduplicate.txt new file mode 100644 index 00000000..c2da13a1 --- /dev/null +++ b/docs/api/examples/controller_post_templatestemplateidduplicate.txt @@ -0,0 +1,27 @@ +curl -i -X POST 'http://localhost:3080/v2/templates/657d7329-4c78-4bfa-ad38-809e4b7e7f17/duplicate' -d '{}' + +POST /v2/templates/657d7329-4c78-4bfa-ad38-809e4b7e7f17/duplicate HTTP/1.1 +{} + + +HTTP/1.1 201 +Connection: close +Content-Length: 378 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:50:14 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/templates/{template_id}/duplicate + +{ + "base_script_file": "vpcs_base_config.txt", + "builtin": false, + "category": "guest", + "compute_id": "local", + "console_auto_start": false, + "console_type": "telnet", + "default_name_format": "PC{0}", + "name": "VPCS_TEST", + "symbol": ":/symbols/vpcs_guest.svg", + "template_id": "da9c4c24-be5f-44ff-b053-169bf92f92a3", + "template_type": "vpcs" +} diff --git a/docs/api/examples/controller_post_version.txt b/docs/api/examples/controller_post_version.txt index febe1d0e..efb86c8c 100644 --- a/docs/api/examples/controller_post_version.txt +++ b/docs/api/examples/controller_post_version.txt @@ -1,8 +1,8 @@ -curl -i -X POST 'http://localhost:3080/v2/version' -d '{"version": "2.1.2dev1"}' +curl -i -X POST 'http://localhost:3080/v2/version' -d '{"version": "2.2.0dev8"}' POST /v2/version HTTP/1.1 { - "version": "2.1.2dev1" + "version": "2.2.0dev8" } @@ -10,10 +10,10 @@ HTTP/1.1 200 Connection: close Content-Length: 30 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:41 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:16 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/version { - "version": "2.1.2dev1" + "version": "2.2.0dev8" } diff --git a/docs/api/examples/controller_put_computescomputeid.txt b/docs/api/examples/controller_put_computescomputeid.txt index dc0e039d..f9511b3e 100644 --- a/docs/api/examples/controller_put_computescomputeid.txt +++ b/docs/api/examples/controller_put_computescomputeid.txt @@ -13,10 +13,10 @@ PUT /v2/computes/my_compute_id HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 335 +Content-Length: 359 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:20 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:46 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/computes/{compute_id} { @@ -28,6 +28,7 @@ X-Route: /v2/computes/{compute_id} "connected": false, "cpu_usage_percent": null, "host": "localhost", + "last_error": null, "memory_usage_percent": null, "name": "http://julien@localhost:84", "port": 84, diff --git a/docs/api/examples/controller_put_gns3vm.txt b/docs/api/examples/controller_put_gns3vm.txt index 8163c726..7d9f686f 100644 --- a/docs/api/examples/controller_put_gns3vm.txt +++ b/docs/api/examples/controller_put_gns3vm.txt @@ -10,8 +10,8 @@ HTTP/1.1 201 Connection: close Content-Length: 27 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:49 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/gns3vm { diff --git a/docs/api/examples/controller_put_projectsprojectid.txt b/docs/api/examples/controller_put_projectsprojectid.txt index 991326ce..8f940169 100644 --- a/docs/api/examples/controller_put_projectsprojectid.txt +++ b/docs/api/examples/controller_put_projectsprojectid.txt @@ -8,19 +8,21 @@ PUT /v2/projects/10010203-0405-0607-0809-0a0b0c0d0e0f HTTP/1.1 HTTP/1.1 200 Connection: close -Content-Length: 510 +Content-Length: 692 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:38 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:50:00 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id} { "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "test.gns3", + "grid_size": 75, "name": "test2", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp3n7ijfjb/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", + "path": "/tmp/tmpzsyyfzvu/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f", "scene_height": 1000, "scene_width": 2000, @@ -29,5 +31,15 @@ X-Route: /v2/projects/{project_id} "show_layers": false, "snap_to_grid": false, "status": "opened", + "supplier": null, + "variables": [ + { + "name": "TEST1" + }, + { + "name": "TEST2", + "value": "value1" + } + ], "zoom": 100 } diff --git a/docs/api/examples/controller_put_projectsprojectiddrawingsdrawingid.txt b/docs/api/examples/controller_put_projectsprojectiddrawingsdrawingid.txt index b4c8f432..cdfd5b3d 100644 --- a/docs/api/examples/controller_put_projectsprojectiddrawingsdrawingid.txt +++ b/docs/api/examples/controller_put_projectsprojectiddrawingsdrawingid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/projects/730a3525-db50-4a6a-ac7b-c724c3eed9e8/drawings/eb4a10ff-3cd1-47dd-b95b-1792d2b08f5c' -d '{"x": 42}' +curl -i -X PUT 'http://localhost:3080/v2/projects/a6488c74-5a5d-43ad-bb7a-ea59b438fed1/drawings/84341c5d-2f21-4e47-ab58-7f8297edff59' -d '{"x": 42}' -PUT /v2/projects/730a3525-db50-4a6a-ac7b-c724c3eed9e8/drawings/eb4a10ff-3cd1-47dd-b95b-1792d2b08f5c HTTP/1.1 +PUT /v2/projects/a6488c74-5a5d-43ad-bb7a-ea59b438fed1/drawings/84341c5d-2f21-4e47-ab58-7f8297edff59 HTTP/1.1 { "x": 42 } @@ -8,15 +8,16 @@ PUT /v2/projects/730a3525-db50-4a6a-ac7b-c724c3eed9e8/drawings/eb4a10ff-3cd1-47d HTTP/1.1 201 Connection: close -Content-Length: 323 +Content-Length: 344 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:35 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:48 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/drawings/{drawing_id} { - "drawing_id": "eb4a10ff-3cd1-47dd-b95b-1792d2b08f5c", - "project_id": "730a3525-db50-4a6a-ac7b-c724c3eed9e8", + "drawing_id": "84341c5d-2f21-4e47-ab58-7f8297edff59", + "locked": false, + "project_id": "a6488c74-5a5d-43ad-bb7a-ea59b438fed1", "rotation": 0, "svg": "", "x": 42, diff --git a/docs/api/examples/controller_put_projectsprojectidlinkslinkid.txt b/docs/api/examples/controller_put_projectsprojectidlinkslinkid.txt index 81d9078d..20c04e47 100644 --- a/docs/api/examples/controller_put_projectsprojectidlinkslinkid.txt +++ b/docs/api/examples/controller_put_projectsprojectidlinkslinkid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/projects/c4cba489-d792-4244-9242-07f53f6c4eac/links/e29aad22-7d24-4648-8282-0c41d1c7e70e' -d '{"filters": {"frequency_drop": [50], "latency": [10]}, "nodes": [{"adapter_number": 0, "label": {"text": "Hello", "x": 64, "y": 0}, "node_id": "eb22314e-ff91-4679-8b65-636ec8b34905", "port_number": 3}, {"adapter_number": 2, "node_id": "1268c0a0-8652-4dba-beaf-07cef8e0a310", "port_number": 4}]}' +curl -i -X PUT 'http://localhost:3080/v2/projects/6d2027c1-ce9b-4db0-855e-e58a13bf5149/links/0677eec3-6872-460a-804b-ccc3525128dc' -d '{"filters": {"frequency_drop": [50], "latency": [10]}, "nodes": [{"adapter_number": 0, "label": {"text": "Hello", "x": 64, "y": 0}, "node_id": "f5d999f4-7e82-4b4d-8495-37e015bd7160", "port_number": 3}, {"adapter_number": 2, "node_id": "692bc02a-c687-4d8d-a94f-f25bea0eaea6", "port_number": 4}]}' -PUT /v2/projects/c4cba489-d792-4244-9242-07f53f6c4eac/links/e29aad22-7d24-4648-8282-0c41d1c7e70e HTTP/1.1 +PUT /v2/projects/6d2027c1-ce9b-4db0-855e-e58a13bf5149/links/0677eec3-6872-460a-804b-ccc3525128dc HTTP/1.1 { "filters": { "frequency_drop": [ @@ -18,12 +18,12 @@ PUT /v2/projects/c4cba489-d792-4244-9242-07f53f6c4eac/links/e29aad22-7d24-4648-8 "x": 64, "y": 0 }, - "node_id": "eb22314e-ff91-4679-8b65-636ec8b34905", + "node_id": "f5d999f4-7e82-4b4d-8495-37e015bd7160", "port_number": 3 }, { "adapter_number": 2, - "node_id": "1268c0a0-8652-4dba-beaf-07cef8e0a310", + "node_id": "692bc02a-c687-4d8d-a94f-f25bea0eaea6", "port_number": 4 } ] @@ -34,8 +34,8 @@ HTTP/1.1 201 Connection: close Content-Length: 1022 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:36 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:50 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/links/{link_id} { @@ -50,7 +50,7 @@ X-Route: /v2/projects/{project_id}/links/{link_id} 10 ] }, - "link_id": "e29aad22-7d24-4648-8282-0c41d1c7e70e", + "link_id": "0677eec3-6872-460a-804b-ccc3525128dc", "link_type": "ethernet", "nodes": [ { @@ -60,7 +60,7 @@ X-Route: /v2/projects/{project_id}/links/{link_id} "x": 64, "y": 0 }, - "node_id": "eb22314e-ff91-4679-8b65-636ec8b34905", + "node_id": "f5d999f4-7e82-4b4d-8495-37e015bd7160", "port_number": 3 }, { @@ -72,10 +72,10 @@ X-Route: /v2/projects/{project_id}/links/{link_id} "x": -10, "y": -10 }, - "node_id": "1268c0a0-8652-4dba-beaf-07cef8e0a310", + "node_id": "692bc02a-c687-4d8d-a94f-f25bea0eaea6", "port_number": 4 } ], - "project_id": "c4cba489-d792-4244-9242-07f53f6c4eac", + "project_id": "6d2027c1-ce9b-4db0-855e-e58a13bf5149", "suspend": false } diff --git a/docs/api/examples/controller_put_projectsprojectidnodesnodeid.txt b/docs/api/examples/controller_put_projectsprojectidnodesnodeid.txt index 1b58e104..09679421 100644 --- a/docs/api/examples/controller_put_projectsprojectidnodesnodeid.txt +++ b/docs/api/examples/controller_put_projectsprojectidnodesnodeid.txt @@ -1,6 +1,6 @@ -curl -i -X PUT 'http://localhost:3080/v2/projects/758ba972-b86f-4fe1-8ee4-55a47010ccd6/nodes/fc936387-be57-4907-b240-bc2806f28a30' -d '{"compute_id": "example.com", "name": "test", "node_type": "vpcs", "properties": {"startup_script": "echo test"}}' +curl -i -X PUT 'http://localhost:3080/v2/projects/4c107b46-f1b3-4652-b0dd-5702ac24cecc/nodes/173e22a8-ca70-4a75-9488-e3ed05ac889a' -d '{"compute_id": "example.com", "name": "test", "node_type": "vpcs", "properties": {"startup_script": "echo test"}}' -PUT /v2/projects/758ba972-b86f-4fe1-8ee4-55a47010ccd6/nodes/fc936387-be57-4907-b240-bc2806f28a30 HTTP/1.1 +PUT /v2/projects/4c107b46-f1b3-4652-b0dd-5702ac24cecc/nodes/173e22a8-ca70-4a75-9488-e3ed05ac889a HTTP/1.1 { "compute_id": "example.com", "name": "test", @@ -13,30 +13,33 @@ PUT /v2/projects/758ba972-b86f-4fe1-8ee4-55a47010ccd6/nodes/fc936387-be57-4907-b HTTP/1.1 200 Connection: close -Content-Length: 1080 +Content-Length: 1158 Content-Type: application/json -Date: Mon, 08 Jan 2018 08:16:37 GMT -Server: Python/3.6 GNS3/2.1.2dev1 +Date: Sat, 30 Mar 2019 08:49:53 GMT +Server: Python/3.6 GNS3/2.2.0dev8 X-Route: /v2/projects/{project_id}/nodes/{node_id} { "command_line": null, "compute_id": "example.com", "console": 2048, - "console_host": "", + "console_auto_start": false, + "console_host": "", "console_type": null, + "custom_adapters": [], "first_port_name": null, "height": 59, "label": { "rotation": 0, - "style": "font-size: 10;font-familly: Verdana", + "style": null, "text": "test", "x": null, "y": -40 }, + "locked": false, "name": "test", "node_directory": null, - "node_id": "fc936387-be57-4907-b240-bc2806f28a30", + "node_id": "173e22a8-ca70-4a75-9488-e3ed05ac889a", "node_type": "vpcs", "port_name_format": "Ethernet{0}", "port_segment_size": 0, @@ -52,12 +55,13 @@ X-Route: /v2/projects/{project_id}/nodes/{node_id} "short_name": "e0" } ], - "project_id": "758ba972-b86f-4fe1-8ee4-55a47010ccd6", + "project_id": "4c107b46-f1b3-4652-b0dd-5702ac24cecc", "properties": {}, "status": "stopped", "symbol": ":/symbols/computer.svg", + "template_id": null, "width": 65, "x": 0, "y": 0, - "z": 0 + "z": 1 } diff --git a/docs/api/examples/controller_put_templatestemplateid.txt b/docs/api/examples/controller_put_templatestemplateid.txt new file mode 100644 index 00000000..d6233cc1 --- /dev/null +++ b/docs/api/examples/controller_put_templatestemplateid.txt @@ -0,0 +1,38 @@ +curl -i -X PUT 'http://localhost:3080/v2/templates/8d3341d1-7ef5-4b64-ae0e-d6044ba0ff91' -d '{"base_script_file": "vpcs_base_config.txt", "category": "guest", "compute_id": "local", "console_auto_start": false, "console_type": "telnet", "default_name_format": "PC{0}", "name": "VPCS_TEST_RENAMED", "symbol": ":/symbols/vpcs_guest.svg", "template_id": "8d3341d1-7ef5-4b64-ae0e-d6044ba0ff91", "template_type": "vpcs"}' + +PUT /v2/templates/8d3341d1-7ef5-4b64-ae0e-d6044ba0ff91 HTTP/1.1 +{ + "base_script_file": "vpcs_base_config.txt", + "category": "guest", + "compute_id": "local", + "console_auto_start": false, + "console_type": "telnet", + "default_name_format": "PC{0}", + "name": "VPCS_TEST_RENAMED", + "symbol": ":/symbols/vpcs_guest.svg", + "template_id": "8d3341d1-7ef5-4b64-ae0e-d6044ba0ff91", + "template_type": "vpcs" +} + + +HTTP/1.1 200 +Connection: close +Content-Length: 386 +Content-Type: application/json +Date: Sat, 30 Mar 2019 08:50:14 GMT +Server: Python/3.6 GNS3/2.2.0dev8 +X-Route: /v2/templates/{template_id} + +{ + "base_script_file": "vpcs_base_config.txt", + "builtin": false, + "category": "guest", + "compute_id": "local", + "console_auto_start": false, + "console_type": "telnet", + "default_name_format": "PC{0}", + "name": "VPCS_TEST_RENAMED", + "symbol": ":/symbols/vpcs_guest.svg", + "template_id": "8d3341d1-7ef5-4b64-ae0e-d6044ba0ff91", + "template_type": "vpcs" +} diff --git a/docs/api/notifications/compute.created.json b/docs/api/notifications/compute.created.json index 48759ae3..9eca2c8e 100644 --- a/docs/api/notifications/compute.created.json +++ b/docs/api/notifications/compute.created.json @@ -7,6 +7,7 @@ "connected": false, "cpu_usage_percent": null, "host": "localhost", + "last_error": null, "memory_usage_percent": null, "name": "http://julien@localhost:84", "port": 84, diff --git a/docs/api/notifications/compute.deleted.json b/docs/api/notifications/compute.deleted.json index 2c489ad4..9eee3296 100644 --- a/docs/api/notifications/compute.deleted.json +++ b/docs/api/notifications/compute.deleted.json @@ -7,6 +7,7 @@ "connected": false, "cpu_usage_percent": null, "host": "localhost", + "last_error": null, "memory_usage_percent": null, "name": "http://julien@localhost:84", "port": 84, diff --git a/docs/api/notifications/compute.updated.json b/docs/api/notifications/compute.updated.json index 75d786f7..8d898760 100644 --- a/docs/api/notifications/compute.updated.json +++ b/docs/api/notifications/compute.updated.json @@ -7,6 +7,7 @@ "connected": false, "cpu_usage_percent": null, "host": "localhost", + "last_error": null, "memory_usage_percent": null, "name": "http://julien@localhost:84", "port": 84, diff --git a/docs/api/notifications/drawing.created.json b/docs/api/notifications/drawing.created.json index b50f542b..37ccb240 100644 --- a/docs/api/notifications/drawing.created.json +++ b/docs/api/notifications/drawing.created.json @@ -1,6 +1,7 @@ { - "drawing_id": "b6e1dcb4-442c-4c55-a1eb-537f57ee7974", - "project_id": "6170501f-a3d6-4ab7-82e7-57b4394538f8", + "drawing_id": "250e1fbb-2a72-43c5-8398-eea0b3df9b74", + "locked": false, + "project_id": "a962f4d7-b5dd-4db2-8a73-ca8c30418fce", "rotation": 0, "svg": "", "x": 10, diff --git a/docs/api/notifications/drawing.deleted.json b/docs/api/notifications/drawing.deleted.json index a7299cc2..126aca78 100644 --- a/docs/api/notifications/drawing.deleted.json +++ b/docs/api/notifications/drawing.deleted.json @@ -1,9 +1,10 @@ { - "drawing_id": "df4f6a0a-429a-40c9-ae38-dbb4733d0750", - "project_id": "3cf20b3c-0602-49a6-b593-d49b6a1a5238", + "drawing_id": "a9c5b7b1-e286-4c54-ba54-cdc5f127f0cc", + "locked": false, + "project_id": "d355abec-d468-4730-8540-291c1745e44c", "rotation": 0, "svg": "", "x": 0, "y": 0, - "z": 0 + "z": 2 } \ No newline at end of file diff --git a/docs/api/notifications/drawing.updated.json b/docs/api/notifications/drawing.updated.json index e39a54d2..fc72091a 100644 --- a/docs/api/notifications/drawing.updated.json +++ b/docs/api/notifications/drawing.updated.json @@ -1,6 +1,7 @@ { - "drawing_id": "eb4a10ff-3cd1-47dd-b95b-1792d2b08f5c", - "project_id": "730a3525-db50-4a6a-ac7b-c724c3eed9e8", + "drawing_id": "84341c5d-2f21-4e47-ab58-7f8297edff59", + "locked": false, + "project_id": "a6488c74-5a5d-43ad-bb7a-ea59b438fed1", "rotation": 0, "x": 42, "y": 20, diff --git a/docs/api/notifications/link.created.json b/docs/api/notifications/link.created.json index 2947c017..446f2e39 100644 --- a/docs/api/notifications/link.created.json +++ b/docs/api/notifications/link.created.json @@ -10,7 +10,7 @@ 10 ] }, - "link_id": "d61729b0-e4c8-4d29-9e37-ed7997d2fcd8", + "link_id": "423fceec-5297-4fa4-8ae7-be7abfeef98e", "link_type": "ethernet", "nodes": [ { @@ -22,7 +22,7 @@ "x": -10, "y": -10 }, - "node_id": "2384cb6c-1783-4872-9c9e-91f015dee027", + "node_id": "2d322416-e9af-4665-8a85-13fbde3b100d", "port_number": 3 }, { @@ -34,10 +34,10 @@ "x": -10, "y": -10 }, - "node_id": "a679eb04-b702-4353-baa2-3554e49396b1", + "node_id": "69dae8da-bded-4b8b-baea-e1bb280432bf", "port_number": 4 } ], - "project_id": "9ca80ee5-8396-4c65-a477-874532d42ed3", + "project_id": "42ee96fe-5802-4164-86d7-f4b8fec50eea", "suspend": false } \ No newline at end of file diff --git a/docs/api/notifications/link.deleted.json b/docs/api/notifications/link.deleted.json index e666a28e..072d8c3b 100644 --- a/docs/api/notifications/link.deleted.json +++ b/docs/api/notifications/link.deleted.json @@ -3,9 +3,9 @@ "capture_file_path": null, "capturing": false, "filters": {}, - "link_id": "3b6257c1-ce3b-44c8-8c6c-a0457d6e9e04", + "link_id": "56ee24d1-9e61-4239-a9fb-d0496c021c91", "link_type": "ethernet", "nodes": [], - "project_id": "2883d355-8b23-4ddd-a21b-ff213e485c29", + "project_id": "5b0d6522-946f-4e88-b4cc-055812007d17", "suspend": false } \ No newline at end of file diff --git a/docs/api/notifications/link.updated.json b/docs/api/notifications/link.updated.json index 9d4c628a..8a2a172c 100644 --- a/docs/api/notifications/link.updated.json +++ b/docs/api/notifications/link.updated.json @@ -10,7 +10,7 @@ 10 ] }, - "link_id": "e29aad22-7d24-4648-8282-0c41d1c7e70e", + "link_id": "0677eec3-6872-460a-804b-ccc3525128dc", "link_type": "ethernet", "nodes": [ { @@ -20,7 +20,7 @@ "x": 64, "y": 0 }, - "node_id": "eb22314e-ff91-4679-8b65-636ec8b34905", + "node_id": "f5d999f4-7e82-4b4d-8495-37e015bd7160", "port_number": 3 }, { @@ -32,10 +32,10 @@ "x": -10, "y": -10 }, - "node_id": "1268c0a0-8652-4dba-beaf-07cef8e0a310", + "node_id": "692bc02a-c687-4d8d-a94f-f25bea0eaea6", "port_number": 4 } ], - "project_id": "c4cba489-d792-4244-9242-07f53f6c4eac", + "project_id": "6d2027c1-ce9b-4db0-855e-e58a13bf5149", "suspend": false } \ No newline at end of file diff --git a/docs/api/notifications/node.updated.json b/docs/api/notifications/node.updated.json deleted file mode 100644 index c01837b0..00000000 --- a/docs/api/notifications/node.updated.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "command_line": "", - "compute_id": "local", - "console": 5004, - "console_host": "127.0.0.1", - "console_type": "telnet", - "first_port_name": null, - "height": 59, - "label": { - "rotation": 0, - "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;", - "text": "PC1", - "x": 18, - "y": -25 - }, - "name": "PC1", - "node_directory": "/private/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/pytest-of-behlers/pytest-0/test_load_project0/project-files/vpcs/64ba8408-afbf-4b66-9cdd-1fd854427478", - "node_id": "64ba8408-afbf-4b66-9cdd-1fd854427478", - "node_type": "vpcs", - "port_name_format": "Ethernet{0}", - "port_segment_size": 0, - "ports": [ - { - "adapter_number": 0, - "data_link_types": { - "Ethernet": "DLT_EN10MB" - }, - "link_type": "ethernet", - "name": "Ethernet0", - "port_number": 0, - "short_name": "e0" - } - ], - "project_id": "3c1be6f9-b4ba-4737-b209-63c47c23359f", - "properties": {}, - "status": "stopped", - "symbol": ":/symbols/computer.svg", - "width": 65, - "x": -300, - "y": -118, - "z": 1 -} \ No newline at end of file diff --git a/docs/api/notifications/project.closed.json b/docs/api/notifications/project.closed.json index 41ca0640..d7bd49aa 100644 --- a/docs/api/notifications/project.closed.json +++ b/docs/api/notifications/project.closed.json @@ -2,10 +2,12 @@ "auto_close": true, "auto_open": false, "auto_start": false, - "filename": "test.gns3", - "name": "test", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmpsh708y29/projects/2f24e0e9-9f39-41d3-a413-e7c14c5db6f7", - "project_id": "2f24e0e9-9f39-41d3-a413-e7c14c5db6f7", + "drawing_grid_size": 25, + "filename": "Test.gns3", + "grid_size": 75, + "name": "Test", + "path": "/tmp/tmps0wphr5t/projects/87c334ef-f588-45ae-98b1-4a54249f1cb9", + "project_id": "87c334ef-f588-45ae-98b1-4a54249f1cb9", "scene_height": 1000, "scene_width": 2000, "show_grid": false, @@ -13,5 +15,7 @@ "show_layers": false, "snap_to_grid": false, "status": "closed", + "supplier": null, + "variables": null, "zoom": 100 } \ No newline at end of file diff --git a/docs/api/notifications/project.updated.json b/docs/api/notifications/project.updated.json index eb1cffb9..924f6d36 100644 --- a/docs/api/notifications/project.updated.json +++ b/docs/api/notifications/project.updated.json @@ -2,9 +2,11 @@ "auto_close": true, "auto_open": false, "auto_start": false, + "drawing_grid_size": 25, "filename": "test.gns3", + "grid_size": 75, "name": "test2", - "path": "/var/folders/qy/g6blgc5n7y93pzg61zyt7cmr0000gn/T/tmp3n7ijfjb/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", + "path": "/tmp/tmpzsyyfzvu/projects/10010203-0405-0607-0809-0a0b0c0d0e0f", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f", "scene_height": 1000, "scene_width": 2000, @@ -13,5 +15,15 @@ "show_layers": false, "snap_to_grid": false, "status": "opened", + "supplier": null, + "variables": [ + { + "name": "TEST1" + }, + { + "name": "TEST2", + "value": "value1" + } + ], "zoom": 100 } \ No newline at end of file diff --git a/docs/api/notifications/settings.updated.json b/docs/api/notifications/settings.updated.json deleted file mode 100644 index fdd99a65..00000000 --- a/docs/api/notifications/settings.updated.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "modification_uuid": "c1aaa5d1-ce63-49f4-bfcc-e67dfac60ce3", - "test": true -} \ No newline at end of file diff --git a/docs/api/notifications/snapshot.restored.json b/docs/api/notifications/snapshot.restored.json index c956d922..518d45b1 100644 --- a/docs/api/notifications/snapshot.restored.json +++ b/docs/api/notifications/snapshot.restored.json @@ -1,6 +1,6 @@ { - "created_at": 1515399400, + "created_at": 1553935809, "name": "test", - "project_id": "eb0c9744-0882-440d-aeb0-f7e136989c30", - "snapshot_id": "7782fde0-310f-4eed-8899-0fba6189999c" + "project_id": "55292fcb-7ff8-4c4a-b16e-423fe9cc4abf", + "snapshot_id": "7c972c42-cec8-48d2-931a-154c9ab32836" } \ No newline at end of file diff --git a/docs/api/notifications/template.created.json b/docs/api/notifications/template.created.json new file mode 100644 index 00000000..abda7694 --- /dev/null +++ b/docs/api/notifications/template.created.json @@ -0,0 +1,44 @@ +{ + "builtin": false, + "category": "switch", + "compute_id": "local", + "default_name_format": "Hub{0}", + "name": "Ethernet hub template", + "ports_mapping": [ + { + "name": "Ethernet0", + "port_number": 0 + }, + { + "name": "Ethernet1", + "port_number": 1 + }, + { + "name": "Ethernet2", + "port_number": 2 + }, + { + "name": "Ethernet3", + "port_number": 3 + }, + { + "name": "Ethernet4", + "port_number": 4 + }, + { + "name": "Ethernet5", + "port_number": 5 + }, + { + "name": "Ethernet6", + "port_number": 6 + }, + { + "name": "Ethernet7", + "port_number": 7 + } + ], + "symbol": ":/symbols/hub.svg", + "template_id": "40d060a4-6646-47c3-a765-2e14e2407a24", + "template_type": "ethernet_hub" +} \ No newline at end of file diff --git a/docs/api/notifications/template.deleted.json b/docs/api/notifications/template.deleted.json new file mode 100644 index 00000000..e6fea3e6 --- /dev/null +++ b/docs/api/notifications/template.deleted.json @@ -0,0 +1,13 @@ +{ + "base_script_file": "vpcs_base_config.txt", + "builtin": false, + "category": "guest", + "compute_id": "local", + "console_auto_start": false, + "console_type": "telnet", + "default_name_format": "PC{0}", + "name": "VPCS_TEST", + "symbol": ":/symbols/vpcs_guest.svg", + "template_id": "34671a00-c069-4631-8007-7f73aa462d7f", + "template_type": "vpcs" +} \ No newline at end of file diff --git a/docs/api/notifications/template.updated.json b/docs/api/notifications/template.updated.json new file mode 100644 index 00000000..2c59febc --- /dev/null +++ b/docs/api/notifications/template.updated.json @@ -0,0 +1,13 @@ +{ + "base_script_file": "vpcs_base_config.txt", + "builtin": false, + "category": "guest", + "compute_id": "local", + "console_auto_start": false, + "console_type": "telnet", + "default_name_format": "PC{0}", + "name": "VPCS_TEST_RENAMED", + "symbol": ":/symbols/vpcs_guest.svg", + "template_id": "8d3341d1-7ef5-4b64-ae0e-d6044ba0ff91", + "template_type": "vpcs" +} \ No newline at end of file diff --git a/docs/api/v2/compute/atm_switch/projectsprojectidatmrelayswitchnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/atm_switch/projectsprojectidatmrelayswitchnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..c1cbb7c0 --- /dev/null +++ b/docs/api/v2/compute/atm_switch/projectsprojectidatmrelayswitchnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/atm_relay_switch/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/atm_relay_switch/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture (always 0) +- **port_number**: Port on the switch + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/atm_switch/projectsprojectidatmswitchnodesnodeidsuspend.rst b/docs/api/v2/compute/atm_switch/projectsprojectidatmswitchnodesnodeidsuspend.rst index 5dfe016d..0c541fcf 100644 --- a/docs/api/v2/compute/atm_switch/projectsprojectidatmswitchnodesnodeidsuspend.rst +++ b/docs/api/v2/compute/atm_switch/projectsprojectidatmswitchnodesnodeidsuspend.rst @@ -5,7 +5,7 @@ POST /v2/compute/projects/**{project_id}**/atm_switch/nodes/**{node_id}**/suspend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suspend an ATM Relay switch +Suspend an ATM Relay switch (does nothing) Parameters ********** diff --git a/docs/api/v2/compute/cloud/projectsprojectidcloudnodes.rst b/docs/api/v2/compute/cloud/projectsprojectidcloudnodes.rst index f074e19c..6d805a3b 100644 --- a/docs/api/v2/compute/cloud/projectsprojectidcloudnodes.rst +++ b/docs/api/v2/compute/cloud/projectsprojectidcloudnodes.rst @@ -44,6 +44,10 @@ Body name ✔ string Cloud name node_id Node UUID ports_mapping array + remote_console_host ['string'] Remote console host or IP + remote_console_http_path string Path of the remote web interface + remote_console_port ['integer', 'null'] Console TCP port + remote_console_type enum Possible values: telnet, vnc, spice, http, https, none Output @@ -58,6 +62,10 @@ Output node_id ✔ string Node UUID ports_mapping ✔ array project_id ✔ string Project UUID + remote_console_host ['string'] Remote console host or IP + remote_console_http_path string Path of the remote web interface + remote_console_port ['integer', 'null'] Console TCP port + remote_console_type enum Possible values: telnet, vnc, spice, http, https, none status enum Possible values: started, stopped, suspended diff --git a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeid.rst b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeid.rst index d6f9bb99..e35a2c09 100644 --- a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeid.rst +++ b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeid.rst @@ -30,6 +30,10 @@ Output node_id ✔ string Node UUID ports_mapping ✔ array project_id ✔ string Project UUID + remote_console_host ['string'] Remote console host or IP + remote_console_http_path string Path of the remote web interface + remote_console_port ['integer', 'null'] Console TCP port + remote_console_type enum Possible values: telnet, vnc, spice, http, https, none status enum Possible values: started, stopped, suspended @@ -85,6 +89,10 @@ Body node_id string Node UUID ports_mapping array project_id string Project UUID + remote_console_host ['string'] Remote console host or IP + remote_console_http_path string Path of the remote web interface + remote_console_port ['integer', 'null'] Console TCP port + remote_console_type enum Possible values: telnet, vnc, spice, http, https, none status enum Possible values: started, stopped, suspended @@ -100,6 +108,10 @@ Output node_id ✔ string Node UUID ports_mapping ✔ array project_id ✔ string Project UUID + remote_console_host ['string'] Remote console host or IP + remote_console_http_path string Path of the remote web interface + remote_console_port ['integer', 'null'] Console TCP port + remote_console_type enum Possible values: telnet, vnc, spice, http, https, none status enum Possible values: started, stopped, suspended diff --git a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.rst index 7d810637..7c42a8bd 100644 --- a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.rst +++ b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -29,7 +29,7 @@ Sample session PUT /v2/compute/projects/**{project_id}**/cloud/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a NIO from a Cloud instance +Update a NIO on a Cloud instance Parameters ********** diff --git a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..c9d8b64c --- /dev/null +++ b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/cloud/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture (always 0) +- **port_number**: Port on the cloud + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst index 869e3ff4..099aa86a 100644 --- a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst +++ b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst @@ -30,3 +30,9 @@ Input data_link_type enum Possible values: DLT_ATM_RFC1483, DLT_EN10MB, DLT_FRELAY, DLT_C_HDLC, DLT_PPP_SERIAL +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt + diff --git a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst index e4059ca5..cc94b45e 100644 --- a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst +++ b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst @@ -20,3 +20,9 @@ Response status codes - **400**: Invalid request - **404**: Instance doesn't exist +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidcloudnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt + diff --git a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidsuspend.rst b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidsuspend.rst index 2452d545..05e97929 100644 --- a/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidsuspend.rst +++ b/docs/api/v2/compute/cloud/projectsprojectidcloudnodesnodeidsuspend.rst @@ -5,7 +5,7 @@ POST /v2/compute/projects/**{project_id}**/cloud/nodes/**{node_id}**/suspend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suspend a cloud +Suspend a cloud (does nothing) Parameters ********** diff --git a/docs/api/v2/compute/docker/projectsprojectiddockernodes.rst b/docs/api/v2/compute/docker/projectsprojectiddockernodes.rst index 4821678e..b1c59f91 100644 --- a/docs/api/v2/compute/docker/projectsprojectiddockernodes.rst +++ b/docs/api/v2/compute/docker/projectsprojectiddockernodes.rst @@ -29,14 +29,16 @@ Input console_http_path string Path of the web interface console_http_port integer Internal port in the container for the HTTP server console_resolution ['string', 'null'] Console resolution for VNC - console_type enum Possible values: telnet, vnc, http, https + console_type enum Possible values: telnet, vnc, http, https, none container_id string Docker container ID Read only + custom_adapters array environment ['string', 'null'] Docker environment variables + extra_hosts ['string', 'null'] Docker extra hosts (added to /etc/hosts) image ✔ string Docker image name name ✔ string Docker container name node_id string Node UUID start_command ['string', 'null'] Docker CMD entry - usage string How to use the qemu VM + usage string How to use the Docker container Output @@ -47,13 +49,15 @@ Output Name Mandatory Type Description adapters ['integer', 'null'] number of adapters aux integer Auxiliary TCP port - console integer Console TCP port + console ['integer', 'null'] Console TCP port console_http_path string Path of the web interface console_http_port integer Internal port in the container for the HTTP server console_resolution string Console resolution for VNC - console_type enum Possible values: telnet, vnc, http, https + console_type enum Possible values: telnet, vnc, http, https, none container_id string Docker container ID Read only + custom_adapters array environment ['string', 'null'] Docker environment + extra_hosts ['string', 'null'] Docker extra hosts (added to /etc/hosts) image string Docker image name Read only name string Docker container name node_directory string Path to the node working directory Read only @@ -61,6 +65,6 @@ Output project_id string Project UUID Read only start_command ['string', 'null'] Docker CMD entry status enum Possible values: started, stopped, suspended - usage string How to use the qemu VM + usage string How to use the Docker container diff --git a/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeid.rst b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeid.rst index a8c718c6..67496300 100644 --- a/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeid.rst +++ b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeid.rst @@ -43,13 +43,15 @@ Input Name Mandatory Type Description adapters ['integer', 'null'] number of adapters aux integer Auxiliary TCP port - console integer Console TCP port + console ['integer', 'null'] Console TCP port console_http_path string Path of the web interface console_http_port integer Internal port in the container for the HTTP server console_resolution string Console resolution for VNC - console_type enum Possible values: telnet, vnc, http, https + console_type enum Possible values: telnet, vnc, http, https, none container_id string Docker container ID Read only + custom_adapters array environment ['string', 'null'] Docker environment + extra_hosts ['string', 'null'] Docker extra hosts (added to /etc/hosts) image string Docker image name Read only name string Docker container name node_directory string Path to the node working directory Read only @@ -57,7 +59,7 @@ Input project_id string Project UUID Read only start_command ['string', 'null'] Docker CMD entry status enum Possible values: started, stopped, suspended - usage string How to use the qemu VM + usage string How to use the Docker container Output @@ -68,13 +70,15 @@ Output Name Mandatory Type Description adapters ['integer', 'null'] number of adapters aux integer Auxiliary TCP port - console integer Console TCP port + console ['integer', 'null'] Console TCP port console_http_path string Path of the web interface console_http_port integer Internal port in the container for the HTTP server console_resolution string Console resolution for VNC - console_type enum Possible values: telnet, vnc, http, https + console_type enum Possible values: telnet, vnc, http, https, none container_id string Docker container ID Read only + custom_adapters array environment ['string', 'null'] Docker environment + extra_hosts ['string', 'null'] Docker extra hosts (added to /etc/hosts) image string Docker image name Read only name string Docker container name node_directory string Path to the node working directory Read only @@ -82,7 +86,7 @@ Output project_id string Project UUID Read only start_command ['string', 'null'] Docker CMD entry status enum Possible values: started, stopped, suspended - usage string How to use the qemu VM + usage string How to use the Docker container Sample session diff --git a/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.rst index c1aff14f..a32ce09b 100644 --- a/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.rst +++ b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -12,7 +12,7 @@ Parameters - **project_id**: Project UUID - **node_id**: Node UUID - **adapter_number**: Adapter where the nio should be added -- **port_number**: Port on the adapter +- **port_number**: Port on the adapter (always 0) Response status codes ********************** @@ -29,14 +29,14 @@ Sample session PUT /v2/compute/projects/**{project_id}**/docker/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a NIO from a Docker instance +Update a NIO on a Docker instance Parameters ********** - **project_id**: Project UUID - **node_id**: Node UUID - **adapter_number**: Network adapter where the nio is located -- **port_number**: Port from where the nio should be updated +- **port_number**: Port from where the nio should be updated (always 0) Response status codes ********************** @@ -60,7 +60,7 @@ Parameters - **project_id**: Project UUID - **node_id**: Node UUID - **adapter_number**: Adapter where the nio should be added -- **port_number**: Port on the adapter +- **port_number**: Port on the adapter (always 0) Response status codes ********************** diff --git a/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..c52514dc --- /dev/null +++ b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/docker/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture +- **port_number**: Port on the adapter (always 0) + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst index 12b041d4..08e218b7 100644 --- a/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst +++ b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst @@ -12,7 +12,7 @@ Parameters - **project_id**: Project UUID - **node_id**: Node UUID - **adapter_number**: Adapter to start a packet capture -- **port_number**: Port on the adapter +- **port_number**: Port on the adapter (always 0) Response status codes ********************** diff --git a/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidsuspend.rst b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidsuspend.rst new file mode 100644 index 00000000..216ccb3f --- /dev/null +++ b/docs/api/v2/compute/docker/projectsprojectiddockernodesnodeidsuspend.rst @@ -0,0 +1,20 @@ +/v2/compute/projects/{project_id}/docker/nodes/{node_id}/suspend +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/docker/nodes/**{node_id}**/suspend +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Suspend a Docker container + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **204**: Instance suspended +- **400**: Invalid request +- **404**: Instance doesn't exist + diff --git a/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodes.rst b/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodes.rst index a47af77e..7d35881d 100644 --- a/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodes.rst +++ b/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodes.rst @@ -27,8 +27,8 @@ Input aux ['null', 'integer'] Auxiliary console TCP port chassis string Cisco router chassis model clock_divisor integer Clock divisor - console integer Console TCP port - console_type enum Possible values: telnet + console ['integer', 'null'] Console TCP port + console_type enum Possible values: telnet, none disk0 integer Disk0 size in MB disk1 integer Disk1 size in MB dynamips_id ['integer', 'null'] Dynamips ID @@ -39,7 +39,7 @@ Input image ✔ string Path to the IOS image image_md5sum ['string', 'null'] Checksum of the IOS image iomem integer I/O memory percentage - mac_addr string Base MAC address + mac_addr ['null', 'string'] Base MAC address midplane enum Possible values: std, vxr mmap boolean MMAP feature name ✔ string Dynamips VM instance name @@ -61,6 +61,7 @@ Input sparsemem boolean Sparse memory feature startup_config_content string Content of IOS startup configuration file system_id string System ID + usage string How to use the Dynamips VM wic0 Network module WIC slot 0 wic1 Network module WIC slot 0 wic2 Network module WIC slot 0 @@ -76,8 +77,8 @@ Output aux ['integer', 'null'] Auxiliary console TCP port chassis string Cisco router chassis model clock_divisor integer Clock divisor - console ✔ integer Console TCP port - console_type ✔ enum Possible values: telnet + console ✔ ['integer', 'null'] Console TCP port + console_type ✔ enum Possible values: telnet, none disk0 integer Disk0 size in MB disk1 integer Disk1 size in MB dynamips_id ✔ integer ID to use with Dynamips @@ -88,7 +89,7 @@ Output image string Path to the IOS image image_md5sum ['string', 'null'] Checksum of the IOS image iomem integer I/O memory percentage - mac_addr string Base MAC address + mac_addr ['null', 'string'] Base MAC address midplane enum Possible values: std, vxr mmap boolean MMAP feature name ✔ string Dynamips VM instance name @@ -111,6 +112,7 @@ Output sparsemem boolean Sparse memory feature status enum Possible values: started, stopped, suspended system_id string System ID + usage string How to use the Dynamips VM wic0 Network module WIC slot 0 wic1 Network module WIC slot 0 wic2 Network module WIC slot 0 diff --git a/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeid.rst b/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeid.rst index 3ea7267c..8904ec62 100644 --- a/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeid.rst +++ b/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeid.rst @@ -28,8 +28,8 @@ Output aux ['integer', 'null'] Auxiliary console TCP port chassis string Cisco router chassis model clock_divisor integer Clock divisor - console ✔ integer Console TCP port - console_type ✔ enum Possible values: telnet + console ✔ ['integer', 'null'] Console TCP port + console_type ✔ enum Possible values: telnet, none disk0 integer Disk0 size in MB disk1 integer Disk1 size in MB dynamips_id ✔ integer ID to use with Dynamips @@ -40,7 +40,7 @@ Output image string Path to the IOS image image_md5sum ['string', 'null'] Checksum of the IOS image iomem integer I/O memory percentage - mac_addr string Base MAC address + mac_addr ['null', 'string'] Base MAC address midplane enum Possible values: std, vxr mmap boolean MMAP feature name ✔ string Dynamips VM instance name @@ -63,6 +63,7 @@ Output sparsemem boolean Sparse memory feature status enum Possible values: started, stopped, suspended system_id string System ID + usage string How to use the Dynamips VM wic0 Network module WIC slot 0 wic1 Network module WIC slot 0 wic2 Network module WIC slot 0 @@ -95,8 +96,8 @@ Input aux integer Auxiliary console TCP port chassis string Cisco router chassis model clock_divisor integer Clock divisor - console integer Console TCP port - console_type enum Possible values: telnet + console ['integer', 'null'] Console TCP port + console_type enum Possible values: telnet, none disk0 integer Disk0 size in MB disk1 integer Disk1 size in MB dynamips_id integer Dynamips ID @@ -107,7 +108,7 @@ Input image string Path to the IOS image image_md5sum ['string', 'null'] Checksum of the IOS image iomem integer I/O memory percentage - mac_addr string Base MAC address + mac_addr ['null', 'string'] Base MAC address midplane enum Possible values: std, vxr mmap boolean MMAP feature name string Dynamips VM instance name @@ -126,6 +127,7 @@ Input slot6 Network module slot 6 sparsemem boolean Sparse memory feature system_id string System ID + usage string How to use the Dynamips VM wic0 Network module WIC slot 0 wic1 Network module WIC slot 0 wic2 Network module WIC slot 0 @@ -141,8 +143,8 @@ Output aux ['integer', 'null'] Auxiliary console TCP port chassis string Cisco router chassis model clock_divisor integer Clock divisor - console ✔ integer Console TCP port - console_type ✔ enum Possible values: telnet + console ✔ ['integer', 'null'] Console TCP port + console_type ✔ enum Possible values: telnet, none disk0 integer Disk0 size in MB disk1 integer Disk1 size in MB dynamips_id ✔ integer ID to use with Dynamips @@ -153,7 +155,7 @@ Output image string Path to the IOS image image_md5sum ['string', 'null'] Checksum of the IOS image iomem integer I/O memory percentage - mac_addr string Base MAC address + mac_addr ['null', 'string'] Base MAC address midplane enum Possible values: std, vxr mmap boolean MMAP feature name ✔ string Dynamips VM instance name @@ -176,6 +178,7 @@ Output sparsemem boolean Sparse memory feature status enum Possible values: started, stopped, suspended system_id string System ID + usage string How to use the Dynamips VM wic0 Network module WIC slot 0 wic1 Network module WIC slot 0 wic2 Network module WIC slot 0 diff --git a/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeidadaptersadapternumberdportsportnumberdnio.rst index f4ade9c2..c8136043 100644 --- a/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeidadaptersadapternumberdportsportnumberdnio.rst +++ b/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -23,7 +23,7 @@ Response status codes PUT /v2/compute/projects/**{project_id}**/dynamips/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a NIO from a Dynamips instance +Update a NIO on a Dynamips instance Parameters ********** diff --git a/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..19695b66 --- /dev/null +++ b/docs/api/v2/compute/dynamips_vm/projectsprojectiddynamipsnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/dynamips/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/dynamips/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture +- **port_number**: Port on the adapter (always 0) + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/ethernet_hub/projectsprojectidethernethubnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/ethernet_hub/projectsprojectidethernethubnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..cd880412 --- /dev/null +++ b/docs/api/v2/compute/ethernet_hub/projectsprojectidethernethubnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/ethernet_hub/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/ethernet_hub/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture (always 0) +- **port_number**: Port on the hub + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/ethernet_hub/projectsprojectidethernethubnodesnodeidsuspend.rst b/docs/api/v2/compute/ethernet_hub/projectsprojectidethernethubnodesnodeidsuspend.rst index e5195707..b4678be3 100644 --- a/docs/api/v2/compute/ethernet_hub/projectsprojectidethernethubnodesnodeidsuspend.rst +++ b/docs/api/v2/compute/ethernet_hub/projectsprojectidethernethubnodesnodeidsuspend.rst @@ -5,7 +5,7 @@ POST /v2/compute/projects/**{project_id}**/ethernet_hub/nodes/**{node_id}**/suspend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suspend an Ethernet hub +Suspend an Ethernet hub (does nothing) Parameters ********** diff --git a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodes.rst b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodes.rst index fe013868..dcbfcb5d 100644 --- a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodes.rst +++ b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodes.rst @@ -42,8 +42,8 @@ Body - - + + @@ -55,8 +55,8 @@ Output
Name Mandatory Type Description
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
name string Ethernet switch name
node_id Node UUID
ports_mapping array
- - + + diff --git a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeid.rst b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeid.rst index 2d03e018..8a56fe64 100644 --- a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeid.rst +++ b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeid.rst @@ -24,8 +24,8 @@ Output
Name Mandatory Type Description
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
name string Ethernet switch name
node_id string Node UUID
ports_mapping array
- - + + @@ -75,8 +75,8 @@ Body
Name Mandatory Type Description
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
name string Ethernet switch name
node_id string Node UUID
ports_mapping array
- - + + @@ -90,8 +90,8 @@ Output
Name Mandatory Type Description
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
name string Ethernet switch name
node_id string Node UUID
ports_mapping array
- - + + diff --git a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..e1d349d5 --- /dev/null +++ b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/ethernet_switch/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/ethernet_switch/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture (always 0) +- **port_number**: Port on the switch + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeidsuspend.rst b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeidsuspend.rst index ca2173a9..e1c568cb 100644 --- a/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeidsuspend.rst +++ b/docs/api/v2/compute/ethernet_switch/projectsprojectidethernetswitchnodesnodeidsuspend.rst @@ -5,7 +5,7 @@ POST /v2/compute/projects/**{project_id}**/ethernet_switch/nodes/**{node_id}**/suspend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suspend an Ethernet switch +Suspend an Ethernet switch (does nothing) Parameters ********** diff --git a/docs/api/v2/compute/frame_relay_switch/projectsprojectidframerelayswitchnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/frame_relay_switch/projectsprojectidframerelayswitchnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..03856bed --- /dev/null +++ b/docs/api/v2/compute/frame_relay_switch/projectsprojectidframerelayswitchnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/frame_relay_switch/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/frame_relay_switch/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture (always 0) +- **port_number**: Port on the switch + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/frame_relay_switch/projectsprojectidframerelayswitchnodesnodeidsuspend.rst b/docs/api/v2/compute/frame_relay_switch/projectsprojectidframerelayswitchnodesnodeidsuspend.rst index 5e48c4a6..ed21ba49 100644 --- a/docs/api/v2/compute/frame_relay_switch/projectsprojectidframerelayswitchnodesnodeidsuspend.rst +++ b/docs/api/v2/compute/frame_relay_switch/projectsprojectidframerelayswitchnodesnodeidsuspend.rst @@ -5,7 +5,7 @@ POST /v2/compute/projects/**{project_id}**/frame_relay_switch/nodes/**{node_id}**/suspend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suspend a Frame Relay switch +Suspend a Frame Relay switch (does nothing) Parameters ********** diff --git a/docs/api/v2/compute/iou/projectsprojectidiounodes.rst b/docs/api/v2/compute/iou/projectsprojectidiounodes.rst index 23ad28e1..09e5335e 100644 --- a/docs/api/v2/compute/iou/projectsprojectidiounodes.rst +++ b/docs/api/v2/compute/iou/projectsprojectidiounodes.rst @@ -25,7 +25,7 @@ Input - + @@ -37,6 +37,7 @@ Input +
Name Mandatory Type Description
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
name string Ethernet switch name
node_id string Node UUID
ports_mapping array
Name Mandatory Type Description
application_id ['integer', 'null'] Application ID for running IOU image
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, null
console_type enum Possible values: telnet, none, null
ethernet_adapters integer How many ethernet adapters are connected to the IOU
l1_keepalives ['boolean', 'null'] Always up ethernet interface
md5sum ['string', 'null'] Checksum of iou binary
ram ['integer', 'null'] Allocated RAM MB
serial_adapters integer How many serial adapters are connected to the IOU
startup_config_content ['string', 'null'] Startup-config of IOU
usage string How to use the IOU VM
use_default_iou_values ['boolean', 'null'] Use default IOU values
@@ -48,8 +49,8 @@ Output Name Mandatory Type Description application_id integer Application ID for running IOU image command_line string Last command line used by GNS3 to start IOU - console integer Console TCP port - console_type enum Possible values: telnet + console ['integer', 'null'] Console TCP port + console_type enum Possible values: telnet, none ethernet_adapters integer How many ethernet adapters are connected to the IOU l1_keepalives boolean Always up ethernet interface md5sum ['string', 'null'] Checksum of iou binary @@ -62,6 +63,7 @@ Output ram integer Allocated RAM MB serial_adapters integer How many serial adapters are connected to the IOU status enum Possible values: started, stopped, suspended + usage string How to use the IOU VM use_default_iou_values ['boolean', 'null'] Use default IOU values diff --git a/docs/api/v2/compute/iou/projectsprojectidiounodesnodeid.rst b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeid.rst index 32b31671..fd60ed4c 100644 --- a/docs/api/v2/compute/iou/projectsprojectidiounodesnodeid.rst +++ b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeid.rst @@ -26,8 +26,8 @@ Output Name Mandatory Type Description application_id integer Application ID for running IOU image command_line string Last command line used by GNS3 to start IOU - console integer Console TCP port - console_type enum Possible values: telnet + console ['integer', 'null'] Console TCP port + console_type enum Possible values: telnet, none ethernet_adapters integer How many ethernet adapters are connected to the IOU l1_keepalives boolean Always up ethernet interface md5sum ['string', 'null'] Checksum of iou binary @@ -40,6 +40,7 @@ Output ram integer Allocated RAM MB serial_adapters integer How many serial adapters are connected to the IOU status enum Possible values: started, stopped, suspended + usage string How to use the IOU VM use_default_iou_values ['boolean', 'null'] Use default IOU values @@ -74,8 +75,8 @@ Input Name Mandatory Type Description application_id integer Application ID for running IOU image command_line string Last command line used by GNS3 to start IOU - console integer Console TCP port - console_type enum Possible values: telnet + console ['integer', 'null'] Console TCP port + console_type enum Possible values: telnet, none ethernet_adapters integer How many ethernet adapters are connected to the IOU l1_keepalives boolean Always up ethernet interface md5sum ['string', 'null'] Checksum of iou binary @@ -88,6 +89,7 @@ Input ram integer Allocated RAM MB serial_adapters integer How many serial adapters are connected to the IOU status enum Possible values: started, stopped, suspended + usage string How to use the IOU VM use_default_iou_values ['boolean', 'null'] Use default IOU values @@ -99,8 +101,8 @@ Output Name Mandatory Type Description application_id integer Application ID for running IOU image command_line string Last command line used by GNS3 to start IOU - console integer Console TCP port - console_type enum Possible values: telnet + console ['integer', 'null'] Console TCP port + console_type enum Possible values: telnet, none ethernet_adapters integer How many ethernet adapters are connected to the IOU l1_keepalives boolean Always up ethernet interface md5sum ['string', 'null'] Checksum of iou binary @@ -113,6 +115,7 @@ Output ram integer Allocated RAM MB serial_adapters integer How many serial adapters are connected to the IOU status enum Possible values: started, stopped, suspended + usage string How to use the IOU VM use_default_iou_values ['boolean', 'null'] Use default IOU values diff --git a/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.rst index 47cd3ee4..7713c21b 100644 --- a/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.rst +++ b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -29,7 +29,7 @@ Sample session PUT /v2/compute/projects/**{project_id}**/iou/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a NIO from a IOU instance +Update a NIO on an IOU instance Parameters ********** diff --git a/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..2fdd89d9 --- /dev/null +++ b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/iou/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture +- **port_number**: Port on the adapter (always 0) + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidstart.rst b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidstart.rst index 6bce9a00..efcf1778 100644 --- a/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidstart.rst +++ b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidstart.rst @@ -25,6 +25,7 @@ Input +
Name Mandatory Type Description
iourc_content ['string', 'null'] Content of the iourc file. Ignored if Null
license_check boolean Whether the license should be checked
Output @@ -35,8 +36,8 @@ Output Name Mandatory Type Description application_id integer Application ID for running IOU image command_line string Last command line used by GNS3 to start IOU - console integer Console TCP port - console_type enum Possible values: telnet + console ['integer', 'null'] Console TCP port + console_type enum Possible values: telnet, none ethernet_adapters integer How many ethernet adapters are connected to the IOU l1_keepalives boolean Always up ethernet interface md5sum ['string', 'null'] Checksum of iou binary @@ -49,6 +50,7 @@ Output ram integer Allocated RAM MB serial_adapters integer How many serial adapters are connected to the IOU status enum Possible values: started, stopped, suspended + usage string How to use the IOU VM use_default_iou_values ['boolean', 'null'] Use default IOU values diff --git a/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidsuspend.rst b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidsuspend.rst new file mode 100644 index 00000000..93f15640 --- /dev/null +++ b/docs/api/v2/compute/iou/projectsprojectidiounodesnodeidsuspend.rst @@ -0,0 +1,20 @@ +/v2/compute/projects/{project_id}/iou/nodes/{node_id}/suspend +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/iou/nodes/**{node_id}**/suspend +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Suspend an IOU instance (does nothing) + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **204**: Instance suspended +- **400**: Invalid request +- **404**: Instance doesn't exist + diff --git a/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.rst index 0cd29dcd..c71f9ff2 100644 --- a/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.rst +++ b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -29,7 +29,7 @@ Sample session PUT /v2/compute/projects/**{project_id}**/nat/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a NIO from a NAT instance +Update a NIO on a NAT instance Parameters ********** diff --git a/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..b70f35fc --- /dev/null +++ b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/nat/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture (always 0) +- **port_number**: Port on the nat + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst index ca03814b..f7ce3e87 100644 --- a/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst +++ b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst @@ -30,3 +30,9 @@ Input data_link_type enum Possible values: DLT_ATM_RFC1483, DLT_EN10MB, DLT_FRELAY, DLT_C_HDLC, DLT_PPP_SERIAL +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt + diff --git a/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst index 588f1425..855d3fac 100644 --- a/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst +++ b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst @@ -20,3 +20,9 @@ Response status codes - **400**: Invalid request - **404**: Instance doesn't exist +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidnatnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt + diff --git a/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidsuspend.rst b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidsuspend.rst index 9d8e1433..940f0e2e 100644 --- a/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidsuspend.rst +++ b/docs/api/v2/compute/nat/projectsprojectidnatnodesnodeidsuspend.rst @@ -5,7 +5,7 @@ POST /v2/compute/projects/**{project_id}**/nat/nodes/**{node_id}**/suspend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suspend a nat +Suspend a nat (does nothing) Parameters ********** diff --git a/docs/api/v2/controller/appliance/appliancestemplates.rst b/docs/api/v2/compute/network/networkports.rst similarity index 60% rename from docs/api/v2/controller/appliance/appliancestemplates.rst rename to docs/api/v2/compute/network/networkports.rst index 75695005..7e7a4c14 100644 --- a/docs/api/v2/controller/appliance/appliancestemplates.rst +++ b/docs/api/v2/compute/network/networkports.rst @@ -1,19 +1,13 @@ -/v2/appliances/templates +/v2/compute/network/ports ------------------------------------------------------------------------------------------------------------------------------------------ .. contents:: -GET /v2/appliances/templates +GET /v2/compute/network/ports ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -List of appliance templates +List all the ports used by the server Response status codes ********************** -- **200**: Appliance template list returned - -Sample session -*************** - - -.. literalinclude:: ../../../examples/controller_get_appliancestemplates.txt +- **200**: OK diff --git a/docs/api/v2/compute/project/projects.rst b/docs/api/v2/compute/project/projects.rst index bf0f3189..ed7b6a5e 100644 --- a/docs/api/v2/compute/project/projects.rst +++ b/docs/api/v2/compute/project/projects.rst @@ -35,6 +35,8 @@ Input + + @@ -44,6 +46,8 @@ Input + +
Name Mandatory Type Description
auto_close boolean Project auto close
drawing_grid_size integer Grid size for the drawing area for drawings
grid_size integer Grid size for the drawing area for nodes
name ['string', 'null'] Project name
path ['string', 'null'] Project directory
project_id ['string', 'null'] Project UUID
show_interface_labels boolean Show interface labels on the drawing area
show_layers boolean Show layers on the drawing area
snap_to_grid boolean Snap to grid on the drawing area
supplier ['object', 'null'] Supplier of the project
variables ['array', 'null'] Variables required to run the project
zoom integer Zoom of the drawing area
@@ -56,7 +60,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -67,6 +73,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/compute/project/projectsprojectid.rst b/docs/api/v2/compute/project/projectsprojectid.rst index 187a0e49..16392317 100644 --- a/docs/api/v2/compute/project/projectsprojectid.rst +++ b/docs/api/v2/compute/project/projectsprojectid.rst @@ -3,6 +3,73 @@ .. contents:: +PUT /v2/compute/projects/**{project_id}** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Update the project on the server + +Response status codes +********************** +- **201**: Project updated +- **403**: Forbidden to update a project + +Input +******* +.. raw:: html + + + + + + + + + + + + + + + + + + + +
Name Mandatory Type Description
auto_close boolean Project auto close when client cut off the notifications feed
auto_open boolean Project open when GNS3 start
auto_start boolean Project start when opened
drawing_grid_size integer Grid size for the drawing area for drawings
grid_size integer Grid size for the drawing area for nodes
name ['string', 'null'] Project name
path ['string', 'null'] Path of the project on the server (work only with --local)
scene_height integer Height of the drawing area
scene_width integer Width of the drawing area
show_grid boolean Show the grid on the drawing area
show_interface_labels boolean Show interface labels on the drawing area
show_layers boolean Show layers on the drawing area
snap_to_grid boolean Snap to grid on the drawing area
supplier ['object', 'null'] Supplier of the project
variables ['array', 'null'] Variables required to run the project
zoom integer Zoom of the drawing area
+ +Output +******* +.. raw:: html + + + + + + + + + + + + + + + + + + + + + + +
Name Mandatory Type Description
auto_close boolean Project auto close when client cut off the notifications feed
auto_open boolean Project open when GNS3 start
auto_start boolean Project start when opened
drawing_grid_size integer Grid size for the drawing area for drawings
filename ['string', 'null'] Project filename
grid_size integer Grid size for the drawing area for nodes
name ['string', 'null'] Project name
path ['string', 'null'] Project directory
project_id string Project UUID
scene_height integer Height of the drawing area
scene_width integer Width of the drawing area
show_grid boolean Show the grid on the drawing area
show_interface_labels boolean Show interface labels on the drawing area
show_layers boolean Show layers on the drawing area
snap_to_grid boolean Snap to grid on the drawing area
status enum Possible values: opened, closed
supplier ['object', 'null'] Supplier of the project
variables ['array', 'null'] Variables required to run the project
zoom integer Zoom of the drawing area
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_put_projectsprojectid.txt + + GET /v2/compute/projects/**{project_id}** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Get project information @@ -25,7 +92,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -36,6 +105,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/compute/project/projectsprojectidimport.rst b/docs/api/v2/compute/project/projectsprojectidimport.rst deleted file mode 100644 index 4222c6e3..00000000 --- a/docs/api/v2/compute/project/projectsprojectidimport.rst +++ /dev/null @@ -1,41 +0,0 @@ -/v2/compute/projects/{project_id}/import ------------------------------------------------------------------------------------------------------------------------------------------- - -.. contents:: - -POST /v2/compute/projects/**{project_id}**/import -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Import a project from a portable archive - -Parameters -********** -- **project_id**: Project UUID - -Response status codes -********************** -- **200**: Project imported -- **403**: Forbidden to import project - -Output -******* -.. raw:: html - - - - - - - - - - - - - - - - - - -
Name Mandatory Type Description
auto_close boolean Project auto close when client cut off the notifications feed
auto_open boolean Project open when GNS3 start
auto_start boolean Project start when opened
filename ['string', 'null'] Project filename
name ['string', 'null'] Project name
path ['string', 'null'] Project directory
project_id string Project UUID
scene_height integer Height of the drawing area
scene_width integer Width of the drawing area
show_grid boolean Show the grid on the drawing area
show_interface_labels boolean Show interface labels on the drawing area
show_layers boolean Show layers on the drawing area
snap_to_grid boolean Snap to grid on the drawing area
status enum Possible values: opened, closed
zoom integer Zoom of the drawing area
- diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodes.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodes.rst index f9994300..d39588a5 100644 --- a/docs/api/v2/compute/qemu/projectsprojectidqemunodes.rst +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodes.rst @@ -23,18 +23,18 @@ Input - - + - + + @@ -57,12 +57,13 @@ Input + - + - +
Name Mandatory Type Description
acpi_shutdown ['boolean', 'null'] ACPI shutdown support
adapter_type ['string', 'null'] QEMU adapter type
adapters ['integer', 'null'] Number of adapters
bios_image string QEMU bios image path
bios_image_md5sum ['string', 'null'] QEMU bios image checksum
boot_priority enum Possible values: c, d, n, cn, cd
boot_priority enum Possible values: c, d, n, cn, cd, dn, dc, nc, nd
cdrom_image string QEMU cdrom image path
cdrom_image_md5sum ['string', 'null'] QEMU cdrom image checksum
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, vnc, spice
console_type enum Possible values: telnet, vnc, spice, spice+agent, none
cpu_throttling ['integer', 'null'] Percentage of CPU allowed for QEMU
cpus ['integer', 'null'] Number of vCPUs
custom_adapters array
hda_disk_image string QEMU hda disk image path
hda_disk_image_md5sum ['string', 'null'] QEMU hda disk image checksum
hda_disk_interface string QEMU hda interface
mac_address ['string', 'null'] QEMU MAC address
name string QEMU VM instance name
node_id Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
options ['string', 'null'] Additional QEMU options
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb, null
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb, null, null
process_priority enum Possible values: realtime, very high, high, normal, low, very low, null
qemu_path ['string', 'null'] Path to QEMU
ram ['integer', 'null'] Amount of RAM in MB
usage string How to use the qemu VM
usage string How to use the Qemu VM
Output @@ -71,17 +72,16 @@ Output - - + - - + + @@ -106,12 +106,14 @@ Output + - + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown support
adapter_type string QEMU adapter type
adapters integer Number of adapters
bios_image string QEMU bios image path
bios_image_md5sum ['string', 'null'] QEMU bios image checksum
boot_priority enum Possible values: c, d, n, cn, cd
boot_priority enum Possible values: c, d, n, cn, cd, dn, dc, nc, nd
cdrom_image string QEMU cdrom image path
cdrom_image_md5sum ['string', 'null'] QEMU cdrom image checksum
command_line string Last command line used by GNS3 to start QEMU
console integer Console TCP port
console_type enum Possible values: telnet, vnc, spice
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, vnc, spice, spice+agent, none
cpu_throttling integer Percentage of CPU allowed for QEMU
cpus ['integer', 'null'] Number of vCPUs
hda_disk_image string QEMU hda disk image path
name string QEMU VM instance name
node_directory string Path to the VM working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
options string Additional QEMU options
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb, null
process_priority enum Possible values: realtime, very high, high, normal, low, very low
project_id string Project UUID
qemu_path string Path to QEMU
ram integer Amount of RAM in MB
save_vm_state ['boolean', 'null'] Save VM state support
status enum Possible values: started, stopped, suspended
usage string How to use the QEMU VM
diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeid.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeid.rst index b49d25de..fa458038 100644 --- a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeid.rst +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeid.rst @@ -24,17 +24,16 @@ Output - - + - - + + @@ -59,12 +58,14 @@ Output + - + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown support
adapter_type string QEMU adapter type
adapters integer Number of adapters
bios_image string QEMU bios image path
bios_image_md5sum ['string', 'null'] QEMU bios image checksum
boot_priority enum Possible values: c, d, n, cn, cd
boot_priority enum Possible values: c, d, n, cn, cd, dn, dc, nc, nd
cdrom_image string QEMU cdrom image path
cdrom_image_md5sum ['string', 'null'] QEMU cdrom image checksum
command_line string Last command line used by GNS3 to start QEMU
console integer Console TCP port
console_type enum Possible values: telnet, vnc, spice
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, vnc, spice, spice+agent, none
cpu_throttling integer Percentage of CPU allowed for QEMU
cpus ['integer', 'null'] Number of vCPUs
hda_disk_image string QEMU hda disk image path
name string QEMU VM instance name
node_directory string Path to the VM working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
options string Additional QEMU options
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb, null
process_priority enum Possible values: realtime, very high, high, normal, low, very low
project_id string Project UUID
qemu_path string Path to QEMU
ram integer Amount of RAM in MB
save_vm_state ['boolean', 'null'] Save VM state support
status enum Possible values: started, stopped, suspended
usage string How to use the QEMU VM
@@ -98,18 +99,18 @@ Input - - + - + + @@ -131,8 +132,9 @@ Input + - + @@ -145,17 +147,16 @@ Output
Name Mandatory Type Description
acpi_shutdown ['boolean', 'null'] ACPI shutdown support
adapter_type ['string', 'null'] QEMU adapter type
adapters ['integer', 'null'] Number of adapters
bios_image string QEMU bios image path
bios_image_md5sum ['string', 'null'] QEMU bios image checksum
boot_priority enum Possible values: c, d, n, cn, cd
boot_priority enum Possible values: c, d, n, cn, cd, dn, dc, nc, nd
cdrom_image string QEMU cdrom image path
cdrom_image_md5sum ['string', 'null'] QEMU cdrom image checksum
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, vnc, spice
console_type enum Possible values: telnet, vnc, spice, spice+agent, none
cpu_throttling ['integer', 'null'] Percentage of CPU allowed for QEMU
cpus ['integer', 'null'] Number of vCPUs
custom_adapters array
hda_disk_image string QEMU hda disk image path
hda_disk_image_md5sum ['string', 'null'] QEMU hda disk image checksum
hda_disk_interface string QEMU hda interface
linked_clone boolean Whether the VM is a linked clone or not
mac_address ['string', 'null'] QEMU MAC address
name ['string', 'null'] QEMU VM instance name
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
options ['string', 'null'] Additional QEMU options
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb, null
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb, null, null
process_priority enum Possible values: realtime, very high, high, normal, low, very low, null
qemu_path ['string', 'null'] Path to QEMU
ram ['integer', 'null'] Amount of RAM in MB
- - + - - + + @@ -180,12 +181,14 @@ Output + - + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown support
adapter_type string QEMU adapter type
adapters integer Number of adapters
bios_image string QEMU bios image path
bios_image_md5sum ['string', 'null'] QEMU bios image checksum
boot_priority enum Possible values: c, d, n, cn, cd
boot_priority enum Possible values: c, d, n, cn, cd, dn, dc, nc, nd
cdrom_image string QEMU cdrom image path
cdrom_image_md5sum ['string', 'null'] QEMU cdrom image checksum
command_line string Last command line used by GNS3 to start QEMU
console integer Console TCP port
console_type enum Possible values: telnet, vnc, spice
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, vnc, spice, spice+agent, none
cpu_throttling integer Percentage of CPU allowed for QEMU
cpus ['integer', 'null'] Number of vCPUs
hda_disk_image string QEMU hda disk image path
name string QEMU VM instance name
node_directory string Path to the VM working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
options string Additional QEMU options
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb, null
process_priority enum Possible values: realtime, very high, high, normal, low, very low
project_id string Project UUID
qemu_path string Path to QEMU
ram integer Amount of RAM in MB
save_vm_state ['boolean', 'null'] Save VM state support
status enum Possible values: started, stopped, suspended
usage string How to use the QEMU VM
diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.rst index 3155ba4c..171a96a4 100644 --- a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.rst +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -29,7 +29,7 @@ Sample session PUT /v2/compute/projects/**{project_id}**/qemu/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a NIO from a Qemu instance +Update a NIO on a Qemu instance Parameters ********** diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..b5dc1803 --- /dev/null +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/qemu/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture +- **port_number**: Port on the adapter (always 0) + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst index 51c724e7..40043b68 100644 --- a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst @@ -30,3 +30,9 @@ Input data_link_type enum Possible values: DLT_ATM_RFC1483, DLT_EN10MB, DLT_FRELAY, DLT_C_HDLC, DLT_PPP_SERIAL +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt + diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst index f29195ad..681aea4a 100644 --- a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst @@ -20,3 +20,9 @@ Response status codes - **400**: Invalid request - **404**: Instance doesn't exist +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidqemunodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt + diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidresizedisk.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidresizedisk.rst new file mode 100644 index 00000000..806ba0d9 --- /dev/null +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidresizedisk.rst @@ -0,0 +1,29 @@ +/v2/compute/projects/{project_id}/qemu/nodes/{node_id}/resize_disk +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/qemu/nodes/**{node_id}**/resize_disk +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Resize a Qemu VM disk image + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **201**: Instance updated +- **404**: Instance doesn't exist + +Input +******* +.. raw:: html + + + + + +
Name Mandatory Type Description
drive_name enum Possible values: hda, hdb, hdc, hdd
extend integer Number of Megabytes to extend the image
+ diff --git a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidstart.rst b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidstart.rst index 2fc5d209..5df86864 100644 --- a/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidstart.rst +++ b/docs/api/v2/compute/qemu/projectsprojectidqemunodesnodeidstart.rst @@ -24,17 +24,16 @@ Output - - + - - + + @@ -59,12 +58,14 @@ Output + - + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown support
adapter_type string QEMU adapter type
adapters integer Number of adapters
bios_image string QEMU bios image path
bios_image_md5sum ['string', 'null'] QEMU bios image checksum
boot_priority enum Possible values: c, d, n, cn, cd
boot_priority enum Possible values: c, d, n, cn, cd, dn, dc, nc, nd
cdrom_image string QEMU cdrom image path
cdrom_image_md5sum ['string', 'null'] QEMU cdrom image checksum
command_line string Last command line used by GNS3 to start QEMU
console integer Console TCP port
console_type enum Possible values: telnet, vnc, spice
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, vnc, spice, spice+agent, none
cpu_throttling integer Percentage of CPU allowed for QEMU
cpus ['integer', 'null'] Number of vCPUs
hda_disk_image string QEMU hda disk image path
name string QEMU VM instance name
node_directory string Path to the VM working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
options string Additional QEMU options
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb
platform enum Possible values: aarch64, alpha, arm, cris, i386, lm32, m68k, microblaze, microblazeel, mips, mips64, mips64el, mipsel, moxie, or32, ppc, ppc64, ppcemb, s390x, sh4, sh4eb, sparc, sparc64, tricore, unicore32, x86_64, xtensa, xtensaeb, null
process_priority enum Possible values: realtime, very high, high, normal, low, very low
project_id string Project UUID
qemu_path string Path to QEMU
ram integer Amount of RAM in MB
save_vm_state ['boolean', 'null'] Save VM state support
status enum Possible values: started, stopped, suspended
usage string How to use the QEMU VM
diff --git a/docs/api/v2/compute/qemu/qemuimg.rst b/docs/api/v2/compute/qemu/qemuimg.rst index b64f4d8d..3e98cdb8 100644 --- a/docs/api/v2/compute/qemu/qemuimg.rst +++ b/docs/api/v2/compute/qemu/qemuimg.rst @@ -37,3 +37,23 @@ Sample session .. literalinclude:: ../../../examples/compute_post_qemuimg.txt + +PUT /v2/compute/qemu/img +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Update a Qemu image + +Response status codes +********************** +- **201**: Image Updated + +Input +******* +.. raw:: html + + + + + + +
Name Mandatory Type Description
extend integer Number of Megabytes to extend the image
path string Absolute or relative path of the image
qemu_img string Path to the qemu-img binary
+ diff --git a/docs/api/v2/compute/server/debug.rst b/docs/api/v2/compute/server/debug.rst index 1e04dd1a..131a5554 100644 --- a/docs/api/v2/compute/server/debug.rst +++ b/docs/api/v2/compute/server/debug.rst @@ -5,9 +5,9 @@ GET /v2/compute/debug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Return debug informations about the compute +Return debug information about the compute Response status codes ********************** -- **201**: Writed +- **201**: Written diff --git a/docs/api/v2/compute/traceng.rst b/docs/api/v2/compute/traceng.rst new file mode 100644 index 00000000..117bd38a --- /dev/null +++ b/docs/api/v2/compute/traceng.rst @@ -0,0 +1,8 @@ +Traceng +----------------------------- + +.. toctree:: + :glob: + :maxdepth: 2 + + traceng/* diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodes.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodes.rst new file mode 100644 index 00000000..f3943793 --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodes.rst @@ -0,0 +1,57 @@ +/v2/compute/projects/{project_id}/traceng/nodes +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/traceng/nodes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create a new TraceNG instance + +Parameters +********** +- **project_id**: Project UUID + +Response status codes +********************** +- **201**: Instance created +- **400**: Invalid request +- **409**: Conflict + +Input +******* +.. raw:: html + + + + + + + + + +
Name Mandatory Type Description
console ['integer', 'null'] Console TCP port
console_type enum Possible values: none
default_destination ['string'] Default destination IP address or hostname for tracing
ip_address ['string'] Source IP address for tracing
name string TraceNG VM name
node_id Node UUID
+ +Output +******* +.. raw:: html + + + + + + + + + + + + + +
Name Mandatory Type Description
command_line string Last command line used by GNS3 to start TraceNG
console ['integer', 'null'] Console TCP port
console_type enum Possible values: none
default_destination ['string'] Default destination IP address or hostname for tracing
ip_address ['string'] Source IP address for tracing
name string TraceNG VM name
node_directory string Path to the VM working directory
node_id string Node UUID
project_id string Project UUID
status enum Possible values: started, stopped, suspended
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidtracengnodes.txt + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeid.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeid.rst new file mode 100644 index 00000000..9ebca68e --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeid.rst @@ -0,0 +1,120 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id} +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Get a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **200**: Success +- **400**: Invalid request +- **404**: Instance doesn't exist + +Output +******* +.. raw:: html + + + + + + + + + + + + + +
Name Mandatory Type Description
command_line string Last command line used by GNS3 to start TraceNG
console ['integer', 'null'] Console TCP port
console_type enum Possible values: none
default_destination ['string'] Default destination IP address or hostname for tracing
ip_address ['string'] Source IP address for tracing
name string TraceNG VM name
node_directory string Path to the VM working directory
node_id string Node UUID
project_id string Project UUID
status enum Possible values: started, stopped, suspended
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_get_projectsprojectidtracengnodesnodeid.txt + + +PUT /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Update a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **200**: Instance updated +- **400**: Invalid request +- **404**: Instance doesn't exist +- **409**: Conflict + +Input +******* +.. raw:: html + + + + + + + + +
Name Mandatory Type Description
console ['integer', 'null'] Console TCP port
console_type enum Possible values: none
default_destination ['string'] Default destination IP address or hostname for tracing
ip_address ['string'] Source IP address for tracing
name ['string', 'null'] TraceNG VM name
+ +Output +******* +.. raw:: html + + + + + + + + + + + + + +
Name Mandatory Type Description
command_line string Last command line used by GNS3 to start TraceNG
console ['integer', 'null'] Console TCP port
console_type enum Possible values: none
default_destination ['string'] Default destination IP address or hostname for tracing
ip_address ['string'] Source IP address for tracing
name string TraceNG VM name
node_directory string Path to the VM working directory
node_id string Node UUID
project_id string Project UUID
status enum Possible values: started, stopped, suspended
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_put_projectsprojectidtracengnodesnodeid.txt + + +DELETE /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Delete a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **204**: Instance deleted +- **400**: Invalid request +- **404**: Instance doesn't exist + +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_delete_projectsprojectidtracengnodesnodeid.txt + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.rst new file mode 100644 index 00000000..138fad91 --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -0,0 +1,76 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Add a NIO to a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Network adapter where the nio is located +- **port_number**: Port where the nio should be added + +Response status codes +********************** +- **201**: NIO created +- **400**: Invalid request +- **404**: Instance doesn't exist + +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt + + +PUT /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Update a NIO on a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Network adapter where the nio is located +- **port_number**: Port from where the nio should be updated + +Response status codes +********************** +- **201**: NIO updated +- **400**: Invalid request +- **404**: Instance doesn't exist + +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_put_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt + + +DELETE /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Remove a NIO from a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Network adapter where the nio is located +- **port_number**: Port from where the nio should be removed + +Response status codes +********************** +- **204**: NIO deleted +- **400**: Invalid request +- **404**: Instance doesn't exist + +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_delete_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdnio.txt + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..b4651830 --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture +- **port_number**: Port on the adapter + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst new file mode 100644 index 00000000..6a5bdaf4 --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst @@ -0,0 +1,38 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/start_capture +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Start a packet capture on a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to start a packet capture +- **port_number**: Port on the adapter + +Response status codes +********************** +- **200**: Capture started +- **400**: Invalid request +- **404**: Instance doesn't exist + +Input +******* +.. raw:: html + + + + + +
Name Mandatory Type Description
capture_file_name string Capture file name
data_link_type enum Possible values: DLT_ATM_RFC1483, DLT_EN10MB, DLT_FRELAY, DLT_C_HDLC, DLT_PPP_SERIAL
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst new file mode 100644 index 00000000..76d419b8 --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst @@ -0,0 +1,28 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/stop_capture +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stop a packet capture on a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to stop a packet capture +- **port_number**: Port on the adapter + +Response status codes +********************** +- **204**: Capture stopped +- **400**: Invalid request +- **404**: Instance doesn't exist + +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidtracengnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidduplicate.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidduplicate.rst new file mode 100644 index 00000000..949318e0 --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidduplicate.rst @@ -0,0 +1,25 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id}/duplicate +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/duplicate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Duplicate a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **201**: Instance duplicated +- **404**: Instance doesn't exist + +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidtracengnodesnodeidduplicate.txt + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidreload.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidreload.rst new file mode 100644 index 00000000..793efd2a --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidreload.rst @@ -0,0 +1,26 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id}/reload +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/reload +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Reload a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **204**: Instance reloaded +- **400**: Invalid request +- **404**: Instance doesn't exist + +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidtracengnodesnodeidreload.txt + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidstart.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidstart.rst new file mode 100644 index 00000000..0f170d5a --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidstart.rst @@ -0,0 +1,53 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id}/start +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/start +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Start a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **204**: Instance started +- **400**: Invalid request +- **404**: Instance doesn't exist + +Input +******* +.. raw:: html + + + + +
Name Mandatory Type Description
destination ['string'] Host or IP address to trace
+ +Output +******* +.. raw:: html + + + + + + + + + + + + + +
Name Mandatory Type Description
command_line string Last command line used by GNS3 to start TraceNG
console ['integer', 'null'] Console TCP port
console_type enum Possible values: none
default_destination ['string'] Default destination IP address or hostname for tracing
ip_address ['string'] Source IP address for tracing
name string TraceNG VM name
node_directory string Path to the VM working directory
node_id string Node UUID
project_id string Project UUID
status enum Possible values: started, stopped, suspended
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidtracengnodesnodeidstart.txt + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidstop.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidstop.rst new file mode 100644 index 00000000..dd5a3acc --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidstop.rst @@ -0,0 +1,26 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id}/stop +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/stop +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stop a TraceNG instance + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **204**: Instance stopped +- **400**: Invalid request +- **404**: Instance doesn't exist + +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidtracengnodesnodeidstop.txt + diff --git a/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidsuspend.rst b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidsuspend.rst new file mode 100644 index 00000000..e62d3c85 --- /dev/null +++ b/docs/api/v2/compute/traceng/projectsprojectidtracengnodesnodeidsuspend.rst @@ -0,0 +1,20 @@ +/v2/compute/projects/{project_id}/traceng/nodes/{node_id}/suspend +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/compute/projects/**{project_id}**/traceng/nodes/**{node_id}**/suspend +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Suspend a TraceNG instance (does nothing) + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **204**: Instance suspended +- **400**: Invalid request +- **404**: Instance doesn't exist + diff --git a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodes.rst b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodes.rst index 04ce4503..ccb89dfb 100644 --- a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodes.rst +++ b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodes.rst @@ -23,16 +23,18 @@ Input - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VirtualBox adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VirtualBox VM instance name
node_id Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
ram integer Amount of RAM
usage string How to use the VirtualBox VM
use_any_adapter boolean Allow GNS3 to use any VirtualBox adapter
vmname string VirtualBox VM name (in VirtualBox itself)
@@ -43,19 +45,21 @@ Output - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VirtualBox adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VirtualBox VM instance name
node_directory ['string', 'null'] Path to the VM working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
project_id string Project UUID
ram integer Amount of RAM
status enum Possible values: started, stopped, suspended
usage string How to use the VirtualBox VM
use_any_adapter boolean Allow GNS3 to use any VirtualBox adapter
vmname string VirtualBox VM name (in VirtualBox itself)
diff --git a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeid.rst b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeid.rst index 5af6251e..feaaad72 100644 --- a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeid.rst +++ b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeid.rst @@ -24,19 +24,21 @@ Output - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VirtualBox adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VirtualBox VM instance name
node_directory ['string', 'null'] Path to the VM working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
project_id string Project UUID
ram integer Amount of RAM
status enum Possible values: started, stopped, suspended
usage string How to use the VirtualBox VM
use_any_adapter boolean Allow GNS3 to use any VirtualBox adapter
vmname string VirtualBox VM name (in VirtualBox itself)
@@ -70,19 +72,21 @@ Input - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VirtualBox adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VirtualBox VM instance name
node_directory ['string', 'null'] Path to the VM working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
project_id string Project UUID
ram integer Amount of RAM
status enum Possible values: started, stopped, suspended
usage string How to use the VirtualBox VM
use_any_adapter boolean Allow GNS3 to use any VirtualBox adapter
vmname string VirtualBox VM name (in VirtualBox itself)
@@ -93,19 +97,21 @@ Output - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VirtualBox adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VirtualBox VM instance name
node_directory ['string', 'null'] Path to the VM working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
project_id string Project UUID
ram integer Amount of RAM
status enum Possible values: started, stopped, suspended
usage string How to use the VirtualBox VM
use_any_adapter boolean Allow GNS3 to use any VirtualBox adapter
vmname string VirtualBox VM name (in VirtualBox itself)
diff --git a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.rst index 01a6b7b4..77a5e3f9 100644 --- a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.rst +++ b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -29,7 +29,7 @@ Sample session PUT /v2/compute/projects/**{project_id}**/virtualbox/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a NIO from a Virtualbox instance +Update a NIO on a Virtualbox instance Parameters ********** diff --git a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..6bfa6198 --- /dev/null +++ b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/virtualbox/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture +- **port_number**: Port on the adapter (always 0) + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst index d22d2127..569b8b26 100644 --- a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst +++ b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst @@ -30,3 +30,9 @@ Input data_link_type enum Possible values: DLT_ATM_RFC1483, DLT_EN10MB, DLT_FRELAY, DLT_C_HDLC, DLT_PPP_SERIAL +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt + diff --git a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst index 10093905..ae8162b6 100644 --- a/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst +++ b/docs/api/v2/compute/virtualbox/projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst @@ -20,3 +20,9 @@ Response status codes - **400**: Invalid request - **404**: Instance doesn't exist +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidvirtualboxnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt + diff --git a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodes.rst b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodes.rst index 4f75cf88..872c459b 100644 --- a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodes.rst +++ b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodes.rst @@ -23,15 +23,17 @@ Input - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VMware adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VMware VM instance name
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
usage string How to use the VMware VM
use_any_adapter boolean Allow GNS3 to use any VMware adapter
vmx_path string Path to the vmx file
@@ -42,18 +44,20 @@ Output - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VMware adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VMware VM instance name
node_directory ['string', 'null'] Path to the node working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
project_id string Project UUID
status enum Possible values: started, stopped, suspended
usage string How to use the VMware VM
use_any_adapter boolean Allow GNS3 to use any VMware adapter
vmx_path string Path to the vmx file
diff --git a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeid.rst b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeid.rst index ac53f4c8..3436d5e2 100644 --- a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeid.rst +++ b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeid.rst @@ -24,18 +24,20 @@ Output - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VMware adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VMware VM instance name
node_directory ['string', 'null'] Path to the node working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
project_id string Project UUID
status enum Possible values: started, stopped, suspended
usage string How to use the VMware VM
use_any_adapter boolean Allow GNS3 to use any VMware adapter
vmx_path string Path to the vmx file
@@ -69,18 +71,20 @@ Input - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VMware adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VMware VM instance name
node_directory ['string', 'null'] Path to the node working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
project_id string Project UUID
status enum Possible values: started, stopped, suspended
usage string How to use the VMware VM
use_any_adapter boolean Allow GNS3 to use any VMware adapter
vmx_path string Path to the vmx file
@@ -91,18 +95,20 @@ Output - - - + + + + +
Name Mandatory Type Description
acpi_shutdown boolean ACPI shutdown
adapter_type string VMware adapter type
adapters integer Number of adapters
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
custom_adapters array
headless boolean Headless mode
linked_clone boolean Whether the VM is a linked clone or not
name string VMware VM instance name
node_directory ['string', 'null'] Path to the node working directory
node_id string Node UUID
on_close enum Possible values: power_off, shutdown_signal, save_vm_state
project_id string Project UUID
status enum Possible values: started, stopped, suspended
usage string How to use the VMware VM
use_any_adapter boolean Allow GNS3 to use any VMware adapter
vmx_path string Path to the vmx file
diff --git a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.rst index dcc2cb4e..72d55fb2 100644 --- a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.rst +++ b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -29,7 +29,7 @@ Sample session PUT /v2/compute/projects/**{project_id}**/vmware/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a NIO from a Virtualbox instance +Update a NIO on a VMware VM instance Parameters ********** diff --git a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..05c91f74 --- /dev/null +++ b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/vmware/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture +- **port_number**: Port on the adapter (always 0) + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst index d6b37ace..6b18bd1c 100644 --- a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst +++ b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst @@ -30,3 +30,9 @@ Input data_link_type enum Possible values: DLT_ATM_RFC1483, DLT_EN10MB, DLT_FRELAY, DLT_C_HDLC, DLT_PPP_SERIAL +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt + diff --git a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst index 732cf328..506f2c89 100644 --- a/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst +++ b/docs/api/v2/compute/vmware/projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst @@ -20,3 +20,9 @@ Response status codes - **400**: Invalid request - **404**: Instance doesn't exist +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidvmwarenodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt + diff --git a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodes.rst b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodes.rst index d8e29add..59274280 100644 --- a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodes.rst +++ b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodes.rst @@ -24,7 +24,7 @@ Input - + @@ -37,8 +37,8 @@ Output
Name Mandatory Type Description
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet
console_type enum Possible values: telnet, none
name string VPCS VM name
node_id Node UUID
startup_script ['string', 'null'] Content of the VPCS startup script
- - + + diff --git a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeid.rst b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeid.rst index f0f4c377..7d28b2f5 100644 --- a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeid.rst +++ b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeid.rst @@ -25,8 +25,8 @@ Output
Name Mandatory Type Description
command_line string Last command line used by GNS3 to start VPCS
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
name string VPCS VM name
node_directory string Path to the VM working directory
node_id string Node UUID
- - + + @@ -64,7 +64,7 @@ Input
Name Mandatory Type Description
command_line string Last command line used by GNS3 to start VPCS
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
name string VPCS VM name
node_directory string Path to the VM working directory
node_id string Node UUID
- +
Name Mandatory Type Description
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet
console_type enum Possible values: telnet, none
name ['string', 'null'] VPCS VM name
@@ -75,8 +75,8 @@ Output - - + + diff --git a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.rst b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.rst index 16ab6825..05abe714 100644 --- a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.rst +++ b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdnio.rst @@ -29,7 +29,7 @@ Sample session PUT /v2/compute/projects/**{project_id}**/vpcs/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/nio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a NIO from a VPCS instance +Update a NIO on a VPCS instance Parameters ********** diff --git a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst new file mode 100644 index 00000000..2d2d191b --- /dev/null +++ b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdpcap.rst @@ -0,0 +1,22 @@ +/v2/compute/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/compute/projects/**{project_id}**/vpcs/nodes/**{node_id}**/adapters/**{adapter_number:\d+}**/ports/**{port_number:\d+}**/pcap +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Stream the pcap capture file + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID +- **adapter_number**: Adapter to steam a packet capture +- **port_number**: Port on the adapter + +Response status codes +********************** +- **200**: File returned +- **403**: Permission denied +- **404**: The file doesn't exist + diff --git a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst index 4091ed70..d63c1789 100644 --- a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst +++ b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.rst @@ -30,3 +30,9 @@ Input
Name Mandatory Type Description
command_line string Last command line used by GNS3 to start VPCS
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
name string VPCS VM name
node_directory string Path to the VM working directory
node_id string Node UUID
data_link_type enum Possible values: DLT_ATM_RFC1483, DLT_EN10MB, DLT_FRELAY, DLT_C_HDLC, DLT_PPP_SERIAL
+Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstartcapture.txt + diff --git a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst index 3ecc986e..3a6311ee 100644 --- a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst +++ b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.rst @@ -20,3 +20,9 @@ Response status codes - **400**: Invalid request - **404**: Instance doesn't exist +Sample session +*************** + + +.. literalinclude:: ../../../examples/compute_post_projectsprojectidvpcsnodesnodeidadaptersadapternumberdportsportnumberdstopcapture.txt + diff --git a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidstart.rst b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidstart.rst index 7f24b0b5..aaf30e31 100644 --- a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidstart.rst +++ b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidstart.rst @@ -25,8 +25,8 @@ Output - - + + diff --git a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidsuspend.rst b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidsuspend.rst index 32abd416..7f785678 100644 --- a/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidsuspend.rst +++ b/docs/api/v2/compute/vpcs/projectsprojectidvpcsnodesnodeidsuspend.rst @@ -5,7 +5,7 @@ POST /v2/compute/projects/**{project_id}**/vpcs/nodes/**{node_id}**/suspend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Suspend a VPCS instance (stop it) +Suspend a VPCS instance (does nothing) Parameters ********** @@ -14,7 +14,7 @@ Parameters Response status codes ********************** -- **204**: Instance stopped +- **204**: Instance suspended - **400**: Invalid request - **404**: Instance doesn't exist diff --git a/docs/api/v2/controller/appliance/appliances.rst b/docs/api/v2/controller/appliance/appliances.rst index 15f47cea..9f38e487 100644 --- a/docs/api/v2/controller/appliance/appliances.rst +++ b/docs/api/v2/controller/appliance/appliances.rst @@ -5,7 +5,7 @@ GET /v2/appliances ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -List of appliance +List of appliances Response status codes ********************** diff --git a/docs/api/v2/controller/compute/s.rst b/docs/api/v2/controller/compute/s.rst index 5b253638..ef82efac 100644 --- a/docs/api/v2/controller/compute/s.rst +++ b/docs/api/v2/controller/compute/s.rst @@ -5,11 +5,11 @@ POST /v2/computes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Register a compute server +Register a compute Response status codes ********************** -- **201**: Compute server added +- **201**: Compute added Input ******* @@ -34,9 +34,10 @@ Output - + + @@ -47,9 +48,9 @@ Output GET /v2/computes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -List of compute servers +List of computes Response status codes ********************** -- **200**: Compute servers list returned +- **200**: Computes list returned diff --git a/docs/api/v2/controller/compute/sid.rst b/docs/api/v2/controller/compute/sid.rst index 25bcc968..c2ddc10d 100644 --- a/docs/api/v2/controller/compute/sid.rst +++ b/docs/api/v2/controller/compute/sid.rst @@ -5,11 +5,11 @@ PUT /v2/computes/**{compute_id}** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Get a compute server information +Update a compute Response status codes ********************** -- **200**: Compute server updated +- **200**: Compute updated - **400**: Invalid request - **404**: Instance doesn't exist @@ -36,9 +36,10 @@ Output - + + @@ -49,11 +50,11 @@ Output GET /v2/computes/**{compute_id}** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Get a compute server information +Get a compute information Response status codes ********************** -- **200**: Compute server information returned +- **200**: Compute information returned Output ******* @@ -63,9 +64,10 @@ Output - + + diff --git a/docs/api/v2/controller/compute/sidemulatoraction.rst b/docs/api/v2/controller/compute/sidemulatoraction.rst index 9759b03c..854ab006 100644 --- a/docs/api/v2/controller/compute/sidemulatoraction.rst +++ b/docs/api/v2/controller/compute/sidemulatoraction.rst @@ -30,3 +30,17 @@ Response status codes - **200**: OK - **404**: Instance doesn't exist + +PUT /v2/computes/**{compute_id}**/**{emulator}**/**{action:.+}** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Forward call specific to compute node. Read the full compute API for available actions + +Parameters +********** +- **compute_id**: Compute UUID + +Response status codes +********************** +- **200**: OK +- **404**: Instance doesn't exist + diff --git a/docs/api/v2/controller/compute/sidemulatorimages.rst b/docs/api/v2/controller/compute/sidemulatorimages.rst index a050b169..d784e4e2 100644 --- a/docs/api/v2/controller/compute/sidemulatorimages.rst +++ b/docs/api/v2/controller/compute/sidemulatorimages.rst @@ -5,11 +5,12 @@ GET /v2/computes/**{compute_id}**/**{emulator}**/images ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Return the list of images available on compute and controller for this emulator type +Return the list of images available on compute for this emulator type Parameters ********** - **compute_id**: Compute UUID +- **emulator**: Emulator type Response status codes ********************** diff --git a/docs/api/v2/controller/compute/sidports.rst b/docs/api/v2/controller/compute/sidports.rst new file mode 100644 index 00000000..d3be0075 --- /dev/null +++ b/docs/api/v2/controller/compute/sidports.rst @@ -0,0 +1,29 @@ +/v2/computes/{compute_id}/ports +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/computes/**{compute_id}**/ports +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Get ports used by a compute + +Parameters +********** +- **compute_id**: Compute UUID + +Response status codes +********************** +- **200**: Ports information returned + +Output +******* +.. raw:: html + +
Name Mandatory Type Description
command_line string Last command line used by GNS3 to start VPCS
console integer Console TCP port
console_type enum Possible values: telnet
console ['integer', 'null'] Console TCP port
console_type enum Possible values: telnet, none
name string VPCS VM name
node_directory string Path to the VM working directory
node_id string Node UUID
Name Mandatory Type Description
capabilities object Get what a server support
compute_id string Server identifier
connected boolean Whether the controller is connected to the compute server or not
connected boolean Whether the controller is connected to the compute or not
cpu_usage_percent ['number', 'null'] CPU usage of the compute. Read only
host string Server host
last_error ['string', 'null'] Last error on the compute
memory_usage_percent ['number', 'null'] RAM usage of the compute. Read only
name string Server name
port integer Server port
Name Mandatory Type Description
capabilities object Get what a server support
compute_id string Server identifier
connected boolean Whether the controller is connected to the compute server or not
connected boolean Whether the controller is connected to the compute or not
cpu_usage_percent ['number', 'null'] CPU usage of the compute. Read only
host string Server host
last_error ['string', 'null'] Last error on the compute
memory_usage_percent ['number', 'null'] RAM usage of the compute. Read only
name string Server name
port integer Server port
Name Mandatory Type Description
capabilities object Get what a server support
compute_id string Server identifier
connected boolean Whether the controller is connected to the compute server or not
connected boolean Whether the controller is connected to the compute or not
cpu_usage_percent ['number', 'null'] CPU usage of the compute. Read only
host string Server host
last_error ['string', 'null'] Last error on the compute
memory_usage_percent ['number', 'null'] RAM usage of the compute. Read only
name string Server name
port integer Server port
+ + + + + +
Name Mandatory Type Description
console_port_range array Console port range
console_ports array Console ports used by the compute
udp_port_range array UDP port range
udp_ports array UDP ports used by the compute
+ diff --git a/docs/api/v2/controller/drawing/projectsprojectiddrawings.rst b/docs/api/v2/controller/drawing/projectsprojectiddrawings.rst index 6886511c..e66ad95b 100644 --- a/docs/api/v2/controller/drawing/projectsprojectiddrawings.rst +++ b/docs/api/v2/controller/drawing/projectsprojectiddrawings.rst @@ -42,6 +42,7 @@ Input + @@ -57,6 +58,7 @@ Output
Name Mandatory Type Description
drawing_id string Drawing UUID
locked boolean Whether the element locked or not
project_id string Project UUID
rotation integer Rotation of the element
svg string SVG content of the drawing
+ diff --git a/docs/api/v2/controller/drawing/projectsprojectiddrawingsdrawingid.rst b/docs/api/v2/controller/drawing/projectsprojectiddrawingsdrawingid.rst index c3906946..990574bb 100644 --- a/docs/api/v2/controller/drawing/projectsprojectiddrawingsdrawingid.rst +++ b/docs/api/v2/controller/drawing/projectsprojectiddrawingsdrawingid.rst @@ -25,6 +25,7 @@ Output
Name Mandatory Type Description
drawing_id string Drawing UUID
locked boolean Whether the element locked or not
project_id string Project UUID
rotation integer Rotation of the element
svg string SVG content of the drawing
+ @@ -61,6 +62,7 @@ Input
Name Mandatory Type Description
drawing_id string Drawing UUID
locked boolean Whether the element locked or not
project_id string Project UUID
rotation integer Rotation of the element
svg string SVG content of the drawing
+ @@ -76,6 +78,7 @@ Output
Name Mandatory Type Description
drawing_id string Drawing UUID
locked boolean Whether the element locked or not
project_id string Project UUID
rotation integer Rotation of the element
svg string SVG content of the drawing
+ diff --git a/docs/api/v2/controller/link/projectsprojectidlinkslinkidpcap.rst b/docs/api/v2/controller/link/projectsprojectidlinkslinkidpcap.rst index 48426bdd..5724af9e 100644 --- a/docs/api/v2/controller/link/projectsprojectidlinkslinkidpcap.rst +++ b/docs/api/v2/controller/link/projectsprojectidlinkslinkidpcap.rst @@ -5,7 +5,7 @@ GET /v2/projects/**{project_id}**/links/**{link_id}**/pcap ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Stream the pcap capture file +Stream the PCAP capture file from compute Parameters ********** diff --git a/docs/api/v2/controller/node/projectsprojectidnodes.rst b/docs/api/v2/controller/node/projectsprojectidnodes.rst index 80dccc7b..05957a62 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodes.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodes.rst @@ -25,15 +25,18 @@ Input + - + + + - + @@ -41,6 +44,7 @@ Input + @@ -56,15 +60,18 @@ Output + - + + + - + @@ -72,6 +79,7 @@ Output + diff --git a/docs/api/v2/controller/node/projectsprojectidnodesnodeid.rst b/docs/api/v2/controller/node/projectsprojectidnodesnodeid.rst index d7885bbe..30e15f2c 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodesnodeid.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesnodeid.rst @@ -5,7 +5,7 @@ GET /v2/projects/**{project_id}**/nodes/**{node_id}** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Update a node instance +Get a node Response status codes ********************** @@ -22,15 +22,18 @@ Output + - + + + - + @@ -38,6 +41,7 @@ Output + @@ -70,15 +74,18 @@ Input + - + + + - + @@ -86,6 +93,7 @@ Input + @@ -101,15 +109,18 @@ Output + - + + + - + @@ -117,6 +128,7 @@ Output + diff --git a/docs/api/v2/controller/node/projectsprojectidnodesnodeidduplicate.rst b/docs/api/v2/controller/node/projectsprojectidnodesnodeidduplicate.rst index d01e661f..f6241dfe 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodesnodeidduplicate.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesnodeidduplicate.rst @@ -38,15 +38,18 @@ Output + - + + + - + @@ -54,6 +57,7 @@ Output + diff --git a/docs/api/v2/controller/node/projectsprojectidnodesnodeidlinks.rst b/docs/api/v2/controller/node/projectsprojectidnodesnodeidlinks.rst new file mode 100644 index 00000000..911da3f2 --- /dev/null +++ b/docs/api/v2/controller/node/projectsprojectidnodesnodeidlinks.rst @@ -0,0 +1,20 @@ +/v2/projects/{project_id}/nodes/{node_id}/links +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/projects/**{project_id}**/nodes/**{node_id}**/links +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Return all the links connected to this node + +Parameters +********** +- **project_id**: Project UUID +- **node_id**: Node UUID + +Response status codes +********************** +- **200**: Links returned +- **400**: Invalid request +- **404**: Instance doesn't exist + diff --git a/docs/api/v2/controller/node/projectsprojectidnodesnodeidreload.rst b/docs/api/v2/controller/node/projectsprojectidnodesnodeidreload.rst index f9df30a0..a8edd1bb 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodesnodeidreload.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesnodeidreload.rst @@ -14,7 +14,7 @@ Parameters Response status codes ********************** -- **204**: Instance reloaded +- **200**: Instance reloaded - **400**: Invalid request - **404**: Instance doesn't exist @@ -27,15 +27,18 @@ Output + - + + + - + @@ -43,6 +46,7 @@ Output + diff --git a/docs/api/v2/compute/project/projectsprojectidstreampath.rst b/docs/api/v2/controller/node/projectsprojectidnodesnodeidresizedisk.rst similarity index 61% rename from docs/api/v2/compute/project/projectsprojectidstreampath.rst rename to docs/api/v2/controller/node/projectsprojectidnodesnodeidresizedisk.rst index edf4cc80..76aec3e8 100644 --- a/docs/api/v2/compute/project/projectsprojectidstreampath.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesnodeidresizedisk.rst @@ -1,19 +1,20 @@ -/v2/compute/projects/{project_id}/stream/{path:.+} +/v2/projects/{project_id}/nodes/{node_id}/resize_disk ------------------------------------------------------------------------------------------------------------------------------------------ .. contents:: -GET /v2/compute/projects/**{project_id}**/stream/**{path:.+}** +POST /v2/projects/**{project_id}**/nodes/**{node_id}**/resize_disk ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Stream a file from a project +Reload a node instance Parameters ********** - **project_id**: Project UUID +- **node_id**: Node UUID Response status codes ********************** -- **200**: File returned -- **403**: Permission denied -- **404**: The file doesn't exist +- **201**: Disk image resized +- **400**: Invalid request +- **404**: Instance doesn't exist diff --git a/docs/api/v2/controller/node/projectsprojectidnodesnodeidstart.rst b/docs/api/v2/controller/node/projectsprojectidnodesnodeidstart.rst index 384c616a..e79d75ef 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodesnodeidstart.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesnodeidstart.rst @@ -14,7 +14,7 @@ Parameters Response status codes ********************** -- **204**: Instance started +- **200**: Instance started - **400**: Invalid request - **404**: Instance doesn't exist @@ -27,15 +27,18 @@ Output + - + + + - + @@ -43,6 +46,7 @@ Output + diff --git a/docs/api/v2/controller/node/projectsprojectidnodesnodeidstop.rst b/docs/api/v2/controller/node/projectsprojectidnodesnodeidstop.rst index e4a8e0f0..252097ff 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodesnodeidstop.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesnodeidstop.rst @@ -14,7 +14,7 @@ Parameters Response status codes ********************** -- **204**: Instance stopped +- **200**: Instance stopped - **400**: Invalid request - **404**: Instance doesn't exist @@ -27,15 +27,18 @@ Output + - + + + - + @@ -43,6 +46,7 @@ Output + diff --git a/docs/api/v2/controller/node/projectsprojectidnodesnodeidsuspend.rst b/docs/api/v2/controller/node/projectsprojectidnodesnodeidsuspend.rst index 25c10972..992ae49d 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodesnodeidsuspend.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesnodeidsuspend.rst @@ -14,7 +14,7 @@ Parameters Response status codes ********************** -- **204**: Instance suspended +- **200**: Instance suspended - **400**: Invalid request - **404**: Instance doesn't exist @@ -27,15 +27,18 @@ Output + - + + + - + @@ -43,6 +46,7 @@ Output + diff --git a/docs/api/v2/controller/node/projectsprojectidnodesreload.rst b/docs/api/v2/controller/node/projectsprojectidnodesreload.rst index dde5ff1e..c4916bb5 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodesreload.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesreload.rst @@ -26,15 +26,18 @@ Output + - + + + - + @@ -42,6 +45,7 @@ Output + diff --git a/docs/api/v2/controller/node/projectsprojectidnodesstart.rst b/docs/api/v2/controller/node/projectsprojectidnodesstart.rst index ab5c4258..e88977e9 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodesstart.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesstart.rst @@ -26,15 +26,18 @@ Output + - + + + - + @@ -42,6 +45,7 @@ Output + diff --git a/docs/api/v2/controller/node/projectsprojectidnodesstop.rst b/docs/api/v2/controller/node/projectsprojectidnodesstop.rst index 1fd47d5a..ad848f0f 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodesstop.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodesstop.rst @@ -26,15 +26,18 @@ Output + - + + + - + @@ -42,6 +45,7 @@ Output + diff --git a/docs/api/v2/controller/node/projectsprojectidnodessuspend.rst b/docs/api/v2/controller/node/projectsprojectidnodessuspend.rst index 5677d8c2..13cc50eb 100644 --- a/docs/api/v2/controller/node/projectsprojectidnodessuspend.rst +++ b/docs/api/v2/controller/node/projectsprojectidnodessuspend.rst @@ -26,15 +26,18 @@ Output + - + + + - + @@ -42,6 +45,7 @@ Output + diff --git a/docs/api/v2/controller/notification.rst b/docs/api/v2/controller/notification.rst new file mode 100644 index 00000000..04f43e18 --- /dev/null +++ b/docs/api/v2/controller/notification.rst @@ -0,0 +1,8 @@ +Notification +----------------------------- + +.. toctree:: + :glob: + :maxdepth: 2 + + notification/* diff --git a/docs/api/v2/controller/notification/notifications.rst b/docs/api/v2/controller/notification/notifications.rst new file mode 100644 index 00000000..067f28f3 --- /dev/null +++ b/docs/api/v2/controller/notification/notifications.rst @@ -0,0 +1,13 @@ +/v2/notifications +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/notifications +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Receive notifications about the controller + +Response status codes +********************** +- **200**: End of stream + diff --git a/docs/api/v2/controller/notification/notificationsws.rst b/docs/api/v2/controller/notification/notificationsws.rst new file mode 100644 index 00000000..074264e9 --- /dev/null +++ b/docs/api/v2/controller/notification/notificationsws.rst @@ -0,0 +1,13 @@ +/v2/notifications/ws +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/notifications/ws +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Receive notifications about controller from a Websocket + +Response status codes +********************** +- **200**: End of stream + diff --git a/docs/api/v2/controller/project/projects.rst b/docs/api/v2/controller/project/projects.rst index cb5c8deb..fc6c8bd2 100644 --- a/docs/api/v2/controller/project/projects.rst +++ b/docs/api/v2/controller/project/projects.rst @@ -19,6 +19,8 @@ Input
Name Mandatory Type Description
drawing_id string Drawing UUID
locked boolean Whether the element locked or not
project_id string Project UUID
rotation integer Rotation of the element
svg string SVG content of the drawing
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
command_line ['null', 'string'] Command line use to start the node
compute_id string Compute identifier
console ['integer', 'null'] Console TCP port
console_auto_start boolean Automatically start the console when the node has started
console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller.
console_type enum Possible values: vnc, telnet, http, https, spice, null
console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null
custom_adapters array
first_port_name ['string', 'null'] Name of the first port
height integer Height of the node (Read only)
label object
locked boolean Whether the element locked or not
name string Node name
node_directory ['null', 'string'] Working directory of the node. Read only
node_id string Node UUID
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu
node_type enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
port_name_format string Formating for port name {0} will be replace by port number
port_segment_size integer Size of the port segment
ports array List of node ports READ only
properties object Properties specific to an emulator
status enum Possible values: stopped, started, suspended
symbol ['string', 'null'] Symbol of the node
template_id ['null', 'string'] Template UUID from which the node has been created. Read only
width integer Width of the node (Read only)
x integer X position of the node
y integer Y position of the node
+ + @@ -28,6 +30,8 @@ Input + +
Name Mandatory Type Description
auto_close boolean Project auto close
drawing_grid_size integer Grid size for the drawing area for drawings
grid_size integer Grid size for the drawing area for nodes
name ['string', 'null'] Project name
path ['string', 'null'] Project directory
project_id ['string', 'null'] Project UUID
show_interface_labels boolean Show interface labels on the drawing area
show_layers boolean Show layers on the drawing area
snap_to_grid boolean Snap to grid on the drawing area
supplier ['object', 'null'] Supplier of the project
variables ['array', 'null'] Variables required to run the project
zoom integer Zoom of the drawing area
@@ -40,7 +44,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -51,6 +57,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/controller/project/projectsload.rst b/docs/api/v2/controller/project/projectsload.rst index 6ba5f38b..d14e641d 100644 --- a/docs/api/v2/controller/project/projectsload.rst +++ b/docs/api/v2/controller/project/projectsload.rst @@ -34,7 +34,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -45,6 +47,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/controller/project/projectsprojectid.rst b/docs/api/v2/controller/project/projectsprojectid.rst index c5df1bfb..90a97a78 100644 --- a/docs/api/v2/controller/project/projectsprojectid.rst +++ b/docs/api/v2/controller/project/projectsprojectid.rst @@ -42,6 +42,8 @@ Input auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Path of the project on the server (work only with --local) scene_height integer Height of the drawing area @@ -50,6 +52,8 @@ Input show_interface_labels boolean Show interface labels on the drawing area show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area @@ -62,7 +66,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -73,6 +79,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/controller/project/projectsprojectidclose.rst b/docs/api/v2/controller/project/projectsprojectidclose.rst index 7fd2c575..51d0717c 100644 --- a/docs/api/v2/controller/project/projectsprojectidclose.rst +++ b/docs/api/v2/controller/project/projectsprojectidclose.rst @@ -25,7 +25,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -36,6 +38,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/controller/project/projectsprojectidduplicate.rst b/docs/api/v2/controller/project/projectsprojectidduplicate.rst index f855c403..13e63c0f 100644 --- a/docs/api/v2/controller/project/projectsprojectidduplicate.rst +++ b/docs/api/v2/controller/project/projectsprojectidduplicate.rst @@ -24,6 +24,8 @@ Input + + @@ -33,6 +35,8 @@ Input + +
Name Mandatory Type Description
auto_close boolean Project auto close
drawing_grid_size integer Grid size for the drawing area for drawings
grid_size integer Grid size for the drawing area for nodes
name ['string', 'null'] Project name
path ['string', 'null'] Project directory
project_id ['string', 'null'] Project UUID
show_interface_labels boolean Show interface labels on the drawing area
show_layers boolean Show layers on the drawing area
snap_to_grid boolean Snap to grid on the drawing area
supplier ['object', 'null'] Supplier of the project
variables ['array', 'null'] Variables required to run the project
zoom integer Zoom of the drawing area
@@ -45,7 +49,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -56,6 +62,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/controller/project/projectsprojectidimport.rst b/docs/api/v2/controller/project/projectsprojectidimport.rst index 48e32969..1b4bf1f9 100644 --- a/docs/api/v2/controller/project/projectsprojectidimport.rst +++ b/docs/api/v2/controller/project/projectsprojectidimport.rst @@ -25,7 +25,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -36,6 +38,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/controller/project/projectsprojectidopen.rst b/docs/api/v2/controller/project/projectsprojectidopen.rst index 0cbb09d1..2ce4c430 100644 --- a/docs/api/v2/controller/project/projectsprojectidopen.rst +++ b/docs/api/v2/controller/project/projectsprojectidopen.rst @@ -25,7 +25,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -36,6 +38,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/compute/project/projectsprojectidexport.rst b/docs/api/v2/controller/project/projectsprojectidstats.rst similarity index 74% rename from docs/api/v2/compute/project/projectsprojectidexport.rst rename to docs/api/v2/controller/project/projectsprojectidstats.rst index 56c3d007..783af39b 100644 --- a/docs/api/v2/compute/project/projectsprojectidexport.rst +++ b/docs/api/v2/controller/project/projectsprojectidstats.rst @@ -1,11 +1,11 @@ -/v2/compute/projects/{project_id}/export +/v2/projects/{project_id}/stats ------------------------------------------------------------------------------------------------------------------------------------------ .. contents:: -GET /v2/compute/projects/**{project_id}**/export +GET /v2/projects/**{project_id}**/stats ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Export a project as a portable archive +Get a project statistics Parameters ********** @@ -13,6 +13,6 @@ Parameters Response status codes ********************** -- **200**: File returned +- **200**: Project statistics returned - **404**: The project doesn't exist diff --git a/docs/api/v2/controller/server/debug.rst b/docs/api/v2/controller/server/debug.rst index 9cc6bb13..80d20fc1 100644 --- a/docs/api/v2/controller/server/debug.rst +++ b/docs/api/v2/controller/server/debug.rst @@ -5,9 +5,9 @@ POST /v2/debug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Dump debug informations to disk (debug directory in config directory). Work only for local server +Dump debug information to disk (debug directory in config directory). Work only for local server Response status codes ********************** -- **201**: Writed +- **201**: Written diff --git a/docs/api/v2/controller/server/settings.rst b/docs/api/v2/controller/server/ioulicense.rst similarity index 56% rename from docs/api/v2/controller/server/settings.rst rename to docs/api/v2/controller/server/ioulicense.rst index ff3cac61..d1981d80 100644 --- a/docs/api/v2/controller/server/settings.rst +++ b/docs/api/v2/controller/server/ioulicense.rst @@ -1,34 +1,22 @@ -/v2/settings +/v2/iou_license ------------------------------------------------------------------------------------------------------------------------------------------ .. contents:: -GET /v2/settings +GET /v2/iou_license ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Retrieve gui settings from the server. Temporary will we removed in later release +Get the IOU license settings Response status codes ********************** -- **200**: OK - -Sample session -*************** +- **200**: IOU license settings returned -.. literalinclude:: ../../../examples/controller_get_settings.txt - - -POST /v2/settings +PUT /v2/iou_license ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Write gui settings on the server. Temporary will we removed in later releas +Update the IOU license settings Response status codes ********************** -- **201**: Writed - -Sample session -*************** - - -.. literalinclude:: ../../../examples/controller_post_settings.txt +- **201**: IOU license settings updated diff --git a/docs/api/v2/controller/snapshot/projectsprojectidsnapshotssnapshotidrestore.rst b/docs/api/v2/controller/snapshot/projectsprojectidsnapshotssnapshotidrestore.rst index 49f02a49..82386f82 100644 --- a/docs/api/v2/controller/snapshot/projectsprojectidsnapshotssnapshotidrestore.rst +++ b/docs/api/v2/controller/snapshot/projectsprojectidsnapshotssnapshotidrestore.rst @@ -26,7 +26,9 @@ Output auto_close boolean Project auto close when client cut off the notifications feed auto_open boolean Project open when GNS3 start auto_start boolean Project start when opened + drawing_grid_size integer Grid size for the drawing area for drawings filename ['string', 'null'] Project filename + grid_size integer Grid size for the drawing area for nodes name ['string', 'null'] Project name path ['string', 'null'] Project directory project_id ✔ string Project UUID @@ -37,6 +39,8 @@ Output show_layers boolean Show layers on the drawing area snap_to_grid boolean Snap to grid on the drawing area status enum Possible values: opened, closed + supplier ['object', 'null'] Supplier of the project + variables ['array', 'null'] Variables required to run the project zoom integer Zoom of the drawing area diff --git a/docs/api/v2/controller/symbol/defaultsymbols.rst b/docs/api/v2/controller/symbol/defaultsymbols.rst new file mode 100644 index 00000000..ff0b2bea --- /dev/null +++ b/docs/api/v2/controller/symbol/defaultsymbols.rst @@ -0,0 +1,13 @@ +/v2/default_symbols +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/default_symbols +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +List of default symbols + +Response status codes +********************** +- **200**: Default symbols list returned + diff --git a/docs/api/v2/controller/symbol/symbolssymbolidraw.rst b/docs/api/v2/controller/symbol/symbolssymbolidraw.rst index 23a5d5ea..113ba75f 100644 --- a/docs/api/v2/controller/symbol/symbolssymbolidraw.rst +++ b/docs/api/v2/controller/symbol/symbolssymbolidraw.rst @@ -18,5 +18,5 @@ Write the symbol file Response status codes ********************** -- **200**: Symbol returned +- **200**: Symbol written diff --git a/docs/api/v2/controller/template.rst b/docs/api/v2/controller/template.rst new file mode 100644 index 00000000..0c4b1ec7 --- /dev/null +++ b/docs/api/v2/controller/template.rst @@ -0,0 +1,8 @@ +Template +----------------------------- + +.. toctree:: + :glob: + :maxdepth: 2 + + template/* diff --git a/docs/api/v2/controller/appliance/projectsprojectidappliancesapplianceid.rst b/docs/api/v2/controller/template/projectsprojectidtemplatestemplateid.rst similarity index 81% rename from docs/api/v2/controller/appliance/projectsprojectidappliancesapplianceid.rst rename to docs/api/v2/controller/template/projectsprojectidtemplatestemplateid.rst index db7dad5a..7a324f12 100644 --- a/docs/api/v2/controller/appliance/projectsprojectidappliancesapplianceid.rst +++ b/docs/api/v2/controller/template/projectsprojectidtemplatestemplateid.rst @@ -1,16 +1,16 @@ -/v2/projects/{project_id}/appliances/{appliance_id} +/v2/projects/{project_id}/templates/{template_id} ------------------------------------------------------------------------------------------------------------------------------------------ .. contents:: -POST /v2/projects/**{project_id}**/appliances/**{appliance_id}** +POST /v2/projects/**{project_id}**/templates/**{template_id}** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Create a node from an appliance +Create a node from a template Parameters ********** - **project_id**: Project UUID -- **appliance_id**: Appliance template UUID +- **template_id**: Template UUID Response status codes ********************** @@ -23,7 +23,7 @@ Input - +
Name Mandatory Type Description
compute_id ['null', 'string'] If the appliance don't have a default compute use this compute
compute_id ['null', 'string'] If the template don't have a default compute use this compute
x integer X position
y integer Y position
@@ -37,15 +37,18 @@ Output command_line ['null', 'string'] Command line use to start the node compute_id ✔ string Compute identifier console ['integer', 'null'] Console TCP port + console_auto_start boolean Automatically start the console when the node has started console_host string Console host. Warning if the host is 0.0.0.0 or :: (listen on all interfaces) you need to use the same address you use to connect to the controller. - console_type enum Possible values: vnc, telnet, http, https, spice, null + console_type enum Possible values: vnc, telnet, http, https, spice, spice+agent, none, null + custom_adapters array first_port_name ['string', 'null'] Name of the first port height integer Height of the node (Read only) label object + locked boolean Whether the element locked or not name ✔ string Node name node_directory ['null', 'string'] Working directory of the node. Read only node_id string Node UUID - node_type ✔ enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, virtualbox, vmware, iou, qemu + node_type ✔ enum Possible values: cloud, nat, ethernet_hub, ethernet_switch, frame_relay_switch, atm_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu port_name_format string Formating for port name {0} will be replace by port number port_segment_size integer Size of the port segment ports array List of node ports READ only @@ -53,6 +56,7 @@ Output properties object Properties specific to an emulator status enum Possible values: stopped, started, suspended symbol ['string', 'null'] Symbol of the node + template_id ['null', 'string'] Template UUID from which the node has been created. Read only width integer Width of the node (Read only) x integer X position of the node y integer Y position of the node diff --git a/docs/api/v2/controller/template/templates.rst b/docs/api/v2/controller/template/templates.rst new file mode 100644 index 00000000..2495fa74 --- /dev/null +++ b/docs/api/v2/controller/template/templates.rst @@ -0,0 +1,67 @@ +/v2/templates +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/templates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Create a new template + +Response status codes +********************** +- **201**: Template created +- **400**: Invalid request + +Input +******* +.. raw:: html + + + + + + + + + + + +
Name Mandatory Type Description
builtin boolean Template is builtin
category Template category
compute_id string Compute identifier
default_name_format string Default name format
name string Template name
symbol string Symbol of the template
template_id string Template UUID
template_type enum Possible values: cloud, ethernet_hub, ethernet_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
+ +Output +******* +.. raw:: html + + + + + + + + + + + +
Name Mandatory Type Description
builtin boolean Template is builtin
category Template category
compute_id string Compute identifier
default_name_format string Default name format
name string Template name
symbol string Symbol of the template
template_id string Template UUID
template_type enum Possible values: cloud, ethernet_hub, ethernet_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/controller_post_templates.txt + + +GET /v2/templates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +List of template + +Response status codes +********************** +- **200**: Template list returned + +Sample session +*************** + + +.. literalinclude:: ../../../examples/controller_get_templates.txt + diff --git a/docs/api/v2/controller/template/templatestemplateid.rst b/docs/api/v2/controller/template/templatestemplateid.rst new file mode 100644 index 00000000..37a35d08 --- /dev/null +++ b/docs/api/v2/controller/template/templatestemplateid.rst @@ -0,0 +1,107 @@ +/v2/templates/{template_id} +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +GET /v2/templates/**{template_id}** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Get an template + +Response status codes +********************** +- **200**: Template found +- **400**: Invalid request +- **404**: Template doesn't exist + +Output +******* +.. raw:: html + + + + + + + + + + + +
Name Mandatory Type Description
builtin boolean Template is builtin
category Template category
compute_id string Compute identifier
default_name_format string Default name format
name string Template name
symbol string Symbol of the template
template_id string Template UUID
template_type enum Possible values: cloud, ethernet_hub, ethernet_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/controller_get_templatestemplateid.txt + + +PUT /v2/templates/**{template_id}** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Update an template + +Response status codes +********************** +- **200**: Template updated +- **400**: Invalid request +- **404**: Template doesn't exist + +Input +******* +.. raw:: html + + + + + + + + + + + +
Name Mandatory Type Description
builtin boolean Template is builtin
category Template category
compute_id string Compute identifier
default_name_format string Default name format
name string Template name
symbol string Symbol of the template
template_id string Template UUID
template_type enum Possible values: cloud, ethernet_hub, ethernet_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
+ +Output +******* +.. raw:: html + + + + + + + + + + + +
Name Mandatory Type Description
builtin boolean Template is builtin
category Template category
compute_id string Compute identifier
default_name_format string Default name format
name string Template name
symbol string Symbol of the template
template_id string Template UUID
template_type enum Possible values: cloud, ethernet_hub, ethernet_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/controller_put_templatestemplateid.txt + + +DELETE /v2/templates/**{template_id}** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Delete an template + +Parameters +********** +- **template_id**: template UUID + +Response status codes +********************** +- **204**: Template deleted +- **400**: Invalid request +- **404**: Template doesn't exist + +Sample session +*************** + + +.. literalinclude:: ../../../examples/controller_delete_templatestemplateid.txt + diff --git a/docs/api/v2/controller/template/templatestemplateidduplicate.rst b/docs/api/v2/controller/template/templatestemplateidduplicate.rst new file mode 100644 index 00000000..6f66c345 --- /dev/null +++ b/docs/api/v2/controller/template/templatestemplateidduplicate.rst @@ -0,0 +1,41 @@ +/v2/templates/{template_id}/duplicate +------------------------------------------------------------------------------------------------------------------------------------------ + +.. contents:: + +POST /v2/templates/**{template_id}**/duplicate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Duplicate an template + +Parameters +********** +- **template_id**: Template UUID + +Response status codes +********************** +- **201**: Template duplicated +- **400**: Invalid request +- **404**: Template doesn't exist + +Output +******* +.. raw:: html + + + + + + + + + + + +
Name Mandatory Type Description
builtin boolean Template is builtin
category Template category
compute_id string Compute identifier
default_name_format string Default name format
name string Template name
symbol string Symbol of the template
template_id string Template UUID
template_type enum Possible values: cloud, ethernet_hub, ethernet_switch, docker, dynamips, vpcs, traceng, virtualbox, vmware, iou, qemu
+ +Sample session +*************** + + +.. literalinclude:: ../../../examples/controller_post_templatestemplateidduplicate.txt + diff --git a/docs/controller_notifications.rst b/docs/controller_notifications.rst new file mode 100644 index 00000000..e21caa54 --- /dev/null +++ b/docs/controller_notifications.rst @@ -0,0 +1,98 @@ +Controller notifications +======================== + +Controller notifications can be received from the controller, they can be used to get information +about computes and appliance. + +Notification endpoints +********************** + +Listen to the HTTP stream endpoint or to the WebSocket endpoint. + + * :doc:`api/v2/controller/notification/notifications` + * :doc:`api/v2/controller/notification/notificationsws` + +It is recommended to use the WebSocket endpoint. + +Available notifications +*********************** + +.. contents:: + :local: + +ping +---- +Keep-alive between client and controller. Also used to receive the current CPU and memory usage. + +.. literalinclude:: api/notifications/ping.json + + +compute.created +--------------- + +A compute has been created. + +.. literalinclude:: api/notifications/compute.created.json + +compute.updated +--------------- + +A compute has been updated. + +.. literalinclude:: api/notifications/compute.updated.json + + +compute.deleted +--------------- + +A compute has been deleted. + +.. literalinclude:: api/notifications/compute.deleted.json + + +template.created +----------------- + +A template has been created. + +.. literalinclude:: api/notifications/template.created.json + + +template.updated +----------------- + +A template has been updated. + +.. literalinclude:: api/notifications/template.updated.json + + +template.deleted +----------------- + +A template has been deleted. + +.. literalinclude:: api/notifications/template.deleted.json + + +log.error +--------- + +Sends an error + +.. literalinclude:: api/notifications/log.error.json + + +log.warning +------------ + +Sends a warning + +.. literalinclude:: api/notifications/log.warning.json + + +log.info +--------- + +Sends an information + +.. literalinclude:: api/notifications/log.info.json diff --git a/docs/curl.rst b/docs/curl.rst index a4acd4d6..20a4c85a 100644 --- a/docs/curl.rst +++ b/docs/curl.rst @@ -28,7 +28,7 @@ Check the server version with a simple curl command: List computes ############## -List all the compute servers: +List all the computes: .. code-block:: shell-session @@ -45,7 +45,7 @@ List all the compute servers: } ] -There is only one compute server where nodes can be run in this example. +There is only one compute where nodes can be run in this example. This compute as a special id: local, this is the local server which is embedded in the GNS3 controller. Create a project @@ -231,8 +231,17 @@ Add a packet filter Packet filters allow to filter packet on a given link. Here to drop a packet every 5 packets: .. code-block:: shell-session - curl -X PUT "http://localhost:3080/v2/projects/b8c070f7-f34c-4b7b-ba6f-be3d26ed073f/links/007f2177-6790-4e1b-ac28-41fa226b2a06" -d '{"filters": {"frequency_drop": [5]}}' + # curl -X PUT "http://localhost:3080/v2/projects/b8c070f7-f34c-4b7b-ba6f-be3d26ed073f/links/007f2177-6790-4e1b-ac28-41fa226b2a06" -d '{"filters": {"frequency_drop": [5]}}' + +Template creation +################### + +A template contains all the required settings to create a new node. This is useful to create many nodes with the same settings. + +.. code-block:: shell-session + + # curl -X POST "http://localhost:3080/v2/templates" -d '{"name": "Qemu template", "compute_id": "local", "platform": "i386", "hda_disk_image": "IOSvL2-15.2.4.0.55E.qcow2", "ram": 512, "template_type": "qemu"}' Node creation ############## @@ -240,43 +249,90 @@ Node creation There are two ways to add nodes. 1. Manually by passing all the information required to create a new node. -2. Using an appliance template stored on your server. +2. Using a template stored on your server. -Using an appliance template ---------------------------- +Using a template +----------------- -List all the available appliance templates: +List all the available templates: .. code-block:: shell-session - # curl "http://localhost:3080/v2/appliances" + # curl "http://localhost:3080/v2/templates" [ { - "appliance_id": "5fa8a8ca-0f80-4ac4-8104-2b32c7755443", + "adapter_type": "e1000", + "adapters": 1, + "template_id": "70c79a82-5ef6-4911-8284-f6f31eb0ebf2", + "template_type": "qemu", + "bios_image": "", + "boot_priority": "c", + "builtin": false, "category": "guest", - "compute_id": "vm", + "cdrom_image": "", + "compute_id": "local", + "console_auto_start": false, + "console_type": "telnet", + "cpu_throttling": 0, + "cpus": 1, + "custom_adapters": [], "default_name_format": "{name}-{0}", - "name": "MicroCore", - "node_type": "qemu", - "symbol": ":/symbols/qemu_guest.svg" - }, - { - "appliance_id": "9cd59d5a-c70f-4454-8313-6a9e81a8278f", - "category": "guest", - "compute_id": "vm", - "default_name_format": "{name}-{0}", - "name": "Chromium", - "node_type": "docker", - "symbol": ":/symbols/docker_guest.svg" + "first_port_name": "", + "hda_disk_image": "IOSvL2-15.2.4.0.55E.qcow2", + "hda_disk_interface": "ide", + "hdb_disk_image": "", + "hdb_disk_interface": "ide", + "hdc_disk_image": "", + "hdc_disk_interface": "ide", + "hdd_disk_image": "", + "hdd_disk_interface": "ide", + "initrd": "", + "kernel_command_line": "", + "kernel_image": "", + "legacy_networking": false, + "linked_clone": true, + "mac_address": "", + "name": "Qemu template", + "on_close": "power_off", + "options": "", + "platform": "i386", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "process_priority": "normal", + "qemu_path": "", + "ram": 512, + "symbol": ":/symbols/qemu_guest.svg", + "usage": "" } + { + "adapters": 1, + "template_id": "888984a8-c802-427b-97a7-ee097ee63faf", + "template_type": "docker", + "builtin": false, + "category": "guest", + "compute_id": "local", + "console_auto_start": false, + "console_http_path": "/", + "console_http_port": 80, + "console_resolution": "1024x768", + "console_type": "telnet", + "custom_adapters": [], + "default_name_format": "{name}-{0}", + "environment": "", + "extra_hosts": "", + "image": "debian:latest", + "name": "Debian", + "start_command": "", + "symbol": ":/symbols/docker_guest.svg" + }, ] -Use the appliance template and add coordinates to select where the node will be put on the canvas: +Use the template and add coordinates to select where the node will be put on the canvas: .. code-block:: shell-session - # curl -X POST http://localhost:3080/v2/projects/b8c070f7-f34c-4b7b-ba6f-be3d26ed073f/appliances/9cd59d5a-c70f-4454-8313-6a9e81a8278f -d '{"x": 12, "y": 42}' + # curl -X POST http://localhost:3080/v2/projects/b8c070f7-f34c-4b7b-ba6f-be3d26ed073f/templates/888984a8-c802-427b-97a7-ee097ee63faf -d '{"x": 12, "y": 42}' Manual creation of a Qemu node @@ -487,20 +543,36 @@ Manual creation of a Dynamips node "z": 0 } -Notifications -############# +Controller notifications +######################## -Notifications can be seen by connection to the notification feed: +Controller notifications can be seen by connecting to the notification feed: + +.. code-block:: shell-session + + # curl "http://localhost:3080/v2/notifications" + {"action": "ping", "event": {"compute_id": "local", "cpu_usage_percent": 35.7, "memory_usage_percent": 80.7}} + {"action": "compute.updated", "event": {"capabilities": {"node_types": ["cloud", "ethernet_hub", "ethernet_switch", "nat", "vpcs", "virtualbox", "dynamips", "frame_relay_switch", "atm_switch", "qemu", "vmware", "traceng", "docker", "iou"], "platform": "linux", "version": "2.2.0dev5-68ecbff"}, "compute_id": "local", "connected": true, "cpu_usage_percent": 12.0, "host": "127.0.0.1", "last_error": null, "memory_usage_percent": 45.7, "name": "coruscant", "port": 3080, "protocol": "http", "user": "admin"}} + {"action": "template.created", "event": {"template_id": "384f9b02-6451-4b27-8d29-76623b5d9e79", "template_type": "dynamips", "auto_delete_disks": false, "builtin": false, "category": "router", "compute_id": "local", "console_auto_start": false, "console_type": "telnet", "default_name_format": "R{0}", "disk0": 0, "disk1": 0, "exec_area": 64, "idlemax": 500, "idlepc": "", "idlesleep": 30, "image": "c3725-adventerprisek9-mz.124-15.T14.image", "iomem": 5, "mac_addr": "", "mmap": true, "name": "My c3725", "nvram": 256, "platform": "c3725", "private_config": "", "ram": 128, "sparsemem": true, "startup_config": "ios_base_startup-config.txt", "symbol": ":/symbols/router.svg", "system_id": "FTX0945W0MY"}} + +A Websocket notification stream is also available on http://localhost:3080/v2/notifications/ws + +Read :doc:`controller_notifications` for more information. + + +Project notifications +##################### + +Project notifications can be seen by connecting to the notification feed: .. code-block:: shell-session # curl "http://localhost:3080/v2/projects/b8c070f7-f34c-4b7b-ba6f-be3d26ed073f/notifications" - {"action": "ping", "event": {"compute_id": "local", "cpu_usage_percent": 35.7, "memory_usage_percent": 80.7}} {"action": "node.updated", "event": {"command_line": "/usr/local/bin/vpcs -p 5001 -m 1 -i 1 -F -R -s 10001 -c 10000 -t 127.0.0.1", "compute_id": "local", "console": 5001, "console_host": "127.0.0.1", "console_type": "telnet", "name": "VPCS 2", "node_id": "83892a4d-aea0-4350-8b3e-d0af3713da74", "node_type": "vpcs", "project_id": "b8c070f7-f34c-4b7b-ba6f-be3d26ed073f", "properties": {"startup_script": null, "startup_script_path": null}, "status": "started"}} A Websocket notification stream is also available on http://localhost:3080/v2/projects/b8c070f7-f34c-4b7b-ba6f-be3d26ed073f/notifications/ws -Read :doc:`notifications` for more information. +Read :doc:`project_notifications` for more information. Where to find the endpoints? diff --git a/docs/endpoints.rst b/docs/endpoints.rst index a5e110ed..f2e56379 100644 --- a/docs/endpoints.rst +++ b/docs/endpoints.rst @@ -11,7 +11,7 @@ Controller endpoints The controller manages everything, it is the central decision point and has a complete view of your network topologies, what nodes run on -which compute server, the links between them etc. +which compute, the links between them etc. This is the high level API which can be used by users to manually control the GNS3 backend. The controller will call the compute endpoints when needed. diff --git a/docs/file_format.rst b/docs/file_format.rst index 89a2e3ff..5cbfaed9 100644 --- a/docs/file_format.rst +++ b/docs/file_format.rst @@ -23,6 +23,7 @@ A minimal version: The revision is the version of file format: +* 9: GNS3 2.2 * 8: GNS3 2.1 * 7: GNS3 2.0 * 6: GNS3 2.0 < beta 3 diff --git a/docs/general.rst b/docs/general.rst index f5f34d80..b09d8de0 100644 --- a/docs/general.rst +++ b/docs/general.rst @@ -87,7 +87,7 @@ Notifications Notifications can be received from the server by listening to a HTTP stream or via a Websocket. -Read :doc:`notifications` for more information +Read :doc:`controller_notifications` and `project_notifications` for more information Previous versions ================= diff --git a/docs/glossary.rst b/docs/glossary.rst index 2260eb45..7b32bc20 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -1,26 +1,30 @@ Glossary ======== +Project +-------- + +A project contains everything that is needed to save and restore a virtual network in GNS3 (the topology, virtual disks, settings etc.) + Topology -------- -Contains everything to represent a virtual network (nodes, visual elements, links...) +A topology represents a virtual network (nodes, visual elements, links...). A topology is often used to refer to a project. Node ---- A Virtual Machine (Dynamips, IOU, Qemu, VPCS...) or builtin node (cloud, switch, hub...) that run on a compute. +Template +--------- + +A template used to create a new node. A node is created when dragging a template to a topology. + Appliance --------- -A model for a node used to create a node. When you drag an appliance to the topology a node is created. - -Appliance template ------------------- - -A file (.gns3a) used to create a new node. - +A file (.gns3a or .gns3appliance) used to create a new template with predefined settings. Drawing ------- diff --git a/docs/gns3_file.json b/docs/gns3_file.json index a91ac6a3..39661c34 100644 --- a/docs/gns3_file.json +++ b/docs/gns3_file.json @@ -64,10 +64,57 @@ "type": "boolean", "description": "Show the grid on the drawing area" }, + "grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for nodes" + }, + "drawing_grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for drawings" + }, "show_interface_labels": { "type": "boolean", "description": "Show interface labels on the drawing area" }, + "supplier": { + "type": [ + "object", + "null" + ], + "description": "Supplier of the project", + "properties": { + "logo": { + "type": "string", + "description": "Path to the project supplier logo" + }, + "url": { + "type": "string", + "description": "URL to the project supplier site" + } + } + }, + "variables": { + "type": [ + "array", + "null" + ], + "description": "Variables required to run the project", + "items": { + "properties": { + "name": { + "type": "string", + "description": "Variable name" + }, + "value": { + "type": "string", + "description": "Variable value" + } + }, + "required": [ + "name" + ] + } + }, "topology": { "description": "The topology content", "type": "object", @@ -111,7 +158,7 @@ ] }, "connected": { - "description": "Whether the controller is connected to the compute server or not", + "description": "Whether the controller is connected to the compute or not", "type": "boolean" }, "cpu_usage_percent": { @@ -132,6 +179,13 @@ "maximum": 100, "minimum": 0 }, + "last_error": { + "description": "Last error on the compute", + "type": [ + "string", + "null" + ] + }, "capabilities": { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Get what a server support", @@ -162,6 +216,7 @@ "docker", "dynamips", "vpcs", + "traceng", "virtualbox", "vmware", "iou", @@ -222,6 +277,10 @@ "description": "Z property", "type": "integer" }, + "locked": { + "description": "Whether the element locked or not", + "type": "boolean" + }, "rotation": { "description": "Rotation of the element", "type": "integer", @@ -286,11 +345,14 @@ "type": "string" }, "style": { - "description": "SVG style attribute", - "type": "string" + "description": "SVG style attribute. Apply default style if null", + "type": [ + "string", + "null" + ] }, "x": { - "description": "Relative X position of the label. If null center it", + "description": "Relative X position of the label. Center it if null", "type": [ "integer", "null" @@ -387,6 +449,16 @@ "maxLength": 36, "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" }, + "template_id": { + "description": "Template UUID from which the node has been created. Read only", + "type": [ + "null", + "string" + ], + "minLength": 36, + "maxLength": 36, + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, "node_type": { "description": "Type of node", "enum": [ @@ -399,6 +471,7 @@ "docker", "dynamips", "vpcs", + "traceng", "virtualbox", "vmware", "iou", @@ -446,9 +519,15 @@ "http", "https", "spice", + "spice+agent", + "none", null ] }, + "console_auto_start": { + "description": "Automatically start the console when the node has started", + "type": "boolean" + }, "properties": { "description": "Properties specific to an emulator", "type": "object" @@ -468,11 +547,14 @@ "type": "string" }, "style": { - "description": "SVG style attribute", - "type": "string" + "description": "SVG style attribute. Apply default style if null", + "type": [ + "string", + "null" + ] }, "x": { - "description": "Relative X position of the label. If null center it", + "description": "Relative X position of the label. Center it if null", "type": [ "integer", "null" @@ -524,6 +606,10 @@ "description": "Z position of the node", "type": "integer" }, + "locked": { + "description": "Whether the element locked or not", + "type": "boolean" + }, "port_name_format": { "description": "Formating for port name {0} will be replace by port number", "type": "string" @@ -540,6 +626,40 @@ "null" ] }, + "custom_adapters": { + "type": "array", + "default": [], + "items": { + "type": "object", + "description": "Custom properties", + "properties": { + "adapter_number": { + "type": "integer", + "description": "Adapter number" + }, + "port_name": { + "type": "string", + "description": "Custom port name", + "minLength": 1 + }, + "adapter_type": { + "type": "string", + "description": "Custom adapter type", + "minLength": 1 + }, + "mac_address": { + "description": "Custom MAC address", + "type": "string", + "minLength": 1, + "pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$" + } + }, + "additionalProperties": false, + "required": [ + "adapter_number" + ] + } + }, "ports": { "description": "List of node ports READ only", "type": "array", @@ -559,6 +679,14 @@ "type": "integer", "description": "Adapter slot" }, + "adapter_type": { + "description": "Adapter type", + "type": [ + "string", + "null" + ], + "minLength": 1 + }, "port_number": { "type": "integer", "description": "Port slot" @@ -572,8 +700,17 @@ }, "data_link_types": { "type": "object", - "description": "Available PCAP type for capture", + "description": "Available PCAP types for capture", "properties": {} + }, + "mac_address": { + "description": "MAC address (if available)", + "type": [ + "string", + "null" + ], + "minLength": 1, + "pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$" } }, "additionalProperties": false diff --git a/docs/index.rst b/docs/index.rst index dead8e53..057e6a3e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -18,7 +18,8 @@ API general glossary curl - notifications + controller_notifications + project_notifications position endpoints diff --git a/docs/notifications.rst b/docs/project_notifications.rst similarity index 74% rename from docs/notifications.rst rename to docs/project_notifications.rst index 13dc7878..f37dd07e 100644 --- a/docs/notifications.rst +++ b/docs/project_notifications.rst @@ -1,17 +1,17 @@ -Notifications -============= +Project notifications +===================== -Notifications can be received from the controller, they can be used to update your local data. +Project notifications can be received from the controller, they can be used to update projects. Notification endpoints ********************** -Listen to the HTTP stream endpoint or to the Websocket endpoint. +Listen to the HTTP stream endpoint or to the WebSocket endpoint. * :doc:`api/v2/controller/project/projectsprojectidnotifications` * :doc:`api/v2/controller/project/projectsprojectidnotificationsws` -It is recommended to use the Websocket endpoint. +It is recommended to use the WebSocket endpoint. Available notifications *********************** @@ -26,30 +26,6 @@ Keep-alive between client and controller. Also used to receive the current CPU a .. literalinclude:: api/notifications/ping.json -compute.created ----------------- - -A compute has been created. - -.. literalinclude:: api/notifications/compute.created.json - - -compute.updated ----------------- - -A compute has been updated. - -.. literalinclude:: api/notifications/compute.updated.json - - -compute.deleted ---------------- - -A compute has been deleted. - -.. literalinclude:: api/notifications/compute.deleted.json - - node.created ------------ @@ -169,11 +145,3 @@ log.info Sends an information .. literalinclude:: api/notifications/log.info.json - - -settings.updated ------------------ - -GUI settings have been updated. Will be removed in a later release. - -.. literalinclude:: api/notifications/settings.updated.json diff --git a/gns3server/appliances/aaa.gns3a b/gns3server/appliances/aaa.gns3a new file mode 100644 index 00000000..b54b24a9 --- /dev/null +++ b/gns3server/appliances/aaa.gns3a @@ -0,0 +1,19 @@ +{ + "name": "AAA", + "category": "guest", + "description": "This appliance provides RADIUS and TACACS+ services with preconfigured users and groups.", + "vendor_name": "Ubuntu", + "vendor_url": "https://www.ubuntu.com/", + "product_name": "AAA", + "registry_version": 3, + "status": "stable", + "maintainer": "Andras Dosztal", + "maintainer_email": "developers@gns3.net", + "symbol": "linux_guest.svg", + "usage": "RADIUS users:\n- alice\n- bob\n\nTACACS+ users:\n- gns3 (role: admin)\n- readonly\n\nAll users, as well as the RADIUS/TACACS+ clients have the password 'gns3' set.", + "docker": { + "adapters": 1, + "image": "adosztal/aaa:latest", + "console_type": "telnet" + } +} diff --git a/gns3server/appliances/arista-ceos.gns3a b/gns3server/appliances/arista-ceos.gns3a new file mode 100644 index 00000000..84790a41 --- /dev/null +++ b/gns3server/appliances/arista-ceos.gns3a @@ -0,0 +1,19 @@ +{ + "name": "cEOS", + "category": "multilayer_switch", + "description": "Arista cEOS\u2122 introduces the containerized packaging of EOS software and its agents for deployment in cloud infrastructure with the same proven EOS software image that runs on all Arista products. These flexible deployment options empower cloud network operators that are customizing their operating environments to provide a uniform workflow for development, testing and deployment of differentiated services.", + "vendor_name": "Arista", + "vendor_url": "http://www.arista.com/", + "product_name": "cEOS", + "registry_version": 3, + "status": "experimental", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "usage": "Download:\nCreate a (free) Arista account and login.\nThen navigate to Support / Software Download and download the cEOS-lab image.\n\nInstallation:\nCopy the image to your GNS3VM (or other Linux) server, then run the following commands:\n\ncEOS-4.21.0F and newer, replace by the cEOS version:\ndocker import cEOS-lab.tar.xz ceosimage:\necho \"rm /etc/systemd/system/getty.target.wants/getty@tty1.service\" | \\\ndocker run --name=ceos-container -e CEOS=1 -e container=docker -e EOS_PLATFORM=ceoslab -e SKIP_ZEROTOUCH_BARRIER_IN_SYSDBINIT=1 -e ETBA=1 -e INTFTYPE=eth -i ceosimage: sh\ndocker commit --change='CMD [\"/sbin/init\"]' --change='VOLUME /mnt/flash' ceos-container ceosimage:GNS3\ndocker rm ceos-container\n\ncEOS-4.20.5F:\ndocker import cEOS-lab.tar.xz ceosimage:4.20.5F\necho \"rm /etc/systemd/system/getty.target.wants/getty@tty1.service\" | \\\ndocker run --name=ceos-container -e CEOS=1 -e container=docker -e EOS_PLATFORM=ceossim -e SKIP_ZEROTOUCH_BARRIER_IN_SYSDBINIT=1 -e ETBA=1 -e INTFTYPE=eth -i ceosimage:4.20.5F sh\ndocker commit --change='CMD [\"/sbin/init\"]' --change='VOLUME /mnt/flash' ceos-container ceosimage:GNS3\ndocker rm ceos-container\n\nUsage:\nStart an auxiliary console on the cEOS and issue the \"Cli\" command.\nOnly cEOS-4.20.5F: Login on the console with username \"admin\".", + "symbol": ":/symbols/multilayer_switch.svg", + "docker": { + "adapters": 8, + "image": "ceosimage:GNS3", + "console_type": "telnet" + } +} diff --git a/gns3server/appliances/arista-veos.gns3a b/gns3server/appliances/arista-veos.gns3a index 58376afb..57685e19 100644 --- a/gns3server/appliances/arista-veos.gns3a +++ b/gns3server/appliances/arista-veos.gns3a @@ -24,6 +24,20 @@ "kvm": "require" }, "images": [ + { + "filename": "vEOS-lab-4.21.1.1F.vmdk", + "version": "4.21.1.1F", + "md5sum": "02bfb7e53781fd44ff02357f201586d9", + "filesize": 358809600, + "download_url": "https://www.arista.com/en/support/software-download" + }, + { + "filename": "vEOS-lab-4.20.10M-combined.vmdk", + "version": "4.20.10M-combined", + "md5sum": "d1f2d650f93dbf24e04fdd2c9d62bd62", + "filesize": 334626816, + "download_url": "https://www.arista.com/en/support/software-download" + }, { "filename": "vEOS-lab-4.20.1F.vmdk", "version": "4.20.1F", @@ -31,6 +45,34 @@ "filesize": 662044672, "download_url": "https://www.arista.com/en/support/software-download" }, + { + "filename": "vEOS-lab-4.19.10M-combined.vmdk", + "version": "4.19.10M-combined", + "md5sum": "103daa45c33be4584cbe6adc60de46a3", + "filesize": 324141056, + "download_url": "https://www.arista.com/en/support/software-download" + }, + { + "filename": "vEOS-lab-4.19.10M.vmdk", + "version": "4.19.10M", + "md5sum": "665ed14389411ae5f16ba0a2ff84240a", + "filesize": 637337600, + "download_url": "https://www.arista.com/en/support/software-download" + }, + { + "filename": "vEOS-lab-4.18.10M-combined.vmdk", + "version": "4.18.10M-combined", + "md5sum": "e33e0ef5b8cecc84c5bb57569b36b9c6", + "filesize": 317652992, + "download_url": "https://www.arista.com/en/support/software-download" + }, + { + "filename": "vEOS-lab-4.18.10M.vmdk", + "version": "4.18.10M", + "md5sum": "1d87e9ace37fe3706dbf3e49c8d4d231", + "filesize": 624427008, + "download_url": "https://www.arista.com/en/support/software-download" + }, { "filename": "vEOS-lab-4.18.5M.vmdk", "version": "4.18.5M", @@ -45,6 +87,13 @@ "filesize": 620625920, "download_url": "https://www.arista.com/en/support/software-download" }, + { + "filename": "vEOS-lab-4.17.8M.vmdk", + "version": "4.17.8M", + "md5sum": "afc79a06f930ea2cc0ae3e03cbfd3f23", + "filesize": 608829440, + "download_url": "https://www.arista.com/en/support/software-download" + }, { "filename": "vEOS-lab-4.17.2F.vmdk", "version": "4.17.2F", @@ -52,6 +101,13 @@ "filesize": 609615872, "download_url": "https://www.arista.com/en/support/software-download" }, + { + "filename": "vEOS-lab-4.16.13M.vmdk", + "version": "4.16.13M", + "md5sum": "4d0facf90140fc3aab031f0f8f88a32f", + "filesize": 521404416, + "download_url": "https://www.arista.com/en/support/software-download" + }, { "filename": "vEOS-lab-4.16.6M.vmdk", "version": "4.16.6M", @@ -59,6 +115,13 @@ "filesize": 519962624, "download_url": "https://www.arista.com/en/support/software-download" }, + { + "filename": "vEOS-lab-4.15.10M.vmdk", + "version": "4.15.10M", + "md5sum": "98e08281a9c48ddf6f3c5d62a124a20f", + "filesize": 517079040, + "download_url": "https://www.arista.com/en/support/software-download" + }, { "filename": "vEOS-lab-4.15.5M.vmdk", "version": "4.15.5M", @@ -96,6 +159,19 @@ } ], "versions": [ + { + "name": "4.21.1F", + "images": { + "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", + "hdb_disk_image": "vEOS-lab-4.21.1.1F.vmdk" + } + }, + { + "name": "4.20.10M-combined", + "images": { + "hda_disk_image": "vEOS-lab-4.20.10M-combined.vmdk" + } + }, { "name": "4.20.1F", "images": { @@ -103,6 +179,32 @@ "hdb_disk_image": "vEOS-lab-4.20.1F.vmdk" } }, + { + "name": "4.19.10M-combined", + "images": { + "hda_disk_image": "vEOS-lab-4.19.10M-combined.vmdk" + } + }, + { + "name": "4.19.10M", + "images": { + "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", + "hdb_disk_image": "vEOS-lab-4.19.10M.vmdk" + } + }, + { + "name": "4.18.10M-combined", + "images": { + "hda_disk_image": "vEOS-lab-4.18.10M-combined.vmdk" + } + }, + { + "name": "4.18.10M", + "images": { + "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", + "hdb_disk_image": "vEOS-lab-4.18.10M.vmdk" + } + }, { "name": "4.18.5M", "images": { @@ -117,6 +219,13 @@ "hdb_disk_image": "vEOS-lab-4.18.1F.vmdk" } }, + { + "name": "4.17.8M", + "images": { + "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", + "hdb_disk_image": "vEOS-lab-4.17.8M.vmdk" + } + }, { "name": "4.17.2F", "images": { @@ -124,6 +233,13 @@ "hdb_disk_image": "vEOS-lab-4.17.2F.vmdk" } }, + { + "name": "4.16.13M", + "images": { + "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", + "hdb_disk_image": "vEOS-lab-4.16.13M.vmdk" + } + }, { "name": "4.16.6M", "images": { @@ -131,6 +247,13 @@ "hdb_disk_image": "vEOS-lab-4.16.6M.vmdk" } }, + { + "name": "4.15.10M", + "images": { + "hda_disk_image": "Aboot-veos-serial-8.0.0.iso", + "hdb_disk_image": "vEOS-lab-4.15.10M.vmdk" + } + }, { "name": "4.15.5M", "images": { diff --git a/gns3server/appliances/aruba-arubaoscx.gns3a b/gns3server/appliances/aruba-arubaoscx.gns3a new file mode 100644 index 00000000..7556b67c --- /dev/null +++ b/gns3server/appliances/aruba-arubaoscx.gns3a @@ -0,0 +1,53 @@ +{ + "name": "ArubaOS-CX Simulation Software", + "category": "multilayer_switch", + "status": "stable", + "product_name": "ArubaOS-CX Simulation Software", + "description": "The ArubaOS-CX Simulation Software OVA is a virtual platform to enable simulation of the ArubaOS-CX Network Operating System. Simulated networks can be created using many of the protocols in the ArubaOS-CX Operating system like OSPF and BGP. Key features like the Aruba Network Analytics Engine and the REST API can be simulated, providing a lightweight development platform to building the modern network. This software can be easily implemented in the GNS3 simulation software to enable drag and drop network design for building complex simulated topologies.", + "maintainer_email": "alloytm@gmail.com", + "vendor_url": "arubanetworks.com", + "vendor_name": "HPE Aruba", + "availability": "service-contract", + "maintainer": "Tak Mem Loy", + "registry_version": 4, + "usage": "Default username admin with blank password.", + "symbol": ":/symbols/route_switch_processor.svg", + "first_port_name": "mgmt", + "port_name_format": "1/1/{0}", + + "qemu": { + "arch": "x86_64", + "ram": 4096, + "adapters": 8, + "hdb_disk_interface": "ide", + "hdc_disk_interface": "ide", + "hda_disk_interface": "ide", + "cpus": 2, + "kvm": "require", + "adapter_type": "virtio-net-pci", + "console_type": "vnc", + "options": "-nographic", + "process_priority": "normal" + }, + + "images": [ + { + "filename": "arubaoscx-disk-image-genericx86-p4-20180712161119.vmdk", + "version": "10.01.0001", + "md5sum": "9146ae0ac650d8206c9600e03753f022", + "filesize": 287734784, + "download_url": "http://support.arubanetworks.com/" + } + + ], + + "versions": [ + { + "name": "10.01.0001", + "images": { + "hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20180712161119.vmdk" + } + } + ] + +} diff --git a/gns3server/appliances/aruba-vmc.gns3a b/gns3server/appliances/aruba-vmc.gns3a new file mode 100644 index 00000000..9a81cac7 --- /dev/null +++ b/gns3server/appliances/aruba-vmc.gns3a @@ -0,0 +1,56 @@ +{ + "versions": [ + { + "name": "8.2.1.1", + "images": { + "hda_disk_image": "ArubaOS_VMC_8.2.1.1_65265-disk1.qcow2", + "hdb_disk_image": "ArubaOS_VMC_8.2.1.1_65265-disk2.qcow2" + } + } + ], + "status": "stable", + "name": "Aruba VMC", + "product_name": "Aruba VMC", + "maintainer_email": "gary.ossewaarde@gmail.com", + "vendor_url": "arubanetworks.com", + "vendor_name": "HPE Aruba", + "images": [ + { + "filename": "ArubaOS_VMC_8.2.1.1_65265-disk1.qcow2", + "version": "8.2.1.1", + "md5sum": "f3bc233f0714e4b1cc127e337d077574", + "filesize": 197066752, + "download_url": "http://support.arubanetworks.com/" + }, + { + "filename": "ArubaOS_VMC_8.2.1.1_65265-disk2.qcow2", + "version": "8.2.1.1", + "md5sum": "18ede2afc7595fdac4508a8a3972e302", + "filesize": 19202048, + "download_url": "http://support.arubanetworks.com/" + } + + ], + "port_name_format": "GE0/0/{0}", + "qemu": { + "arch": "x86_64", + "ram": 6144, + "adapters": 4, + "hdb_disk_interface": "ide", + "hdc_disk_interface": "ide", + "hda_disk_interface": "ide", + "cpus": 3, + "kvm": "require", + "kernel_command_line": "-smp cores=3,threads=1,sockets=1 -cpu host -nographic", + "adapter_type": "e1000", + "console_type": "vnc", + "options": "-smp cores=3,threads=1,sockets=1 -cpu host -nographic", + "process_priority": "normal" + }, + "availability": "service-contract", + "category": "guest", + "maintainer": "Gary Ossewaarde", + "description": "Aruba Virtual Mobility Controller", + "first_port_name": "mgmt", + "registry_version": 4 +} diff --git a/gns3server/appliances/asterisk.gns3a b/gns3server/appliances/asterisk.gns3a index 4f6d0c9e..272f302c 100644 --- a/gns3server/appliances/asterisk.gns3a +++ b/gns3server/appliances/asterisk.gns3a @@ -1,11 +1,11 @@ { - "name": "AsteriskNOW", + "name": "AsteriskNOW / FreePBX", "category": "guest", "description": "AsteriskNOW makes it easy to create custom telephony solutions by automatically installing the 'plumbing'. It's a complete Linux distribution with Asterisk, the DAHDI driver framework, and, the FreePBX administrative GUI. Much of the complexity of Asterisk and Linux is handled by the installer, the yum package management utility and the administrative GUI. With AsteriskNOW, application developers and integrators can concentrate on building solutions, not maintaining the plumbing.", "vendor_name": "Digium", "vendor_url": "http://www.asterisk.org/", "documentation_url": "https://wiki.asterisk.org/wiki/display/AST/Installing+AsteriskNOW", - "product_name": "AsteriskNOW", + "product_name": "AsteriskNOW / FreePBX", "product_url": "http://www.asterisk.org/downloads/asterisknow", "registry_version": 3, "status": "stable", @@ -24,6 +24,14 @@ "kvm": "allow" }, "images": [ + { + "filename": "SNG7-FPBX-64bit-1805-2.iso", + "version": "14", + "md5sum": "64f0c38c17ce680f7106f94183bc5745", + "filesize": 1755316224, + "download_url": "https://www.freepbx.org/downloads/", + "direct_download_url": "https://downloads.freepbxdistro.org/ISO/SNG7-FPBX-64bit-1805-2.iso" + }, { "filename": "AsteriskNow-1013-current-64.iso", "version": "10.13", @@ -58,6 +66,13 @@ } ], "versions": [ + { + "name": "14", + "images": { + "hda_disk_image": "empty30G.qcow2", + "cdrom_image": "SNG7-FPBX-64bit-1805-2.iso" + } + }, { "name": "10.13", "images": { diff --git a/gns3server/appliances/bsdrp.gns3a b/gns3server/appliances/bsdrp.gns3a index d7319ea8..ac100721 100644 --- a/gns3server/appliances/bsdrp.gns3a +++ b/gns3server/appliances/bsdrp.gns3a @@ -19,6 +19,33 @@ "kvm": "allow" }, "images": [ + { + "filename": "BSDRP-1.92-full-amd64-serial.img", + "version": "1.92", + "md5sum": "1a123f3ba7ce73aa5823a65a7c571be1", + "filesize": 1000000000, + "download_url": "https://bsdrp.net/downloads", + "direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.92/amd64/BSDRP-1.92-full-amd64-serial.img.xz/download", + "compression": "xz" + }, + { + "filename": "BSDRP-1.91-full-amd64-serial.img", + "version": "1.91", + "md5sum": "cea67b29ce94e66b617e7dc90956af45", + "filesize": 1000000000, + "download_url": "https://bsdrp.net/downloads", + "direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.91/amd64/BSDRP-1.91-full-amd64-serial.img.xz/download", + "compression": "xz" + }, + { + "filename": "BSDRP-1.90-full-amd64-serial.img", + "version": "1.90", + "md5sum": "78b7182bed93888d17d18a67d5fec3a7", + "filesize": 1000000000, + "download_url": "https://bsdrp.net/downloads", + "direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.90/amd64/BSDRP-1.90-full-amd64-serial.img.xz/download", + "compression": "xz" + }, { "filename": "BSDRP-1.80-full-amd64-serial.img", "version": "1.80", @@ -39,6 +66,24 @@ } ], "versions": [ + { + "name": "1.92", + "images": { + "hda_disk_image": "BSDRP-1.92-full-amd64-serial.img" + } + }, + { + "name": "1.91", + "images": { + "hda_disk_image": "BSDRP-1.91-full-amd64-serial.img" + } + }, + { + "name": "1.90", + "images": { + "hda_disk_image": "BSDRP-1.90-full-amd64-serial.img" + } + }, { "name": "1.80", "images": { diff --git a/gns3server/appliances/centos-cloud.gns3a b/gns3server/appliances/centos-cloud.gns3a new file mode 100644 index 00000000..c2c60b92 --- /dev/null +++ b/gns3server/appliances/centos-cloud.gns3a @@ -0,0 +1,52 @@ +{ + "name": "CentOS Cloud Guest", + "category": "guest", + "description": "CentOS official image for self-hosted cloud", + "vendor_name": "The CentOS Project", + "vendor_url": "https://www.centos.org/", + "documentation_url": "https://wiki.centos.org/Documentation", + "product_name": "Centos Cloud", + "product_url": "https://wiki.centos.org/Cloud", + "registry_version": 3, + "status": "stable", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "usage": "Username: centos\nPassword: centos", + "port_name_format": "Ethernet{0}", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 1, + "ram": 1024, + "hda_disk_interface": "virtio", + "arch": "x86_64", + "console_type": "telnet", + "boot_priority": "c", + "kvm": "require", + "options": "-nographic" + }, + "images": [ + { + "filename": "CentOS-7-x86_64-GenericCloud-1809.qcow2", + "version": "7-1809", + "md5sum": "da79108d1324b27bd1759362b82fbe40", + "filesize": 914948096, + "download_url": "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1809.qcow2" + }, + { + "filename": "centos-cloud-init-data.iso", + "version": "1.0", + "md5sum": "15ca60c12db6d13b8eeae1a19613fd6e", + "filesize": 378880, + "download_url": "https://github.com/asenci/gns3-centos-cloud-init-data/raw/master/centos-cloud-init-data.iso" + } + ], + "versions": [ + { + "name": "7 (1809)", + "images": { + "hda_disk_image": "CentOS-7-x86_64-GenericCloud-1809.qcow2", + "cdrom_image": "centos-cloud-init-data.iso" + } + } + ] +} diff --git a/gns3server/appliances/cisco-3745.gns3a b/gns3server/appliances/cisco-3745.gns3a index 99956a63..9a683493 100644 --- a/gns3server/appliances/cisco-3745.gns3a +++ b/gns3server/appliances/cisco-3745.gns3a @@ -11,7 +11,6 @@ "maintainer": "GNS3 Team", "maintainer_email": "developers@gns3.net", "dynamips": { - "chassis": "", "platform": "c3745", "ram": 256, "nvram": 256, diff --git a/gns3server/appliances/cisco-7200.gns3a b/gns3server/appliances/cisco-7200.gns3a index 538656bd..d3db50e1 100644 --- a/gns3server/appliances/cisco-7200.gns3a +++ b/gns3server/appliances/cisco-7200.gns3a @@ -22,14 +22,14 @@ "images": [ { "filename": "c7200-adventerprisek9-mz.124-24.T5.image", - "version": "124-25.T5", + "version": "124-24.T5", "md5sum": "6b89d0d804e1f2bb5b8bda66b5692047", "filesize": 102345240 } ], "versions": [ { - "name": "124-25.T5", + "name": "124-24.T5", "idlepc": "0x606df838", "images": { "image": "c7200-adventerprisek9-mz.124-24.T5.image" diff --git a/gns3server/appliances/cisco-asav.gns3a b/gns3server/appliances/cisco-asav.gns3a index edf2c265..9d45fb46 100644 --- a/gns3server/appliances/cisco-asav.gns3a +++ b/gns3server/appliances/cisco-asav.gns3a @@ -26,11 +26,18 @@ }, "images": [ { - "filename": "asav991.qcow2", - "version": "9.9.1", - "md5sum": "179c52e62b417f38fe21ff1792b8cfc7", - "filesize": 200671232, - "download_url": "https://software.cisco.com/download/type.html?mdfid=286119613&flowid=50242" + "filename": "asav992.qcow2", + "version": "9.9.2", + "md5sum": "0cba453dbf70313d8d63a00700618f52", + "filesize": 204865536, + "download_url": "https://software.cisco.com/download/home/286119613/type/280775065/release/9.9.2" + }, + { + "filename": "asav983.qcow2", + "version": "9.8.3", + "md5sum": "f9cf40b2d555a1bea6d36bc83f06ea33", + "filesize": 199491584, + "download_url": "https://software.cisco.com/download/home/286119613/type/280775065/release/9.8.3" }, { "filename": "asav981-5.qcow2", @@ -105,9 +112,15 @@ ], "versions": [ { - "name": "9.9.1", + "name": "9.9.2", "images": { - "hda_disk_image": "asav991.qcow2" + "hda_disk_image": "asav992.qcow2" + } + }, + { + "name": "9.8.3", + "images": { + "hda_disk_image": "asav983.qcow2" } }, { diff --git a/gns3server/appliances/cisco-csr1000v.gns3a b/gns3server/appliances/cisco-csr1000v.gns3a index 505cbcb8..2884904a 100644 --- a/gns3server/appliances/cisco-csr1000v.gns3a +++ b/gns3server/appliances/cisco-csr1000v.gns3a @@ -14,7 +14,7 @@ "usage": "There is no default password and enable password. A default configuration is present.", "port_name_format": "Gi{port1}", "qemu": { - "adapter_type": "virtio-net-pci", + "adapter_type": "vmxnet3", "adapters": 4, "ram": 3072, "arch": "x86_64", @@ -22,6 +22,27 @@ "kvm": "require" }, "images": [ + { + "filename": "csr1000v-universalk9.16.10.01b-serial.qcow2", + "version": "16.10.1b", + "md5sum": "0d3d647f83631c7955ad7899e6cce293", + "filesize": 950468608, + "download_url": "https://software.cisco.com/download/home/284364978/type/282046477/release/Gibraltar-16.10.1b" + }, + { + "filename": "csr1000v-universalk9.16.09.01-serial.qcow2", + "version": "16.9.1", + "md5sum": "d7e1c83b6f513beb4200c7691d119086", + "filesize": 917897216, + "download_url": "https://software.cisco.com/download/home/284364978/type/282046477/release/Fuji-16.9.1" + }, + { + "filename": "csr1000v-universalk9.16.08.01a-serial.qcow2", + "version": "16.8.1a", + "md5sum": "91e2572f20c77606d710223511cd279a", + "filesize": 890044416, + "download_url": "https://software.cisco.com/download/home/284364978/type/282046477" + }, { "filename": "csr1000v-universalk9.16.07.01-serial.qcow2", "version": "16.7.1", @@ -94,6 +115,24 @@ } ], "versions": [ + { + "name": "16.10.1b", + "images": { + "hda_disk_image": "csr1000v-universalk9.16.10.01b-serial.qcow2" + } + }, + { + "name": "16.9.1", + "images": { + "hda_disk_image": "csr1000v-universalk9.16.09.01-serial.qcow2" + } + }, + { + "name": "16.8.1a", + "images": { + "hda_disk_image": "csr1000v-universalk9.16.08.01a-serial.qcow2" + } + }, { "name": "16.7.1", "images": { diff --git a/gns3server/appliances/cisco-dcnm.gns3a b/gns3server/appliances/cisco-dcnm.gns3a index ff828246..7d6484d9 100644 --- a/gns3server/appliances/cisco-dcnm.gns3a +++ b/gns3server/appliances/cisco-dcnm.gns3a @@ -25,12 +25,19 @@ "options": "-smp 2" }, "images": [ + { + "filename": "dcnm-va.11.1.1.iso", + "version": "11.1.1", + "md5sum": "43af970d046d1430d3ec7950dbe4a20a", + "filesize": 4432132096, + "download_url": "https://software.cisco.com/download/home/281722751/type/282088134/release/11.1%25281%2529" + }, { "filename": "dcnm-va.10.1.1.iso", "version": "10.1.1", "md5sum": "4eca14506decaf166251c64e67adb110", "filesize": 2927532032, - "download_url": "https://software.cisco.com/download/release.html?mdfid=281722751&softwareid=282088134&release=10.1(1)&relind=AVAILABLE&rellifecycle=&reltype=latest" + "download_url": "https://software.cisco.com/download/home/281722751/type/282088134/release/10.1%25281%2529" }, { "filename": "empty100G.qcow2", @@ -42,6 +49,13 @@ } ], "versions": [ + { + "name": "11.1.1", + "images": { + "hda_disk_image": "empty100G.qcow2", + "cdrom_image": "dcnm-va.11.1.1.iso" + } + }, { "name": "10.1.1", "images": { diff --git a/gns3server/appliances/cisco-fcnf.gns3a b/gns3server/appliances/cisco-fcnf.gns3a new file mode 100644 index 00000000..e0aa5599 --- /dev/null +++ b/gns3server/appliances/cisco-fcnf.gns3a @@ -0,0 +1,70 @@ +{ + "name": "Cisco Flow Collector for NetFlow", + "category": "firewall", + "description": "Cisco Stealthwatch is the most comprehensive visibility and network traffic security analytics solution that uses enterprise telemetry from the existing network infrastructure. It provides advanced threat detection, accelerated threat response, and simplified network segmentation using multilayer machine learning and entity modeling. With advanced behavioral analytics, you’ll always know who is on your network and what they are doing.\n\nAt the heart of the Stealthwatch System is the highly scalable Stealthwatch Flow Collector. The Flow Collector is available as either a physical or a virtual appliance. The Flow Collector VE performs the same functions as its physical counterpart, but in a virtual environment. The Stealthwatch Flow Collector for NetFlow gathers NetFlow, cFlow, J-Flow, Packeteer 2, NetStream, and IPFIX data. To achieve full network visibility with a traditional probe-based approach, you would need to install a probe for each router or switch on your network. This results in many costly hardware installations. Conversely, Stealthwatch’s flow-based approach provides you with full network visibility at a fraction of the cost. Each Flow Collector can process data for as many as 1,000,000 hosts from up to 2,000 flow exporters, depending on the Flow Collector model and license restrictions. ", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "documentation_url": "https://www.cisco.com/c/en/us/support/security/stealthwatch/tsd-products-support-series-home.html", + "product_name": "Flow Collector for NetFlow", + "product_url": "https://www.cisco.com/c/en/us/products/security/stealthwatch/index.html", + "registry_version": 4, + "status": "experimental", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "usage": "Starting Flow Collector for NetFlow will start an installation of FCNF onto a blank 200GB Drive.\nDefault console username/password: sysadmin/lan1cope.\nDefault web username/password: admin/lan411cope.", + "symbol": ":/symbols/asa.svg", + "first_port_name": "eth0", + "port_name_format": "eth{port1}", + "qemu": { + "cpus": 2, + "adapter_type": "e1000", + "adapters": 1, + "ram": 8192, + "hda_disk_interface": "scsi", + "arch": "x86_64", + "console_type": "vnc", + "boot_priority": "cd", + "kvm": "require", + "options": "" + }, + "images": [ + { + "filename": "FlowCollector-NetFlow-6.10.4-2018.11.14.1757-0.iso", + "version": "6.10.4-2018.11.14.1757-0", + "md5sum": "accd9fb9dd2d312805883749899a2fc0", + "filesize": 2479288320, + "download_url": "https://stealthwatch.flexnetoperations.com/control/lncp/product?child_plneID=786407" + }, + { + "filename": "FlowCollector-NetFlow-6.10.2-2018.03.19.2230-0.iso", + "version": "6.10.2-2018.03.19.2230-0", + "md5sum": "e2ac83fa617ed9e073e845cedae76873", + "filesize": 2430076928, + "download_url": "https://software.cisco.com/download/home/286307342/type/286307754/release/6.10.2" + }, + { + "filename": "empty200G.qcow2", + "version": "1.0", + "md5sum": "d1686d2f25695dee32eab9a6f4652c7c", + "filesize": 200192, + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty200G.qcow2/download" + } + ], + "versions": [ + { + "name": "6.10.4-2018.11.14.1757-0", + "images": { + "hda_disk_image": "empty200G.qcow2", + "cdrom_image": "FlowCollector-NetFlow-6.10.4-2018.11.14.1757-0.iso" + } + }, + { + "name": "6.10.2-2018.03.19.2230-0", + "images": { + "hda_disk_image": "empty200G.qcow2", + "cdrom_image": "FlowCollector-NetFlow-6.10.2-2018.03.19.2230-0.iso" + } + } + ] +} diff --git a/gns3server/appliances/cisco-fsve.gns3a b/gns3server/appliances/cisco-fsve.gns3a new file mode 100644 index 00000000..d84f5150 --- /dev/null +++ b/gns3server/appliances/cisco-fsve.gns3a @@ -0,0 +1,56 @@ +{ + "name": "Cisco Flow Sensor", + "category": "firewall", + "description": "Cisco Stealthwatch is the most comprehensive visibility and network traffic security analytics solution that uses enterprise telemetry from the existing network infrastructure. It provides advanced threat detection, accelerated threat response, and simplified network segmentation using multilayer machine learning and entity modeling. With advanced behavioral analytics, you’ll always know who is on your network and what they are doing.\n\nUsing the same technology as the Stealthwatch Flow Sensor appliance, the Flow Sensor VE is a virtual appliance that provides visibility into virtual environments, generating flow data for areas that are not flow-enabled. ", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "documentation_url": "https://www.cisco.com/c/en/us/support/security/stealthwatch/tsd-products-support-series-home.html", + "product_name": "Flow Sensor VE", + "product_url": "https://www.cisco.com/c/en/us/products/security/stealthwatch/index.html", + "registry_version": 4, + "status": "experimental", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "usage": "Starting Flow Sensor will start an installation of FSVE onto a blank 100GB Drive.\nDefault console username/password: sysadmin/lan1cope.\nDefault web username/password: admin/lan411cope.", + "symbol": ":/symbols/asa.svg", + "first_port_name": "eth0", + "port_name_format": "eth{port1}", + "qemu": { + "cpus": 1, + "adapter_type": "e1000", + "adapters": 2, + "ram": 8192, + "hda_disk_interface": "scsi", + "arch": "x86_64", + "console_type": "vnc", + "boot_priority": "cd", + "kvm": "require", + "options": "" + }, + "images": [ + { + "filename": "FlowSensor-AE-6.10.2-2018.03.19.2224-0.iso", + "version": "6.10.2-2018.03.19.2224-0", + "md5sum": "ef8712e655fcbc92dc1a1551ee2e4a80", + "filesize": 1287245824, + "download_url": "https://software.cisco.com/download/home/286307342/type/286307754/release/6.10.2" + }, + { + "filename": "empty100G.qcow2", + "version": "1.0", + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "filesize": 198656, + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download" + } + ], + "versions": [ + { + "name": "6.10.2-2018.03.19.2224-0", + "images": { + "hda_disk_image": "empty100G.qcow2", + "cdrom_image": "FlowSensor-AE-6.10.2-2018.03.19.2224-0.iso" + } + } + ] +} diff --git a/gns3server/appliances/cisco-iosxrv9k.gns3a b/gns3server/appliances/cisco-iosxrv9k.gns3a index a140b6d1..5516a2c2 100644 --- a/gns3server/appliances/cisco-iosxrv9k.gns3a +++ b/gns3server/appliances/cisco-iosxrv9k.gns3a @@ -11,19 +11,46 @@ "status": "experimental", "maintainer": "GNS3 Team", "maintainer_email": "developers@gns3.net", - "usage": "Default username/password: admin/admin, cisco/cisco and lab/lab. There is no default configuration present.", + "usage": "Default username/password: admin/admin, cisco/cisco and lab/lab. There is no default configuration present. Interfaces may take several minutes to be usable after appliance boot.\n\nThe interfaces are mapped the following way:\n- NIC0: unused\n- NIC1: unused\n- NIC2: Gi0/0/0/0\n- NIC3: Gi0/0/0/1\n- NICn: Gi0/0/0/(n-2)", "first_port_name": "MgmtEth0/0/CPU0/0", - "port_name_format": "GigabitEthernet0/0/0/{0}", + "port_name_format": "NIC{0}", "qemu": { - "adapter_type": "e1000", - "adapters": 4, + "adapter_type": "virtio-net-pci", + "adapters": 7, "ram": 16384, - "arch": "i386", + "arch": "x86_64", "console_type": "telnet", "kvm": "require", - "options": "-smp 4" + "options": "-smp 4 -cpu host" }, "images": [ + { + "filename": "xrv9k-fullk9-x-6.5.2.qcow2", + "version": "6.5.2", + "md5sum": "506d9e23dda7365c99dd82b613859697", + "filesize": 1205010432, + "download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.5.1" + }, + { + "filename": "xrv9k-fullk9-x-6.5.1.qcow2", + "version": "6.5.1", + "md5sum": "730868e7cd46de9aa2e950899c7f9498", + "filesize": 1208811520, + "download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.5.1" + }, + { + "filename": "xrv9k-fullk9-x-6.4.2.qcow2", + "version": "6.4.2", + "md5sum": "6958763192c7bb59a1b8049d377de1b4", + "filesize": 1311703040, + "download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.4.2" + }, + { "filename": "xrv9k-fullk9-x-6.4.1.qcow2", + "version": "6.4.1", + "md5sum": "9c56b684e307706005a503e289cb9317", + "filesize": 1304887296, + "download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.4.1" + }, { "filename": "xrv9k-fullk9-x-6.2.25.qcow2", "version": "6.2.25", @@ -47,6 +74,30 @@ } ], "versions": [ + { + "name": "6.5.2", + "images": { + "hda_disk_image": "xrv9k-fullk9-x-6.5.2.qcow2" + } + }, + { + "name": "6.5.1", + "images": { + "hda_disk_image": "xrv9k-fullk9-x-6.5.1.qcow2" + } + }, + { + "name": "6.4.2", + "images": { + "hda_disk_image": "xrv9k-fullk9-x-6.4.2.qcow2" + } + }, + { + "name": "6.4.1", + "images": { + "hda_disk_image": "xrv9k-fullk9-x-6.4.1.qcow2" + } + }, { "name": "6.2.25", "images": { diff --git a/gns3server/appliances/cisco-ise.gns3a b/gns3server/appliances/cisco-ise.gns3a index 950e532c..b7056f5b 100644 --- a/gns3server/appliances/cisco-ise.gns3a +++ b/gns3server/appliances/cisco-ise.gns3a @@ -23,29 +23,36 @@ "console_type": "vnc", "boot_priority": "cd", "kvm": "require", - "options": "-smp 2" + "options": "-smp 2 -smbios type=1,product=KVM" }, "images": [ + { + "filename": "ise-2.2.0.470.SPA.x86_64.iso", + "version": "2.2.0.470", + "md5sum": "7fe5e730d0a51ef66e69d1463717ff3f", + "filesize": 8044992512, + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.2.0" + }, { "filename": "ise-2.1.0.474.SPA.x86_64.iso", "version": "2.1.0.474", "md5sum": "8dc844696790f2f5f37054899fab3e2a", "filesize": 6161475584, - "download_url": "https://software.cisco.com/download/release.html?mdfid=283801620&flowid=&softwareid=283802505&release=2.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest" + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.1.0" }, { "filename": "ise-2.0.1.130.SPA.x86_64.iso", "version": "2.0.1.130", "md5sum": "25ac842fdbb61f6e75f2f8b26beea28e", "filesize": 5129990144, - "download_url": "https://software.cisco.com/download/release.html?mdfid=283801620&flowid=&softwareid=283802505&release=2.1.0&relind=AVAILABLE&rellifecycle=&reltype=latest" + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.0.1" }, { "filename": "ise-2.0.0.306.SPA.x86_64.iso", "version": "2.0.0.306", "md5sum": "b7a454ee235db29b5c208b19bfd1fbd1", "filesize": 5088827392, - "download_url": "https://software.cisco.com/download/release.html?mdfid=283801620&flowid=&softwareid=283802505&release=2.0.0&relind=AVAILABLE&rellifecycle=&reltype=latest" + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.0" }, { "filename": "empty200G.qcow2", @@ -57,6 +64,13 @@ } ], "versions": [ + { + "name": "2.2.0.470", + "images": { + "hda_disk_image": "empty200G.qcow2", + "cdrom_image": "ise-2.2.0.470.SPA.x86_64.iso" + } + }, { "name": "2.1.0.474", "images": { @@ -78,6 +92,5 @@ "cdrom_image": "ise-2.0.0.306.SPA.x86_64.iso" } } - ] } diff --git a/gns3server/appliances/cisco-nxosv9k.gns3a b/gns3server/appliances/cisco-nxosv9k.gns3a index 653f4920..6c3650ed 100644 --- a/gns3server/appliances/cisco-nxosv9k.gns3a +++ b/gns3server/appliances/cisco-nxosv9k.gns3a @@ -25,6 +25,48 @@ "kvm": "require" }, "images": [ + { + "filename": "nxosv-final.9.2.3.qcow2", + "version": "9.2.3", + "md5sum": "74bd9a5b4970e868685f753e48979194", + "filesize": 1357643776, + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.2%25283%2529" + }, + { + "filename": "nxosv-final.9.2.2.qcow2", + "version": "9.2.2", + "md5sum": "2119702c488552fc4d1b4210a04d4f64", + "filesize": 1344077824, + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.2%25281%2529" + }, + { + "filename": "nxosv-final.9.2.1.qcow2", + "version": "9.2.1", + "md5sum": "1d7fa4654602d7ffbf62544edfe71986", + "filesize": 1330315264, + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.2%25281%2529" + }, + { + "filename": "nxosv-final.7.0.3.I7.6.qcow2", + "version": "7.0.3.I7.6", + "md5sum": "a122ee954b4c11761abd99291b70544e", + "filesize": 1031995392, + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/7.0%25283%2529I7%25286%2529" + }, + { + "filename": "nxosv-final.7.0.3.I7.5.qcow2", + "version": "7.0.3.I7.5", + "md5sum": "68a4008e189c8a35ccb8ee58db9608bb", + "filesize": 1027670016, + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/7.0%25283%2529I7%25285%2529" + }, + { + "filename": "nxosv-final.7.0.3.I7.4.qcow2", + "version": "7.0.3.I7.4", + "md5sum": "1e980c95ca47045ae45ded6e07fabfb8", + "filesize": 985792512, + "download_url": "https://software.cisco.com/download/" + }, { "filename": "nxosv-final.7.0.3.I7.3.qcow2", "version": "7.0.3.I7.3", @@ -78,6 +120,48 @@ } ], "versions": [ + { + "name": "9.2.3", + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.9.2.3.qcow2" + } + }, + { + "name": "9.2.2", + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.9.2.2.qcow2" + } + }, + { + "name": "9.2.1", + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.9.2.1.qcow2" + } + }, + { + "name": "7.0.3.I7.6", + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I7.6.qcow2" + } + }, + { + "name": "7.0.3.I7.5", + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I7.5.qcow2" + } + }, + { + "name": "7.0.3.I7.4", + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nxosv-final.7.0.3.I7.4.qcow2" + } + }, { "name": "7.0.3.I7.3", "images": { diff --git a/gns3server/appliances/cisco-smc.gns3a b/gns3server/appliances/cisco-smc.gns3a new file mode 100644 index 00000000..e17155cd --- /dev/null +++ b/gns3server/appliances/cisco-smc.gns3a @@ -0,0 +1,70 @@ +{ + "name": "Cisco Stealthwatch Management Console", + "category": "firewall", + "description": "Cisco Stealthwatch is the most comprehensive visibility and network traffic security analytics solution that uses enterprise telemetry from the existing network infrastructure. It provides advanced threat detection, accelerated threat response, and simplified network segmentation using multilayer machine learning and entity modeling. With advanced behavioral analytics, you’ll always know who is on your network and what they are doing.\n\nAs the control center for the Stealthwatch System, the SMC manages, coordinates, configures, and organizes all of the different components of the system. The SMC client software allows you to access the SMC’s user-friendly graphical user interface from any local computer with access to a Web browser. Through the client interface, you can easily access real-time security and network information about critical segments throughout your enterprise. ", + "vendor_name": "Cisco", + "vendor_url": "http://www.cisco.com/", + "documentation_url": "https://www.cisco.com/c/en/us/support/security/stealthwatch/tsd-products-support-series-home.html", + "product_name": "Stealthwatch Management Console", + "product_url": "https://www.cisco.com/c/en/us/products/security/stealthwatch/index.html", + "registry_version": 4, + "status": "experimental", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "usage": "Starting Stealthwatch Management Console will start an installation of SMC onto a blank 200GB Drive.\nDefault console username/password: sysadmin/lan1cope.\nDefault web username/password: admin/lan411cope.", + "symbol": "cisco-fmcv.svg", + "first_port_name": "eth0", + "port_name_format": "eth{port1}", + "qemu": { + "cpus": 3, + "adapter_type": "e1000", + "adapters": 1, + "ram": 8192, + "hda_disk_interface": "scsi", + "arch": "x86_64", + "console_type": "vnc", + "boot_priority": "cd", + "kvm": "require", + "options": "" + }, + "images": [ + { + "filename": "SMC-6.10.4-2018.11.14.1757-0.iso", + "version": "6.10.4-2018.11.14.1757-0", + "md5sum": "1de82eddf5303012aa8701144a7d4c7b", + "filesize": 2518747136, + "download_url": "https://stealthwatch.flexnetoperations.com/control/lncp/product?child_plneID=786407" + }, + { + "filename": "SMC-6.10.2-2018.03.19.2228-0.iso", + "version": "6.10.2-2018.03.19.2228-0", + "md5sum": "e4e31ea6eb5c17c12769724f0c70b452", + "filesize": 2311847936, + "download_url": "https://software.cisco.com/download/home/286307342/type/286307754/release/6.10.2" + }, + { + "filename": "empty200G.qcow2", + "version": "1.0", + "md5sum": "d1686d2f25695dee32eab9a6f4652c7c", + "filesize": 200192, + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty200G.qcow2/download" + } + ], + "versions": [ + { + "name": "6.10.4-2018.11.14.1757-0", + "images": { + "hda_disk_image": "empty200G.qcow2", + "cdrom_image": "SMC-6.10.4-2018.11.14.1757-0.iso" + } + }, + { + "name": "6.10.2-2018.03.19.2228-0", + "images": { + "hda_disk_image": "empty200G.qcow2", + "cdrom_image": "SMC-6.10.2-2018.03.19.2228-0.iso" + } + } + ] +} diff --git a/gns3server/appliances/citrix-netscaler-vpx.gns3a b/gns3server/appliances/citrix-netscaler-vpx.gns3a index 8c62df07..0fcd184a 100644 --- a/gns3server/appliances/citrix-netscaler-vpx.gns3a +++ b/gns3server/appliances/citrix-netscaler-vpx.gns3a @@ -26,6 +26,13 @@ "options": "-smp 2 -cpu host" }, "images": [ + { + "filename": "NSVPX-KVM-12.0-56.20_nc_32.qcow2", + "version": "12.0-56.20", + "md5sum": "0ea1c23e3b8eb8451037d46ee472cfa6", + "filesize": 739704832, + "download_url": "https://www.citrix.com/lp/try/netscaler-vpx-express.html" + }, { "filename": "NSVPX-KVM-11.1-47.14_nc.raw", "version": "11.1-47.14 F", @@ -42,6 +49,12 @@ } ], "versions": [ + { + "name": "12.0-56.20", + "images": { + "hda_disk_image": "NSVPX-KVM-12.0-56.20_nc_32.qcow2" + } + }, { "name": "11.1-47.14 F", "images": { diff --git a/gns3server/appliances/clearos.gns3a b/gns3server/appliances/clearos.gns3a index 25cd1876..37c2cc14 100644 --- a/gns3server/appliances/clearos.gns3a +++ b/gns3server/appliances/clearos.gns3a @@ -22,6 +22,13 @@ "kvm": "require" }, "images": [ + { + "filename": "ClearOS-7.5-DVD-x86_64.iso", + "version": "7.5", + "md5sum": "1e23c5f73a6c996420d8e0e70b000bf9", + "filesize": 1146093568, + "download_url": "https://www.clearos.com/clearfoundation/software/clearos-downloads" + }, { "filename": "ClearOS-7.4-DVD-x86_64.iso", "version": "7.4", @@ -53,6 +60,13 @@ } ], "versions": [ + { + "name": "7.5", + "images": { + "hda_disk_image": "empty30G.qcow2", + "cdrom_image": "ClearOS-7.5-DVD-x86_64.iso" + } + }, { "name": "7.4", "images": { diff --git a/gns3server/appliances/coreos.gns3a b/gns3server/appliances/coreos.gns3a index 396ca39f..07d27af5 100644 --- a/gns3server/appliances/coreos.gns3a +++ b/gns3server/appliances/coreos.gns3a @@ -21,6 +21,42 @@ "kvm": "allow" }, "images": [ + { + "filename": "coreos_production_qemu_image.2023.5.0.img", + "version": "2023.5.0", + "md5sum": "f8b12e524aa81220222d06473b3f36dc", + "filesize": 587661312, + "download_url": "http://stable.release.core-os.net/amd64-usr/2023.5.0/", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/2023.5.0/coreos_production_qemu_image.img.bz2", + "compression": "bzip2" + }, + { + "filename": "coreos_production_qemu_image.1911.5.0.img", + "version": "1911.5.0", + "md5sum": "3b5b33697cfc545d8eb9fb461c612e76", + "filesize": 940507136, + "download_url": "http://stable.release.core-os.net/amd64-usr/1911.5.0/", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1911.5.0/coreos_production_qemu_image.img.bz2", + "compression": "bzip2" + }, + { + "filename": "coreos_production_qemu_image.1855.5.0.img", + "version": "1855.5.0", + "md5sum": "6b5b06bc47446277c5c536c09b5a7988", + "filesize": 924319744, + "download_url": "http://stable.release.core-os.net/amd64-usr/1855.5.0/", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1855.5.0/coreos_production_qemu_image.img.bz2", + "compression": "bzip2" + }, + { + "filename": "coreos_production_qemu_image.1688.5.3.img", + "version": "1688.5.3", + "md5sum": "f1015a9573fb6e378d2a5e86b4243acd", + "filesize": 867368960, + "download_url": "http://stable.release.core-os.net/amd64-usr/1688.5.3/", + "direct_download_url": "http://stable.release.core-os.net/amd64-usr/1688.5.3/coreos_production_qemu_image.img.bz2", + "compression": "bzip2" + }, { "filename": "coreos_production_qemu_image.1632.2.1.img", "version": "1632.2.1", @@ -158,10 +194,34 @@ } ], "versions": [ + { + "name": "2023.5.0", + "images": { + "hda_disk_image": "coreos_production_qemu_image.2023.5.0.img" + } + }, + { + "name": "1911.5.0", + "images": { + "hda_disk_image": "coreos_production_qemu_image.1911.5.0.img" + } + }, + { + "name": "1855.5.0", + "images": { + "hda_disk_image": "coreos_production_qemu_image.1855.5.0.img" + } + }, + { + "name": "1688.5.3", + "images": { + "hda_disk_image": "coreos_production_qemu_image.1688.5.3.img" + } + }, { "name": "1632.2.1", "images": { - "hda_disk_image": "coreos_production_qemu_image.1576.4.0.img" + "hda_disk_image": "coreos_production_qemu_image.1632.2.1.img" } }, { diff --git a/gns3server/appliances/cumulus-vx.gns3a b/gns3server/appliances/cumulus-vx.gns3a index 42a3f9f3..cc085d7d 100644 --- a/gns3server/appliances/cumulus-vx.gns3a +++ b/gns3server/appliances/cumulus-vx.gns3a @@ -23,13 +23,69 @@ "kvm": "require" }, "images": [ + { + "filename": "cumulus-linux-3.7.3-vx-amd64-qemu.qcow2", + "version": "3.7.3", + "md5sum": "e6f438cd44ede841ff290c85dedd127e", + "filesize": 1514340352, + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/CumulusLinux-3.7.3/cumulus-linux-3.7.3-vx-amd64-qemu.qcow2" + }, + { + "filename": "cumulus-linux-3.7.2-vx-amd64-qemu.qcow2", + "version": "3.7.2", + "md5sum": "2fcd785da0452e403c44ba5f3ac4e870", + "filesize": 1574502400, + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/CumulusLinux-3.7.2/cumulus-linux-3.7.2-vx-amd64-qemu.qcow2" + }, + { + "filename": "cumulus-linux-3.7.1-vx-amd64-qemu.qcow2", + "version": "3.7.1", + "md5sum": "201055c57e4a20bb5772289ea6216631", + "filesize": 1640300544, + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/CumulusLinux-3.7.1/cumulus-linux-3.7.1-vx-amd64-qemu.qcow2" + }, + { + "filename": "cumulus-linux-3.6.2-vx-amd64.qcow2", + "version": "3.6.2", + "md5sum": "fda2cfc556de7b12daf45369bd60d33b", + "filesize": 1157169152, + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "direct_download_url": "https://s3.amazonaws.com/cumulusfiles/CumulusLinux-3.6.2/cumulus-linux-3.6.2-vx-amd64.qcow2" + }, + { + "filename": "cumulus-linux-3.6.1-vx-amd64.qcow2", + "version": "3.6.1", + "md5sum": "b2145a689ceea668d003a0d2f2faa045", + "filesize": 1068761088, + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "direct_download_url": "https://s3.amazonaws.com/cumulusfiles/CumulusLinux-3.6.1/cumulus-linux-3.6.1-vx-amd64.qcow2" + }, + { + "filename": "cumulus-linux-3.6.0-vx-amd64.qcow2", + "version": "3.6.0", + "md5sum": "b5356b6c922f5620d7e6971d44e9be4d", + "filesize": 1105199104, + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.6.0-vx-amd64.qcow2" + }, + { + "filename": "cumulus-linux-3.5.3-vx-amd64.qcow2", + "version": "3.5.3", + "md5sum": "4ecbd7341b214fa3c3b27ab11d1df2fb", + "filesize": 1084358656, + "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.5.3-vx-amd64.qcow2" + }, { "filename": "cumulus-linux-3.5.2-vx-amd64.qcow2", "version": "3.5.2", "md5sum": "87d1d8b297e5ebd77924669dfb7e4c9f", "filesize": 996605952, "download_url": "https://cumulusnetworks.com/cumulus-vx/download/", - "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.5.0-vx-amd64.qcow2" + "direct_download_url": "http://cumulusfiles.s3.amazonaws.com/cumulus-linux-3.5.3-vx-amd64.qcow2" }, { "filename": "cumulus-linux-3.5.0-vx-amd64.qcow2", @@ -141,6 +197,48 @@ } ], "versions": [ + { + "name": "3.7.3", + "images": { + "hda_disk_image": "cumulus-linux-3.7.3-vx-amd64-qemu.qcow2" + } + }, + { + "name": "3.7.2", + "images": { + "hda_disk_image": "cumulus-linux-3.7.2-vx-amd64-qemu.qcow2" + } + }, + { + "name": "3.7.1", + "images": { + "hda_disk_image": "cumulus-linux-3.7.1-vx-amd64-qemu.qcow2" + } + }, + { + "name": "3.6.2", + "images": { + "hda_disk_image": "cumulus-linux-3.6.2-vx-amd64.qcow2" + } + }, + { + "name": "3.6.1", + "images": { + "hda_disk_image": "cumulus-linux-3.6.1-vx-amd64.qcow2" + } + }, + { + "name": "3.6.0", + "images": { + "hda_disk_image": "cumulus-linux-3.6.0-vx-amd64.qcow2" + } + }, + { + "name": "3.5.3", + "images": { + "hda_disk_image": "cumulus-linux-3.5.3-vx-amd64.qcow2" + } + }, { "name": "3.5.2", "images": { diff --git a/gns3server/appliances/dell-ftos.gns3a b/gns3server/appliances/dell-ftos.gns3a index 136fb48a..af13461a 100644 --- a/gns3server/appliances/dell-ftos.gns3a +++ b/gns3server/appliances/dell-ftos.gns3a @@ -1,16 +1,16 @@ { - "name": "Dell FTOS", + "name": "Dell OS9", "category": "router", - "description": "Dell Networking OS10 combines the best of Linux, open computing and networking to advance open networking disaggregation. Dell Networking OS10 is a transformational software platform that provides networking hardware abstraction through a common set of APIs. Enable consistency across compute and network resources for your system operators (SysOps) groups that require server-like manageability. Easily leverage your existing network configuration. Dell Networking OS10 incorporates traditional networking integration. Enhance the integration and control you allow your development and operations (DevOps) teams, down to identifying an object as an individual, manageable entity within the platform.", + "description": "Dell Networking OS9 (formerly FTOS).\nOS9 powers the Dell Networking product portfolio and has been hardened in some of the largest and most demanding environments in the world to meet stringent reliability, scalability and serviceability requirements. \n\nDownload and uncompress zip files from the Dell support site - corresponding to the FTOS/OS9 image name. Please 'Select FTOS for S-Series OS-EMULATOR'. Import the resulting ISO image.", "vendor_name": "Dell Inc.", "vendor_url": "http://www.dell.com/", - "product_name": "Dell FTOS", + "product_name": "Dell OS9", "product_url": "http://www.dell.com/us/business/p/open-platform-software/pd", "registry_version": 3, "status": "experimental", "maintainer": "GNS3 Team", "maintainer_email": "developers@gns3.net", - "usage": "Abort the BCM process and format the flash after first boot by entering these commands:\nen\nformat flash:\n\nSometimes the flash device is not available after boot.", + "usage": "Make sure the Boot priority of the configuration template is HDD or CD.\n\nAbort the BCM process and format the flash after first boot by entering these commands:\nen\nformat flash:\n\nSometimes the flash device is not available after boot.", "first_port_name": "Management0/0", "port_name_format": "fortyGigE0/{0}", "qemu": { @@ -29,7 +29,7 @@ "version": "9.8.0", "md5sum": "b9b50eda0a73407dc381792ff7975e24", "filesize": 108115968, - "download_url": "https://www.force10networks.com/csportal20/Software/Downloads.aspx", + "download_url": "https://www.force10networks.com/CSPortal20/Software/SSeriesDownloads.aspx", "compression": "zip" }, { diff --git a/gns3server/appliances/dns.gns3a b/gns3server/appliances/dns.gns3a new file mode 100644 index 00000000..0902b0db --- /dev/null +++ b/gns3server/appliances/dns.gns3a @@ -0,0 +1,19 @@ +{ + "name": "DNS", + "category": "guest", + "description": "This appliance provides DNS using dnsmasq with the local domain set to \"lab\".", + "vendor_name": "Ubuntu", + "vendor_url": "https://www.ubuntu.com/", + "product_name": "DNS", + "registry_version": 3, + "status": "stable", + "maintainer": "Andras Dosztal", + "maintainer_email": "developers@gns3.net", + "symbol": "linux_guest.svg", + "usage": "You can add records by adding entries to the /etc/hosts file in the following format:\n%IP_ADDRESS% %HOSTNAME%.lab %HOSTNAME%\n\nExample:\n192.168.123.10 router1.lab router1", + "docker": { + "adapters": 1, + "image": "adosztal/dns:latest", + "console_type": "telnet" + } +} diff --git a/gns3server/appliances/exos.gns3a b/gns3server/appliances/exos.gns3a index 3f09c669..33b95944 100644 --- a/gns3server/appliances/exos.gns3a +++ b/gns3server/appliances/exos.gns3a @@ -1,159 +1,139 @@ { - "name": "EXOS", + "name": "EXOS VM", "category": "multilayer_switch", - "description": "ExtremeXOS was designed from the ground up to meet the needs of large cloud and private data centers, service providers, intelligent, converged enterprise edge networks, and everything in between. It provides the high performance and rich features required by these diverse environments.", + "description": "The ExtremeXOS VM is created and maintained by Extreme Networks for users to emulate a network using EXOS switches.", "vendor_name": "Extreme Networks", - "vendor_url": "http://www.extremenetworks.com/", - "documentation_url": "http://www.extremenetworks.com/support/documentation", - "product_name": "EXOS", - "product_url": "http://www.extremenetworks.com/product/extremexos-network-operating-system", + "vendor_url": "https://www.extremenetworks.com", + "documentation_url": "https://www.extremenetworks.com/support/documentation", + "product_name": "EXOS VM", "registry_version": 3, "status": "stable", - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", - "usage": "You can change the console to telnet after install. Default user: admin (no password set)", - "first_port_name": "Management", + "maintainer": "Extreme Networks", + "maintainer_email": "GitHubscripting@extremenetworks.com", + "usage": "Boot up and login is admin with no password.", + "symbol": "ethernet_switch.svg", + "first_port_name": "Mgmt", "port_name_format": "Port{port1}", "qemu": { - "adapter_type": "e1000", + "adapter_type": "rtl8139", "adapters": 13, - "ram": 256, + "ram": 512, "hda_disk_interface": "ide", "arch": "x86_64", "console_type": "telnet", - "boot_priority": "cd", - "kvm": "require", - "options": "-smp 2 -cpu core2duo" + "boot_priority": "dc", + "kvm": "allow", + "options": "-cpu core2duo" }, + "images": [ + + { + "filename": "EXOS-VM_v30.1.1.4.qcow2", + "version": "30.1.1.4", + "md5sum": "92d3f9b13d750f7bfa804823fa545772", + "filesize": 383385600, + "direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v30.1.1.4.qcow2" + }, + { + "filename": "EXOS-VM_v22.6.1.4.qcow2", + "version": "22.6.1.4", + "md5sum": "82b31b11b26143a82c8259a4825696fc", + "filesize": 180355072, + "direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.6.1.4.qcow2" + }, + { + "filename": "EXOS-VM_v22.5.1.7.qcow2", + "version": "22.5.1.7", + "md5sum": "d2e8ae6783b6ed777ad5cd8cafd83c86", + "filesize": 180289536, + "direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.5.1.7.qcow2" + }, { - "filename": "exosvm-22.4.1.4.iso", + "filename": "EXOS-VM_v22.4.1.4-disk1.qcow2", "version": "22.4.1.4", - "md5sum": "2134a511084519a5f8ad00a6f7cd71a9", - "filesize": 49993728, - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.4.1.4.iso" + "md5sum": "5f1ee41912d74d423ce8ae57ea413602", + "filesize": 229638144, + "direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.4.1.4-disk1.qcow2" }, { - "filename": "exosvm-22.2.1.5.iso", + "filename": "EXOS-VM_v22.3.1.4patch1-4-disk1.qcow2", + "version": "22.3.1.4", + "md5sum": "a4585b6e987ff730f5c044af339fe090", + "filesize": 218431488, + "direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.3.1.4patch1-4-disk1.qcow2" + }, + { + "filename": "EXOS-VM_v22.2.1.5-disk1.qcow2", "version": "22.2.1.5", - "md5sum": "bf51fd5b3c5e9dab10a616055265bcf2", - "filesize": 44578816, - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.2.1.5.iso" + "md5sum": "e3cfe92077addda6ad34185288c90acf", + "filesize": 179568640, + "direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.2.1.5-disk1.qcow2" }, { - "filename": "exosvm-22.1.1.5.iso", + "filename": "EXOS-VM_v22.1.1.5-disk1.qcow2", "version": "22.1.1.5", - "md5sum": "df3897ca2d7c7053582587ed120114fa", - "filesize": 44220416, - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.1.1.5.iso" + "md5sum": "77683060e75d81b776761f6829b15e9b", + "filesize": 179437568, + "direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.1.1.5-disk1.qcow2" }, - { - "filename": "exosvm-21.1.2.14.iso", - "version": "21.1.2.14", - "md5sum": "de0752d56e41d92027ce1fccd604b14b", - "filesize": 41101312, - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/vm-21.1.2.14.iso?raw=true" - }, - { - "filename": "exosvm-21.1.1.4.iso", + { + "filename": "EXOS-VM_v21.1.1.4-disk1.qcow2", "version": "21.1.1.4", - "md5sum": "4d5db0e01a39b08775ed6a3e2c8bf663", - "filesize": 41046016, - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/vm-21.1.1.4.iso?raw=true" - }, - { - "filename": "exospc-16.2.1.6.iso", - "version": "16.2.1.6", - "md5sum": "b4be339afb02c03dcb4349630c1adb4f", - "filesize": 36306944, - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.2.1.6.iso?raw=true" - }, - { - "filename": "exospc-16.1.3.6.iso", - "version": "16.1.3.6", - "md5sum": "4c17b2bf2a4909527f6c866a68ba406e", - "filesize": 35758080, - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.1.3.6.iso?raw=true" - }, - { - "filename": "exospc-16.1.2.14.iso", - "version": "16.1.2.14", - "md5sum": "140cdc11f426156ffcbde150b2f46768", - "filesize": 35743744, - "download_url": "https://github.com/extremenetworks/Virtual_EXOS", - "direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.1.2.14.iso?raw=true" - }, - { - "filename": "empty8G.qcow2", - "version": "1.0", - "md5sum": "f1d2c25b6990f99bd05b433ab603bdb4", - "filesize": 197120, - "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download" + "md5sum": "654606809b6fd3bca400377483eb4a79", + "filesize": 117560832, + "direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v21.1.1.4-disk1.qcow2" } + ], + "versions": [ + { + "name": "30.1.1.4", + "images": { + "hda_disk_image": "EXOS-VM_v30.1.1.4.qcow2" + } + }, + { + "name": "22.6.1.4", + "images": { + "hda_disk_image": "EXOS-VM_v22.6.1.4.qcow2" + } + }, + { + "name": "22.5.1.7", + "images": { + "hda_disk_image": "EXOS-VM_v22.5.1.7.qcow2" + } + }, { "name": "22.4.1.4", "images": { - "hda_disk_image": "empty8G.qcow2", - "cdrom_image": "exosvm-22.4.1.4.iso" + "hda_disk_image": "EXOS-VM_v22.4.1.4-disk1.qcow2" + } + }, + { + "name": "22.3.1.4", + "images": { + "hda_disk_image": "EXOS-VM_v22.3.1.4patch1-4-disk1.qcow2" } }, { "name": "22.2.1.5", "images": { - "hda_disk_image": "empty8G.qcow2", - "cdrom_image": "exosvm-22.2.1.5.iso" + "hda_disk_image": "EXOS-VM_v22.2.1.5-disk1.qcow2" } }, { "name": "22.1.1.5", "images": { - "hda_disk_image": "empty8G.qcow2", - "cdrom_image": "exosvm-22.1.1.5.iso" - } - }, - { - "name": "21.1.2.14", - "images": { - "hda_disk_image": "empty8G.qcow2", - "cdrom_image": "exosvm-21.1.2.14.iso" + "hda_disk_image": "EXOS-VM_v22.1.1.5-disk1.qcow2" } }, { "name": "21.1.1.4", "images": { - "hda_disk_image": "empty8G.qcow2", - "cdrom_image": "exosvm-21.1.1.4.iso" - } - }, - { - "name": "16.2.1.6", - "images": { - "hda_disk_image": "empty8G.qcow2", - "cdrom_image": "exospc-16.2.1.6.iso" - } - }, - { - "name": "16.1.3.6", - "images": { - "hda_disk_image": "empty8G.qcow2", - "cdrom_image": "exospc-16.1.3.6.iso" - } - }, - { - "name": "16.1.2.14", - "images": { - "hda_disk_image": "empty8G.qcow2", - "cdrom_image": "exospc-16.1.2.14.iso" + "hda_disk_image": "EXOS-VM_v21.1.1.4-disk1.qcow2" } } ] diff --git a/gns3server/appliances/extreme-networks-voss.gns3a b/gns3server/appliances/extreme-networks-voss.gns3a new file mode 100644 index 00000000..077883be --- /dev/null +++ b/gns3server/appliances/extreme-networks-voss.gns3a @@ -0,0 +1,64 @@ +{ + "name": "VOSS VM", + "category": "multilayer_switch", + "description": "The VOSS VM is a software emulation of a VSP8K switch.", + "vendor_name": "Extreme Networks", + "vendor_url": "http://www.extremenetworks.com", + "documentation_url": "http://www.extremenetworks.com/support/documentation", + "product_name": "VOSS_VM", + "registry_version": 3, + "status": "experimental", + "maintainer": "Extreme Networks", + "maintainer_email": "voss@extremenetworks.com", + "usage": "Boot up and login is rwa/rwa", + "symbol": ":/symbols/multilayer_switch.svg", + "first_port_name": "Mgmt", + "port_name_format": "1/{port1}", + "qemu": + { + "adapter_type": "e1000", + "adapters": 9, + "ram": 1024, + "hda_disk_interface": "ide", + "arch": "i386", + "console_type": "telnet", + "kvm": "allow", + "options": "-nographic" + }, + + "images": + [ + { + "filename": "VOSSGNS3.7.1.0.0.qcow2", + "version": "voss_7.1.0.0", + "md5sum": "7bb2974efe1a1ab857debd9fa894dbe7", + "filesize": 193724416, + "direct_download_url": "https://stackingtool.extremenetworks.com/github/VOSSGNS3.7.1.0.0.qcow2" + }, + { + "filename": "VOSSGNS3.7.0.0.0.img", + "version": "voss_7.0.0.0", + "md5sum": "65fe97461156aa88c836a90be1287649", + "filesize": 419430400, + "direct_download_url": "https://stackingtool.extremenetworks.com/github/VOSSGNS3.7.0.0.0.img" + } + ], + + "versions": + [ + { + "name": "7.1.0.0", + "images": + { + "hda_disk_image": "VOSSGNS3.7.1.0.0.qcow2" + } + }, + { + "name": "7.0.0.0", + "images": { + "hda_disk_image": "VOSSGNS3.7.0.0.0.img" + } + } + ] + +} diff --git a/gns3server/appliances/f5-bigip.gns3a b/gns3server/appliances/f5-bigip.gns3a index 863e1944..efaf8464 100644 --- a/gns3server/appliances/f5-bigip.gns3a +++ b/gns3server/appliances/f5-bigip.gns3a @@ -27,6 +27,20 @@ "options": "-smp 2 -cpu host" }, "images": [ + { + "filename": "BIGIP-14.0.0.3-0.0.4.qcow2", + "version": "14.0.0 HF3", + "md5sum": "dc80a7e436ff93e2f4092eece18d369b", + "filesize": 4550164480, + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v14.x/14.0.0/english/14.0.0.3_virtual-edition/&sw=BIG-IP&pro=big-ip_v14.x&ver=14.0.0&container=14.0.0.3_Virtual-Edition&file=BIGIP-14.0.0.3-0.0.4.ALL.qcow2.zip" + }, + { + "filename": "BIGIP-13.1.0.5-0.0.5.qcow2", + "version": "13.1.0 HF5", + "md5sum": "567b70fe36af0f5364883e97e2c08807", + "filesize": 4402446336, + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v13.x/13.1.0/english/13.1.0.5_virtual-edition/&sw=BIG-IP&pro=big-ip_v13.x&ver=13.1.0&container=13.1.0.5_Virtual-Edition&file=BIGIP-13.1.0.5-0.0.5.ALL.qcow2.zip" + }, { "filename": "BIGIP-13.1.0.2.0.0.6.qcow2", "version": "13.1.0 HF2", @@ -55,6 +69,13 @@ "filesize": 3833135104, "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v13.x/13.0.0/english/virtual-edition/&sw=BIG-IP&pro=big-ip_v13.x&ver=13.0.0&container=Virtual-Edition&file=BIGIP-13.0.0.0.0.1645.ALL.qcow2.zip" }, + { + "filename": "BIGIP-12.1.3.4-0.0.2.qcow2", + "version": "12.1.3 HF4", + "md5sum": "b2ec82816480c18af1d45ee833744ee8", + "filesize": 3383164928, + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v12.x/12.1.3/english/12.1.3.4_virtual-edition/&sw=BIG-IP&pro=big-ip_v12.x&ver=12.1.3&container=12.1.3.4_Virtual-Edition&file=BIGIP-12.1.3.4-0.0.2.ALL.qcow2.zip" + }, { "filename": "BIGIP-12.1.2.1.0.271.LTM.qcow2", "version": "12.1.2 HF1", @@ -121,6 +142,20 @@ } ], "versions": [ + { + "name": "14.0.0 HF3", + "images": { + "hda_disk_image": "BIGIP-14.0.0.3-0.0.4.qcow2", + "hdb_disk_image": "empty100G.qcow2" + } + }, + { + "name": "13.1.0 HF5", + "images": { + "hda_disk_image": "BIGIP-13.1.0.5-0.0.5.qcow2", + "hdb_disk_image": "empty100G.qcow2" + } + }, { "name": "13.1.0 HF2", "images": { @@ -149,6 +184,13 @@ "hdb_disk_image": "empty100G.qcow2" } }, + { + "name": "12.1.3 HF4", + "images": { + "hda_disk_image": "BIGIP-12.1.3.4-0.0.2.qcow2", + "hdb_disk_image": "empty100G.qcow2" + } + }, { "name": "12.1.2 HF1", "images": { diff --git a/gns3server/appliances/f5-bigiq.gns3a b/gns3server/appliances/f5-bigiq.gns3a index 97050cf7..45c71511 100644 --- a/gns3server/appliances/f5-bigiq.gns3a +++ b/gns3server/appliances/f5-bigiq.gns3a @@ -29,6 +29,20 @@ "options": "-smp 2 -cpu host" }, "images": [ + { + "filename": "BIG-IQ-6.0.1.1.0.0.9.qcow2", + "version": "6.0.1.1", + "md5sum": "3ae32308fe39d5db555f7f1cdcc734dd", + "filesize": 3895787520, + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/6.0.1/english/v6.0.1.1/&sw=BIG-IQ&pro=big-iq_CM&ver=6.0.1&container=v6.0.1.1&file=BIG-IQ-6.0.1.1.0.0.9.qcow2.zip" + }, + { + "filename": "BIG-IQ-5.4.0.2.24.7467.qcow2", + "version": "5.4.0.2", + "md5sum": "e3e6389438ba1e1676f507658f767e95", + "filesize": 3480748032, + "download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.4.0/english/virtual-edition_base-plus-hf2/&sw=BIG-IQ&pro=big-iq_CM&ver=5.4.0&container=Virtual-Edition_Base-Plus-HF2&file=BIG-IQ-5.4.0.2.24.7467.qcow2.zip" + }, { "filename": "BIG-IQ-5.4.0.0.0.7437.qcow2", "version": "5.4.0", @@ -81,6 +95,20 @@ } ], "versions": [ + { + "name": "6.0.1.1", + "images": { + "hda_disk_image": "BIG-IQ-6.0.1.1.0.0.9.qcow2", + "hdb_disk_image": "empty100G.qcow2" + } + }, + { + "name": "5.4.0.2", + "images": { + "hda_disk_image": "BIG-IQ-5.4.0.2.24.7467.qcow2", + "hdb_disk_image": "empty100G.qcow2" + } + }, { "name": "5.4.0", "images": { diff --git a/gns3server/appliances/fortiadc-manager.gns3a b/gns3server/appliances/fortiadc-manager.gns3a new file mode 100644 index 00000000..74090e70 --- /dev/null +++ b/gns3server/appliances/fortiadc-manager.gns3a @@ -0,0 +1,53 @@ +{ + "name": "FortiADC Manager", + "category": "guest", + "description": "FortiADC Manager allows you to use a web- based user interface to configure remote FortiADC devices. It allows you to simplify and speed up the FortiADC deployment and update process by maintaining configuration templates and policy packages that you can modify and apply as needed.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "documentation_url": "https://docs.fortinet.com/fortiadc-manager/", + "product_name": "FortiADC Manager", + "product_url": "https://www.fortinet.com/products/application-delivery-controller/fortiadc.html", + "registry_version": 3, + "status": "stable", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "usage": "Default username is admin, no password is set.", + "port_name_format": "Port{port1}", + "symbol": "fortinet.svg", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 10, + "ram": 2048, + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "arch": "x86_64", + "console_type": "telnet", + "boot_priority": "c", + "kvm": "allow" + }, + "images": [ + { + "filename": "FADCManager-KVM-V500-build0020-FORTINET.out.kvm-boot.qcow2", + "version": "5.2.0", + "md5sum": "a79d04040848b704ce4efe925518fd3f", + "filesize": 70057984, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FADCManager-KVM-v500-data.qcow2", + "version": "5.x", + "md5sum": "b7500835594e62d8acb1c6ec43d597c1", + "filesize": 30998528, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + } + ], + "versions": [ + { + "name": "5.2.0", + "images": { + "hda_disk_image": "FADCManager-KVM-V500-build0020-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FADCManager-KVM-v500-data.qcow2" + } + } + ] +} diff --git a/gns3server/appliances/fortiadc.gns3a b/gns3server/appliances/fortiadc.gns3a index 10f47817..03d8524f 100644 --- a/gns3server/appliances/fortiadc.gns3a +++ b/gns3server/appliances/fortiadc.gns3a @@ -28,12 +28,54 @@ }, "images": [ { - "filename": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2", - "version": "4.x.x", + "filename": "FAD_KVM-FORTINET.out.kvm-data.qcow2", + "version": "ALL", "md5sum": "b7500835594e62d8acb1c6ec43d597c1", "filesize": 30998528, "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" }, + { + "filename": "FAD_KVM-V500-build0442-FORTINET.out.kvm-boot.qcow2", + "version": "5.2.2", + "md5sum": "7d959ed264b064716e8f1378fceed48f", + "filesize": 104857600, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAD_KVM-V500-build0423-FORTINET.out.kvm-boot.qcow2", + "version": "5.2.0", + "md5sum": "993bcd0e8e5496fdacb78dffb3c9a9b3", + "filesize": 104333312, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAD_KVM-V500-build0239-FORTINET.out.kvm-boot.qcow2", + "version": "5.1.1", + "md5sum": "f94323bc6415dd1477f2352bd3323d14", + "filesize": 75235328, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAD_KVM-V500-build0056-FORTINET.out.kvm-boot.qcow2", + "version": "5.0.1", + "md5sum": "8b3b789fb540b2c30066f66bcbe7f307", + "filesize": 75038720, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAD_KVM-V500-build0045-FORTINET.out.kvm-boot.qcow2", + "version": "5.0.0", + "md5sum": "d7381b3fb7a4534370ce8983e441d888", + "filesize": 74383360, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAD_KVM-V400-build0999-FORTINET.out.kvm-boot.qcow2", + "version": "4.8.5", + "md5sum": "d7825b8d0962800c37ffa814a6b2ad45", + "filesize": 73334784, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FAD_KVM-V400-build0989-FORTINET.out.kvm-boot.qcow2", "version": "4.8.4", @@ -155,123 +197,165 @@ } ], "versions": [ + { + "name": "5.2.2", + "images": { + "hda_disk_image": "FAD_KVM-V500-build0442-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + } + }, + { + "name": "5.2.0", + "images": { + "hda_disk_image": "FAD_KVM-V500-build0423-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + } + }, + { + "name": "5.1.1", + "images": { + "hda_disk_image": "FAD_KVM-V500-build0239-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + } + }, + { + "name": "5.0.1", + "images": { + "hda_disk_image": "FAD_KVM-V400-build0989-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + } + }, + { + "name": "5.0.0", + "images": { + "hda_disk_image": "FAD_KVM-V400-build0989-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + } + }, + { + "name": "4.8.5", + "images": { + "hda_disk_image": "FAD_KVM-V400-build0999-FORTINET.out.kvm-boot.qcow2", + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" + } + }, { "name": "4.8.4", "images": { "hda_disk_image": "FAD_KVM-V400-build0989-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.8.3", "images": { "hda_disk_image": "FAD_KVM-V400-build0983-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.8.2", "images": { "hda_disk_image": "FAD_KVM-V400-build0977-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.8.1", "images": { "hda_disk_image": "FAD_KVM-V400-build0970-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.8.0", "images": { "hda_disk_image": "FAD_KVM-V400-build0937-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.7.4", "images": { "hda_disk_image": "FAD_KVM-V400-build0858-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.7.3", "images": { "hda_disk_image": "FAD_KVM-V400-build0849-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.7.2", "images": { "hda_disk_image": "FAD_KVM-V400-build0844-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.7.1", "images": { "hda_disk_image": "FAD_KVM-V400-build0832-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.7.0", "images": { "hda_disk_image": "FAD_KVM-V400-build0828-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.6.2", "images": { "hda_disk_image": "FAD_KVM-V400-build0679-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.6.1", "images": { "hda_disk_image": "FAD_KVM-V400-build0677-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.6.0", "images": { "hda_disk_image": "FAD_KVM-V400-build0660-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.5.3", "images": { "hda_disk_image": "FAD_KVM-V400-build0605-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.5.2", "images": { "hda_disk_image": "FAD_KVM-v400-build0597-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.5.1", "images": { "hda_disk_image": "FAD_KVM-v400-build0581-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } }, { "name": "4.5.0", "images": { "hda_disk_image": "FAD_KVM-v400-build0560-FORTINET.out.kvm-boot.qcow2", - "hdb_disk_image": "FAD_KVM-v400-FORTINET.out.kvm-data.qcow2" + "hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2" } } ] diff --git a/gns3server/appliances/fortianalyzer.gns3a b/gns3server/appliances/fortianalyzer.gns3a index 611dc6c1..1055e466 100644 --- a/gns3server/appliances/fortianalyzer.gns3a +++ b/gns3server/appliances/fortianalyzer.gns3a @@ -26,6 +26,48 @@ "kvm": "allow" }, "images": [ + { + "filename": "FAZ_VM64_KVM-v6-build1050-FORTINET.out.kvm.qcow2", + "version": "6.2.0", + "md5sum": "dc123116e4c816d8b4dee244bd671844", + "filesize": 140177408, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAZ_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2", + "version": "6.0.3", + "md5sum": "14c98b20ed1d0729e2d04aad49ff1be5", + "filesize": 114589696, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAZ_VM64_KVM-v6-build0205-FORTINET.out.kvm.qcow2", + "version": "6.0.2", + "md5sum": "1c9c6a99244aaf8b215c52194e1f82ed", + "filesize": 115777536, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAZ_VM64_KVM-v6-build0092-FORTINET.out.kvm.qcow2", + "version": "6.0.0", + "md5sum": "e870087db55a095c75ddcafe73e1ea27", + "filesize": 117940224, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAZ_VM64_KVM-v5-build1782-FORTINET.out.kvm.qcow2", + "version": "5.6.7", + "md5sum": "f67c115cc51e911802e9cbcb5cb0c8c2", + "filesize": 110862336, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAZ_VM64_KVM-v5-build1631-FORTINET.out.kvm.qcow2", + "version": "5.6.2", + "md5sum": "c7f1cf26051b50b86e7e59b99e36756f", + "filesize": 105816064, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FAZ_VM64_KVM-v5-build1619-FORTINET.out.kvm.qcow2", "version": "5.6.1", @@ -113,6 +155,48 @@ } ], "versions": [ + { + "name": "6.2.0", + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v6-build1050-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.3", + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.2", + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v6-build0205-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.0", + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v6-build0092-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.6.7", + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1782-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.6.2", + "images": { + "hda_disk_image": "FAZ_VM64_KVM-v5-build1631-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "5.6.1", "images": { diff --git a/gns3server/appliances/fortiauthenticator.gns3a b/gns3server/appliances/fortiauthenticator.gns3a index e9771cbc..382eebab 100644 --- a/gns3server/appliances/fortiauthenticator.gns3a +++ b/gns3server/appliances/fortiauthenticator.gns3a @@ -26,6 +26,41 @@ "kvm": "allow" }, "images": [ + { + "filename": "FAC_VM_KVM-v6-build0010-FORTINET.out.kvm.qcow2", + "version": "6.0.0", + "md5sum": "6699c0b24e54dc6a5215ba3945abb364", + "filesize": 74317824, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAC_VM_KVM-v5-build0366-FORTINET.out.kvm.qcow2", + "version": "5.5.0", + "md5sum": "c6ae060f8840b467efac6701a7e8e6af", + "filesize": 72982528, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAC_VM_KVM-v5-build0297-FORTINET.out.kvm.qcow2", + "version": "5.4.1", + "md5sum": "e63bcaae040f903f9de315f582702619", + "filesize": 72617984, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAC_VM_KVM-v5-build0163-FORTINET.out.kvm.qcow2", + "version": "5.2.2", + "md5sum": "e746b3c6c29b0356ec6b90ed14d4b098", + "filesize": 71565312, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FAC_VM_KVM-v500-build0161-FORTINET.out.kvm.qcow2", + "version": "5.2.1", + "md5sum": "c46ad2de4a20296ebd35b3fcc2d81a1d", + "filesize": 72536064, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FAC_VM_KVM-v5-build0155-FORTINET.out.kvm.qcow2", "version": "5.2.0", @@ -62,47 +97,82 @@ "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" }, { - "filename": "FAC_VM_KVM-v500-DATADRIVE.qcow2", - "version": "5.x.x", + "filename": "FAC_VM_KVM-ALL-DATADRIVE.qcow2", + "version": "All", "md5sum": "09bad6cfe6301930adbc829eb8a67149", "filesize": 258048, "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" } ], "versions": [ + { + "name": "6.0.0", + "images": { + "hda_disk_image": "FAC_VM_KVM-v6-build0010-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" + } + }, + { + "name": "5.5.0", + "images": { + "hda_disk_image": "FAC_VM_KVM-v5-build0366-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" + } + }, + { + "name": "5.4.1", + "images": { + "hda_disk_image": "FAC_VM_KVM-v5-build0297-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" + } + }, + { + "name": "5.2.2", + "images": { + "hda_disk_image": "FAC_VM_KVM-v5-build0163-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" + } + }, + { + "name": "5.2.1", + "images": { + "hda_disk_image": "FAC_VM_KVM-v500-build0161-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" + } + }, { "name": "5.2.0", "images": { "hda_disk_image": "FAC_VM_KVM-v5-build0155-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" } }, { "name": "5.1.2", "images": { "hda_disk_image": "FAC_VM_KVM-v500-build0091-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" } }, { "name": "5.1.1", "images": { "hda_disk_image": "FAC_VM_KVM-v500-build0086-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" } }, { "name": "5.1.0", "images": { "hda_disk_image": "FAC_VM_KVM-v500-build0083-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" } }, { "name": "5.0.0", "images": { "hda_disk_image": "FAC_VM_KVM-v500-build0012-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2" + "hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2" } } ] diff --git a/gns3server/appliances/forticache.gns3a b/gns3server/appliances/forticache.gns3a index 501ec3b0..38ccaaa8 100644 --- a/gns3server/appliances/forticache.gns3a +++ b/gns3server/appliances/forticache.gns3a @@ -26,6 +26,27 @@ "kvm": "require" }, "images": [ + { + "filename": "FCHKVM-v400-build0230-FORTINET.out.kvm.qcow2", + "version": "4.2.9", + "md5sum": "a3583f162004da2f1e0b751e7b23504a", + "filesize": 27672576, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FCHKVM-v400-build0226-FORTINET.out.kvm.qcow2", + "version": "4.2.8", + "md5sum": "17efdc8f037c8ec1d1fc67ae262f619e", + "filesize": 27676672, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FCHKVM-v400-build0222-FORTINET.out.kvm.qcow2", + "version": "4.2.7", + "md5sum": "d77790e414f4e2b31c756906a720e681", + "filesize": 27631616, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FCHKVM-v400-build0216-FORTINET.out.kvm.qcow2", "version": "4.2.6", @@ -99,6 +120,27 @@ } ], "versions": [ + { + "name": "4.2.9", + "images": { + "hda_disk_image": "FCHKVM-v400-build0230-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + } + }, + { + "name": "4.2.8", + "images": { + "hda_disk_image": "FCHKVM-v400-build0226-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + } + }, + { + "name": "4.2.7", + "images": { + "hda_disk_image": "FCHKVM-v400-build0222-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty100G.qcow2" + } + }, { "name": "4.2.6", "images": { diff --git a/gns3server/appliances/fortigate.gns3a b/gns3server/appliances/fortigate.gns3a index caca6d17..f9c5e659 100644 --- a/gns3server/appliances/fortigate.gns3a +++ b/gns3server/appliances/fortigate.gns3a @@ -26,6 +26,41 @@ "kvm": "allow" }, "images": [ + { + "filename": "FGT_VM64_KVM-v6-build0866-FORTINET.out.kvm.qcow2", + "version": "6.2.0", + "md5sum": "588df9ba0db485976f6681810001ae73", + "filesize": 57868288, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FGT_VM64_KVM-v6-build0200-FORTINET.out.kvm.qcow2", + "version": "6.0.3", + "md5sum": "be6f74ea13da09cf0b68e87234e2d8d5", + "filesize": 51552256, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FGT_VM64_KVM-v6-build0076-FORTINET.out.kvm.qcow2", + "version": "6.0.0", + "md5sum": "161728b413e097954bd640ade89dfeb1", + "filesize": 46104576, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FGT_VM64_KVM-v5-build1653-FORTINET.out.kvm.qcow2", + "version": "5.6.7", + "md5sum": "202e1ed7582b02493be63f14cc48c2cb", + "filesize": 43180032, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FGT_VM64_KVM-v5-build1575-FORTINET.out.kvm.qcow2", + "version": "5.6.4", + "md5sum": "c312ea8ec1afffb73858fb1b15c095ef", + "filesize": 41594880, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FGT_VM64_KVM-v5-build1547-FORTINET.out.kvm.qcow2", "version": "5.6.3", @@ -54,6 +89,13 @@ "filesize": 38760448, "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" }, + { + "filename": "FGT_VM64_KVM-v5-build1220-FORTINET.out.kvm.qcow2", + "version": "5.4.10", + "md5sum": "7444d6c85ef6b937a98163482caa5a90", + "filesize": 39043072, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FGT_VM64_KVM-v5-build1183-FORTINET.out.kvm.qcow2", "version": "5.4.8", @@ -183,6 +225,41 @@ } ], "versions": [ + { + "name": "6.2.0", + "images": { + "hda_disk_image": "FGT_VM64_KVM-v6-build0866-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.3", + "images": { + "hda_disk_image": "FGT_VM64_KVM-v6-build0200-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.0", + "images": { + "hda_disk_image": "FGT_VM64_KVM-v6-build0076-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.6.7", + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1653-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.6.4", + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1575-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "5.6.3", "images": { @@ -211,6 +288,13 @@ "hdb_disk_image": "empty30G.qcow2" } }, + { + "name": "5.4.10", + "images": { + "hda_disk_image": "FGT_VM64_KVM-v5-build1220-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "5.4.8", "images": { diff --git a/gns3server/appliances/fortimail.gns3a b/gns3server/appliances/fortimail.gns3a index d52bb26f..511cf513 100644 --- a/gns3server/appliances/fortimail.gns3a +++ b/gns3server/appliances/fortimail.gns3a @@ -26,6 +26,34 @@ "kvm": "allow" }, "images": [ + { + "filename": "FML_VMKV-64-v60-build0143-FORTINET.out.kvm.qcow2", + "version": "6.0.4", + "md5sum": "e6401ecfe9b145256cccb29757bbddfe", + "filesize": 98959360, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FML_VMKV-64-v60-build0126-FORTINET.out.kvm.qcow2", + "version": "6.0.3", + "md5sum": "b062636f029ff0f3d4b74451cc70b755", + "filesize": 96731136, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FML_VMKV-64-v54-build0719-FORTINET.out.kvm.qcow2", + "version": "5.4.5", + "md5sum": "e2f202efd28039a6f1f4ebb7ee69e214", + "filesize": 97255424, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FML_VMKV-64-v54-build0714-FORTINET.out.kvm.qcow2", + "version": "5.4.4", + "md5sum": "6a3155d9cee6af3ecb016e59c0a0765f", + "filesize": 93519872, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FML_VMKV-64-v54-build0712-FORTINET.out.kvm.qcow2", "version": "5.4.3", @@ -54,6 +82,13 @@ "filesize": 101253120, "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" }, + { + "filename": "FML_VMKV-64-v53-build0653-FORTINET.out.kvm.qcow2", + "version": "5.3.12", + "md5sum": "aed4dcb17de047860736d8742362a754", + "filesize": 89980928, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FML_VMKV-64-v53-build0648-FORTINET.out.kvm.qcow2", "version": "5.3.11", @@ -134,6 +169,34 @@ } ], "versions": [ + { + "name": "6.0.4", + "images": { + "hda_disk_image": "FML_VMKV-64-v60-build0143-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.3", + "images": { + "hda_disk_image": "FML_VMKV-64-v60-build0126-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.4.5", + "images": { + "hda_disk_image": "FML_VMKV-64-v54-build0719-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.4.4", + "images": { + "hda_disk_image": "FML_VMKV-64-v54-build0714-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "5.4.3", "images": { @@ -162,6 +225,13 @@ "hdb_disk_image": "empty30G.qcow2" } }, + { + "name": "5.3.12", + "images": { + "hda_disk_image": "FML_VMKV-64-v53-build0653-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "5.3.11", "images": { diff --git a/gns3server/appliances/fortimanager.gns3a b/gns3server/appliances/fortimanager.gns3a index 6b809983..a0347aa4 100644 --- a/gns3server/appliances/fortimanager.gns3a +++ b/gns3server/appliances/fortimanager.gns3a @@ -26,6 +26,41 @@ "kvm": "allow" }, "images": [ + { + "filename": "FMG_VM64_KVM-v6-build1050-FORTINET.out.kvm.qcow2", + "version": "6.2.0", + "md5sum": "c19d2527f91ad1bbafbde5bf08487867", + "filesize": 126894080, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FMG_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2", + "version": "6.0.3", + "md5sum": "5f34d52d9289b0be2a4c04943446ea39", + "filesize": 115703808, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FMG_VM64_KVM-v6-build0205-FORTINET.out.kvm.qcow2", + "version": "6.0.2", + "md5sum": "8f748649c537d9b5466b24c5b4e62017", + "filesize": 116981760, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FMG_VM64_KVM-v6-build0092-FORTINET.out.kvm.qcow2", + "version": "6.0.0", + "md5sum": "73bfe1bc70124521a524d857646b9c2e", + "filesize": 119066624, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FMG_VM64_KVM-v5-build1631-FORTINET.out.kvm.qcow2", + "version": "5.6.2", + "md5sum": "c81cc247e8eb03249b475fe0e847653e", + "filesize": 106946560, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FMG_VM64_KVM-v5-build1619-FORTINET.out.kvm.qcow2", "version": "5.6.1", @@ -113,6 +148,34 @@ } ], "versions": [ + { + "name": "6.2.0", + "images": { + "hda_disk_image": "FMG_VM64_KVM-v6-build1050-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.2", + "images": { + "hda_disk_image": "FMG_VM64_KVM-v6-build0205-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.0", + "images": { + "hda_disk_image": "FMG_VM64_KVM-v6-build0092-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.6.2", + "images": { + "hda_disk_image": "FMG_VM64_KVM-v5-build1631-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "5.6.1", "images": { diff --git a/gns3server/appliances/fortiproxy.gns3a b/gns3server/appliances/fortiproxy.gns3a new file mode 100644 index 00000000..03e39fdf --- /dev/null +++ b/gns3server/appliances/fortiproxy.gns3a @@ -0,0 +1,68 @@ +{ + "name": "FortiProxy", + "category": "firewall", + "description": "FortiProxy is a secure web proxy that protects employees against internet-borne attacks by incorporating multiple detection techniques such as web filtering, DNS filtering, data loss prevention, antivirus, intrusion prevention and advanced threat protection. It helps enterprises enforce internet compliance using granular application control.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "documentation_url": "https://docs.fortinet.com/fortiproxy/", + "product_name": "FortiProxy", + "product_url": "https://www.fortinet.com/content/dam/fortinet/assets/data-sheets/FortiProxy.pdf", + "registry_version": 3, + "status": "stable", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "usage": "The system reboots twice during the initial setup; this is normal.\nDefault username is admin, no password is set.", + "port_name_format": "Port{port1}", + "symbol": "fortinet.svg", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 10, + "ram": 2048, + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "arch": "x86_64", + "console_type": "telnet", + "boot_priority": "c", + "kvm": "allow" + }, + "images": [ + { + "filename": "FPX_KVM-v100-build0162-FORTINET.out.kvm.qcow2", + "version": "1.1.2", + "md5sum": "00db4c04fcc4ac0d7c389a86c71d20a5", + "filesize": 44601344, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FPX_KVM-v100-build0147-FORTINET.out.kvm.qcow2", + "version": "1.1.0", + "md5sum": "d7c60693bfa58246e5063304cd450c89", + "filesize": 42668032, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "empty30G.qcow2", + "version": "1.0", + "md5sum": "3411a599e822f2ac6be560a26405821a", + "filesize": 197120, + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download" + } + ], + "versions": [ + { + "name": "1.1.2", + "images": { + "hda_disk_image": "FPX_KVM-v100-build0162-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "1.1.0", + "images": { + "hda_disk_image": "FPX_KVM-v100-build0147-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + } + ] +} diff --git a/gns3server/appliances/fortirecorder.gns3a b/gns3server/appliances/fortirecorder.gns3a new file mode 100644 index 00000000..fe2a115c --- /dev/null +++ b/gns3server/appliances/fortirecorder.gns3a @@ -0,0 +1,68 @@ +{ + "name": "FortiRecorder", + "category": "guest", + "description": "Surveillance systems can be complicated, expensive, and unreliable. But FortiCamera and FortiRecorder simplify IP video surveillance and there are no license fees. With FortiCams, you can see everything: doors, POS terminals, public areas--whatever you need to keep an eye on. FortiRecorder captures the images for easy monitoring, storage, and retrieval. Just plug in your cameras, connect the FortiRecorder, open a web browser or client application, and you're ready to go. It's easy to navigate and configure with event timelines and profile-driven configuration.", + "vendor_name": "Fortinet", + "vendor_url": "http://www.fortinet.com/", + "documentation_url": "https://docs.fortinet.com/fortirecorder/", + "product_name": "FortiRecorder", + "product_url": "https://www.fortinet.com/products/network-based-video-security/forticam-fortirecorder.html", + "registry_version": 3, + "status": "stable", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "usage": "Use HTTPS when connecting to the WebUI.\nDefault username is admin, no password is set.", + "port_name_format": "Port{port1}", + "symbol": "fortinet.svg", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 10, + "ram": 2048, + "hda_disk_interface": "virtio", + "hdb_disk_interface": "virtio", + "arch": "x86_64", + "console_type": "telnet", + "boot_priority": "c", + "kvm": "allow" + }, + "images": [ + { + "filename": "FRC_VMKV-64-v27-build0700-FORTINET.out.kvm.qcow2", + "version": "2.7.1", + "md5sum": "3736c66af7d958fc672fe29439b405b8", + "filesize": 79429632, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FRC_VMKV-64-v26-build0607-FORTINET.out.kvm.qcow2", + "version": "2.6.3", + "md5sum": "ffa5d42119de576631673516f60e028b", + "filesize": 63569920, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "empty30G.qcow2", + "version": "1.0", + "md5sum": "3411a599e822f2ac6be560a26405821a", + "filesize": 197120, + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download" + } + ], + "versions": [ + { + "name": "2.7.1", + "images": { + "hda_disk_image": "FRC_VMKV-64-v27-build0700-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "2.6.3", + "images": { + "hda_disk_image": "FRC_VMKV-64-v26-build0607-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + } + ] +} diff --git a/gns3server/appliances/fortisandbox.gns3a b/gns3server/appliances/fortisandbox.gns3a index d7d702f4..e022265f 100644 --- a/gns3server/appliances/fortisandbox.gns3a +++ b/gns3server/appliances/fortisandbox.gns3a @@ -27,6 +27,34 @@ "options": "-smp 2" }, "images": [ + { + "filename": "FSA_KVM-v300-build0060-FORTINET.out.kvm.qcow2", + "version": "3.0.4", + "md5sum": "7e744c4d62430917aea4533672710b5a", + "filesize": 157221376, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FSA_KVM-v300-build0049-FORTINET.out.kvm.qcow2", + "version": "3.0.3", + "md5sum": "3ef1f05124d13e23332b8b90f8f71c2c", + "filesize": 156828160, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FSA_KVM-v300-build0029-FORTINET.out.kvm.qcow2", + "version": "3.0.1", + "md5sum": "a2f6c5297a722c5dba40327734a6e0ac", + "filesize": 153158144, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FSA_KVM-v200-build0340-FORTINET.out.kvm.qcow2", + "version": "2.5.2", + "md5sum": "527f3225bd3fbd4ba23779cc1987d2ed", + "filesize": 117834240, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FSA_KVM-v200-build0329-FORTINET.out.kvm.qcow2", "version": "2.5.1", @@ -70,54 +98,82 @@ "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" }, { - "filename": "FSA_v200-datadrive.qcow2", - "version": "2.x", + "filename": "FSA-datadrive.qcow2", + "version": "All", "md5sum": "f2dc0a8fc7591699c364aff400369157", "filesize": 200192, "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" } ], "versions": [ + { + "name": "3.0.4", + "images": { + "hda_disk_image": "FSA_KVM-v300-build0060-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + } + }, + { + "name": "3.0.3", + "images": { + "hda_disk_image": "FSA_KVM-v300-build0049-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + } + }, + { + "name": "3.0.1", + "images": { + "hda_disk_image": "FSA_KVM-v300-build0029-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + } + }, + { + "name": "2.5.2", + "images": { + "hda_disk_image": "FSA_KVM-v200-build0340-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "FSA-datadrive.qcow2" + } + }, { "name": "2.5.1", "images": { "hda_disk_image": "FSA_KVM-v200-build0329-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" + "hdb_disk_image": "FSA-datadrive.qcow2" } }, { "name": "2.4.1", "images": { "hda_disk_image": "FSA_KVM-v200-build0261-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" + "hdb_disk_image": "FSA-datadrive.qcow2" } }, { "name": "2.4.0", "images": { "hda_disk_image": "FSA_KVM-v200-build0252-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" + "hdb_disk_image": "FSA-datadrive.qcow2" } }, { "name": "2.3.3", "images": { "hda_disk_image": "FSA_KVM-v200-build0205-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" + "hdb_disk_image": "FSA-datadrive.qcow2" } }, { "name": "2.3.2", "images": { "hda_disk_image": "FSA_KVM-v200-build0195-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" + "hdb_disk_image": "FSA-datadrive.qcow2" } }, { "name": "2.3.0", "images": { "hda_disk_image": "FSA_VM-v200-build0183-FORTINET.out.kvm.qcow2", - "hdb_disk_image": "FSA_v200-datadrive.qcow2" + "hdb_disk_image": "FSA-datadrive.qcow2" } } ] diff --git a/gns3server/appliances/fortisiem-super_worker.gns3a b/gns3server/appliances/fortisiem-super_worker.gns3a index a280d742..d6223091 100644 --- a/gns3server/appliances/fortisiem-super_worker.gns3a +++ b/gns3server/appliances/fortisiem-super_worker.gns3a @@ -11,7 +11,7 @@ "status": "stable", "maintainer": "GNS3 Team", "maintainer_email": "developers@gns3.net", - "usage": "This is the Super/Worker component. Default credentials:\n- admin / admin*1\n - root / ProspectHills\n\nIf you get a 503 error on the WebUI, run /opt/phoenix/deployment/jumpbox/phinitsuper as root.", + "usage": "This is the Super/Worker component. Default credentials:\n- admin / admin*1\n - root / ProspectHills\n\nIf you get a 503 error on the WebUI, run /opt/phoenix/deployment/jumpbox/phinitsuper as root.\n\nMake sure that Super, Worker(s), Collector(s) and Report Server can connect to FortiSIEM hosted CentOS repo on https port 443 under the URLs below. Otherwise, some packages may not install and 5.0.0 binaries will not run.\n- https://os-pkgs-cdn.fortisiem.fortinet.com/centos6/\n- https://os-pkgs.fortisiem.fortinet.com/centos6/", "port_name_format": "Port{port1}", "symbol": "fortinet.svg", "qemu": { @@ -28,6 +28,69 @@ "options": "-smp 4" }, "images": [ + { + "filename": "FortiSIEM-VA-5.2.1.1553-OS.qcow2", + "version": "5.2.1", + "md5sum": "9dc3f4a9614b65c83d3e9733248cbcea", + "filesize": 3902208000, + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html" + }, + { + "filename": "FortiSIEM-VA-5.2.1.1553-CMDB.qcow2", + "version": "5.2.1", + "md5sum": "ea3f69191eb803cdf021227ec666bf7b", + "filesize": 46858240, + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html" + }, + { + "filename": "FortiSIEM-VA-5.2.1.1553-SVN.qcow2", + "version": "5.2.1", + "md5sum": "eff32e40baf6ede7bc57ad8d241812ad", + "filesize": 46858240, + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html" + }, + { + "filename": "FortiSIEM-VA-5.1.0.1336.qcow2", + "version": "5.1.0", + "md5sum": "753685ee68287c7a56f9da53566ac522", + "filesize": 10376904704, + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html" + }, + { + "filename": "FortiSIEM-VA-5.1.0.1336-1.qcow2", + "version": "5.1.0", + "md5sum": "6ffb7e16d89a6731fc077982cb012ee2", + "filesize": 46858240, + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html" + }, + { + "filename": "FortiSIEM-VA-5.1.0.1336-2.qcow2", + "version": "5.1.0", + "md5sum": "8185e537ce222c2e8407e9bf08e604bb", + "filesize": 46858240, + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html" + }, + { + "filename": "FortiSIEM-VA-5.0.0.1201.qcow2", + "version": "5.0.0", + "md5sum": "1f2f0b1d84e89495fc5b5ca722cb5710", + "filesize": 10029432832, + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release500.html" + }, + { + "filename": "FortiSIEM-VA-5.0.0.1201-1.qcow2", + "version": "5.0.0", + "md5sum": "88e96259f44a82b7c545b82925880513", + "filesize": 46858240, + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release500.html" + }, + { + "filename": "FortiSIEM-VA-5.0.0.1201-2.qcow2", + "version": "5.0.0", + "md5sum": "58d61498e1adc1df062fc12113d42d86", + "filesize": 46858240, + "download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release500.html" + }, { "filename": "FortiSIEM-VA-KVM-4.10.0.1102.qcow2", "version": "4.10.0", @@ -72,6 +135,30 @@ } ], "versions": [ + { + "name": "5.2.1", + "images": { + "hda_disk_image": "FortiSIEM-VA-5.2.1.1553-OS.qcow2", + "hdb_disk_image": "FortiSIEM-VA-5.2.1.1553-CMDB.qcow2", + "hdc_disk_image": "FortiSIEM-VA-5.2.1.1553-SVN.qcow2" + } + }, + { + "name": "5.1.0", + "images": { + "hda_disk_image": "FortiSIEM-VA-5.1.0.1336.qcow2", + "hdb_disk_image": "FortiSIEM-VA-5.1.0.1336-1.qcow2", + "hdc_disk_image": "FortiSIEM-VA-5.1.0.1336-2.qcow2" + } + }, + { + "name": "5.0.0", + "images": { + "hda_disk_image": "FortiSIEM-VA-5.0.0.1201.qcow2", + "hdb_disk_image": "FortiSIEM-VA-5.0.0.1201-1.qcow2", + "hdc_disk_image": "FortiSIEM-VA-5.0.0.1201-2.qcow2" + } + }, { "name": "4.10.0", "images": { diff --git a/gns3server/appliances/fortiweb.gns3a b/gns3server/appliances/fortiweb.gns3a index 3872777d..c365d84f 100644 --- a/gns3server/appliances/fortiweb.gns3a +++ b/gns3server/appliances/fortiweb.gns3a @@ -26,6 +26,48 @@ "kvm": "allow" }, "images": [ + { + "filename": "FWB_KVM-v600-build0383-FORTINET.out.kvm.qcow2", + "version": "6.1.0", + "md5sum": "d2dbbde9f03eb716a54119cc3e6055c4", + "filesize": 190120448, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FWB_KVM-v600-build0056-FORTINET.out.kvm.qcow2", + "version": "6.0.2", + "md5sum": "cc7800bc6c2dd60c583d2d4ef1965e01", + "filesize": 156959232, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FWB_KVM-v600-build0036-FORTINET.out.kvm.qcow2", + "version": "6.0.1", + "md5sum": "220170383b66a6f8091729d67a8fef3e", + "filesize": 138412544, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FWB_KVM-v500-build1618-FORTINET.out.kvm.qcow2", + "version": "5.9.1", + "md5sum": "12bafff7bbfbf9a49554c6378f0e1a46", + "filesize": 132579840, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FWB_KVM-v500-build1609-FORTINET.out.kvm.qcow2", + "version": "5.9.0", + "md5sum": "a957ae3d60eabc685fcda015c31a5d01", + "filesize": 140837376, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "FWB_KVM-v500-build1413-FORTINET.out.kvm.qcow2", + "version": "5.8.6", + "md5sum": "910fefe796daa5c963b0bde121996306", + "filesize": 105775616, + "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, { "filename": "FWB_KVM-v500-build0739-FORTINET.out.kvm-log.qcow2", "version": "5.5.4", @@ -60,9 +102,60 @@ "md5sum": "0a613191948d3618ae16cd9f11988448", "filesize": 87162880, "download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx" + }, + { + "filename": "empty30G.qcow2", + "version": "1.0", + "md5sum": "3411a599e822f2ac6be560a26405821a", + "filesize": 197120, + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download" } + ], "versions": [ + { + "name": "6.1.0", + "images": { + "hda_disk_image": "FWB_KVM-v600-build0383-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.2", + "images": { + "hda_disk_image": "FWB_KVM-v600-build0056-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "6.0.1", + "images": { + "hda_disk_image": "FWB_KVM-v600-build0036-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.9.1", + "images": { + "hda_disk_image": "FWB_KVM-v500-build1618-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.9.0", + "images": { + "hda_disk_image": "FWB_KVM-v500-build1609-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, + { + "name": "5.8.6", + "images": { + "hda_disk_image": "FWB_KVM-v500-build1413-FORTINET.out.kvm.qcow2", + "hdb_disk_image": "empty30G.qcow2" + } + }, { "name": "5.5.4", "images": { diff --git a/gns3server/appliances/freebsd.gns3a b/gns3server/appliances/freebsd.gns3a index 90d97218..31789069 100644 --- a/gns3server/appliances/freebsd.gns3a +++ b/gns3server/appliances/freebsd.gns3a @@ -22,6 +22,24 @@ "kvm": "require" }, "images": [ + { + "filename": "FreeBSD-12.0-RELEASE-amd64.qcow2", + "version": "12.0", + "md5sum": "4d2126ba79dad224628be6f25a908bd8", + "filesize": 2644836352, + "download_url": "https://www.freebsd.org/where.html", + "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/12.0-RELEASE/amd64/Latest/FreeBSD-12.0-RELEASE-amd64.qcow2.xz", + "compression": "xz" + }, + { + "filename": "FreeBSD-11.2-RELEASE-amd64.qcow2", + "version": "11.2", + "md5sum": "44d37e65be4bb4054f067911c84d074a", + "filesize": 1630076928, + "download_url": "https://www.freebsd.org/where.html", + "direct_download_url": "https://download.freebsd.org/ftp/releases/VM-IMAGES/11.2-RELEASE/amd64/Latest/FreeBSD-11.2-RELEASE-amd64.qcow2.xz", + "compression": "xz" + }, { "filename": "FreeBSD-11.1-RELEASE-amd64.qcow2", "version": "11.1", @@ -60,6 +78,18 @@ } ], "versions": [ + { + "name": "12.0", + "images": { + "hda_disk_image": "FreeBSD-12.0-RELEASE-amd64.qcow2" + } + }, + { + "name": "11.2", + "images": { + "hda_disk_image": "FreeBSD-11.2-RELEASE-amd64.qcow2" + } + }, { "name": "11.1", "images": { diff --git a/gns3server/appliances/freenas.gns3a b/gns3server/appliances/freenas.gns3a index e92a05ee..114f3319 100644 --- a/gns3server/appliances/freenas.gns3a +++ b/gns3server/appliances/freenas.gns3a @@ -24,6 +24,38 @@ "kvm": "require" }, "images": [ + { + "filename": "FreeNAS-11.2-U3.iso", + "version": "11.2 U3", + "md5sum": "59ee32e2598a792eec0355b40a511251", + "filesize": 600387584, + "download_url": "http://www.freenas.org/download/", + "direct_download_url": "https://download.freenas.org/11.2/STABLE/U3/x64/FreeNAS-11.2-U3.iso" + }, + { + "filename": "FreeNAS-11.2-RELEASE.iso", + "version": "11.2", + "md5sum": "bf4a9ebb19313c3d45f84c1550477727", + "filesize": 603410432, + "download_url": "http://www.freenas.org/download/", + "direct_download_url": "https://download.freenas.org/11.2/STABLE/RELEASE/x64/FreeNAS-11.2-RELEASE.iso" + }, + { + "filename": "FreeNAS-11.1-U6.iso", + "version": "11.1 U6", + "md5sum": "633d6444cad903c707983b54e04fc053", + "filesize": 636065792, + "download_url": "http://www.freenas.org/download/", + "direct_download_url": "https://download.freenas.org/11/11.1-U6/x64/FreeNAS-11.1-U6.iso" + }, + { + "filename": "FreeNAS-11.1-U4.iso", + "version": "11.1 U4", + "md5sum": "d75623e5671dbc82f32f4b4f8d46092f", + "filesize": 633833472, + "download_url": "http://www.freenas.org/download/", + "direct_download_url": "https://download.freenas.org/11/11.1-U4/x64/FreeNAS-11.1-U4.iso" + }, { "filename": "FreeNAS-11.1-U1.iso", "version": "11.1 U1", @@ -66,6 +98,38 @@ } ], "versions": [ + { + "name": "11.2 U3", + "images": { + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2", + "cdrom_image": "FreeNAS-11.2-U3.iso" + } + }, + { + "name": "11.2", + "images": { + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2", + "cdrom_image": "FreeNAS-11.2-RELEASE.iso" + } + }, + { + "name": "11.1 U6", + "images": { + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2", + "cdrom_image": "FreeNAS-11.1-U6.iso" + } + }, + { + "name": "11.1 U4", + "images": { + "hda_disk_image": "empty30G.qcow2", + "hdb_disk_image": "empty30G.qcow2", + "cdrom_image": "FreeNAS-11.1-U4.iso" + } + }, { "name": "11.1 U1", "images": { diff --git a/gns3server/appliances/frr.gns3a b/gns3server/appliances/frr.gns3a new file mode 100644 index 00000000..476556e6 --- /dev/null +++ b/gns3server/appliances/frr.gns3a @@ -0,0 +1,72 @@ +{ + "name": "FRR", + "category": "router", + "description": "FRRouting (FRR) is an IP routing protocol suite for Linux and Unix platforms which includes protocol daemons for BGP, IS-IS, LDP, OSPF, PIM, and RIP.\n\nFRR’s seamless integration with the native Linux/Unix IP networking stacks makes it applicable to a wide variety of use cases including connecting hosts/VMs/containers to the network, advertising network services, LAN switching and routing, Internet access routers, and Internet peering.\n\nThis is an unofficial VM or FRR.", + "vendor_name": "FRRouting Project", + "vendor_url": "https://frrouting.org", + "product_name": "FRR", + "registry_version": 3, + "status": "stable", + "maintainer": "Andras Dosztal", + "maintainer_email": "developers@gns3.net", + "usage": "Credentials: frr / frr\nIf you exit from the router CLI, you can get back by typing 'vtysh' to the console.", + "port_name_format": "ens{port3}", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 8, + "ram": 512, + "hda_disk_interface": "virtio", + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require" + }, + "images": [ + { + "filename": "frr7.0-vm0.3.qcow2", + "version": "FRR7.0 - VM0.3", + "md5sum": "5fa8ce0ee74215f4c4a8c61778ee0b10", + "filesize": 2044657664, + "download_url": "https://sourceforge.net/projects/frr/files/", + "direct_download_url": "https://sourceforge.net/projects/frr/files/FRR7.0-VM0.3.qcow2.bz2/download", + "compression": "bzip2" + }, + { + "filename": "frr6.0-vm0.2.qcow2", + "version": "FRR6.0 - VM0.2", + "md5sum": "bf5aebd98352716bfabb119abb2ba19a", + "filesize": 1762066432, + "download_url": "https://sourceforge.net/projects/frr/files/", + "direct_download_url": "https://sourceforge.net/projects/frr/files/frr6.0-vm0.2.qcow2.bz2/download", + "compression": "bzip2" + }, + { + "filename": "frr4.0-vm0.1.qcow2", + "version": "FRR4.0 - VM0.1", + "md5sum": "e1dc58cbb2b71c58051538c07d412493", + "filesize": 1670643712, + "download_url": "https://sourceforge.net/projects/frr/files/", + "direct_download_url": "https://sourceforge.net/projects/frr/files/frr4.0-vm0.1.qcow2.bz2/download", + "compression": "bzip2" + } + ], + "versions": [ + { + "name": "FRR7.0 - VM0.3", + "images": { + "hda_disk_image": "frr7.0-vm0.3.qcow2" + } + }, + { + "name": "FRR6.0 - VM0.2", + "images": { + "hda_disk_image": "frr6.0-vm0.2.qcow2" + } + }, + { + "name": "FRR4.0 - VM0.1", + "images": { + "hda_disk_image": "frr4.0-vm0.1.qcow2" + } + } + ] +} diff --git a/gns3server/appliances/hp-vsr1001.gns3a b/gns3server/appliances/hp-vsr1001.gns3a index d061b86a..6d0fb3fc 100644 --- a/gns3server/appliances/hp-vsr1001.gns3a +++ b/gns3server/appliances/hp-vsr1001.gns3a @@ -1,10 +1,10 @@ { "name": "HPE VSR1001", "category": "router", - "description": "The HP VSR1000 Virtual Services Router Series is a software application, running on a server, which provides functionality similar to that of a physical router: robust routing between networked devices using a number of popular routing protocols. It also delivers the critical network services associated with today's enterprise routers such as VPN gateway, firewall and other security and traffic management functions.\n\nThe virtual services router (VSR) application runs on a hypervqcor on the server, and supports VMware vSphere and Linux KVM hypervqcors. From one to eight virtual CPUs are supported, depending on license.\n\nBecause the VSR1000 Series application runs the same HP Comware version 7 operating system as HP switches and routers, it enables significant operational savings. And being virtual, additional agility and ease of deployment is realized, as resources on the VSR can be dynamically allocated and upgraded upon demand as performance requirements grow.\n\nA variety of deployment models are supported including enterprise branch CPE routing, and cloud offload for small to medium workloads.", + "description": "The HPE VSR1000 Virtual Services Router Series is a software application, running on a server, which provides functionality similar to that of a physical router: robust routing between networked devices using a number of popular routing protocols. It also delivers the critical network services associated with today's enterprise routers such as VPN gateway, firewall and other security and traffic management functions.\n\nThe virtual services router (VSR) application runs on a hypervqcor on the server, and supports VMware vSphere and Linux KVM hypervqcors. From one to eight virtual CPUs are supported, depending on license.\n\nBecause the VSR1000 Series application runs the same HPE Comware version 7 operating system as HPE switches and routers, it enables significant operational savings. And being virtual, additional agility and ease of deployment is realized, as resources on the VSR can be dynamically allocated and upgraded upon demand as performance requirements grow.\n\nA variety of deployment models are supported including enterprise branch CPE routing, and cloud offload for small to medium workloads.", "vendor_name": "HPE", "vendor_url": "http://www.hpe.com", - "documentation_url": "http://h20195.www2.hpe.com/v2/default.aspx?cc=us&lc=en&oid=5443878", + "documentation_url": "https://support.hpe.com/hpesc/public/home/documentHome?document_type=135&sp4ts.oid=5195141", "product_name": "VSR1001", "product_url": "https://www.hpe.com/us/en/product-catalog/networking/networking-routers/pip.hpe-flexnetwork-vsr1000-virtual-services-router-series.5443163.html", "registry_version": 3, @@ -20,67 +20,81 @@ "arch": "x86_64", "console_type": "vnc", "boot_priority": "c", - "kvm": "require" + "kvm": "require", + "options": "-machine type=pc-1.0" }, "images": [ + { + "filename": "VSR1000_HPE-CMW710-E0519L03-X64.qco", + "version": "7.10.E0519L03", + "md5sum": "83e23d27e7c3ef7ce813e6aad31d74f7", + "filesize": 202047488, + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=23726&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" + }, { "filename": "VSR1000_HPE-CMW710-R0327L01-X64.qco", "version": "7.10.R0327L01", "md5sum": "907de5140a4a029afe1c517cfc27ecde", "filesize": 138739712, - "download_url": "https://h10145.www1.hp.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=22702&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=22702&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" }, { "filename": "VSR1000_HPE-CMW710-R0326-X64.qco", "version": "7.10.R0326", "md5sum": "4153d638bfa72ca72a957ea8682ad0e2", "filesize": 138412032, - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=" + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=21985&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" }, { "filename": "VSR1000_HPE-CMW710-E0325-X64.qco", "version": "7.10.E0325", "md5sum": "a6731f3af86bee9b209a8b342be6bf75", "filesize": 111738880, - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=" + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=20278&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" }, { "filename": "VSR1000_HPE-CMW710-E0518-X64.qco", "version": "7.10.E0518", "md5sum": "4991436442ae706df8041c69778a48df", "filesize": 201588736, - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=" + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=21929&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" }, { "filename": "VSR1000_HPE-CMW710-E0324-X64.qco", "version": "7.10.E0324", "md5sum": "7a0ff32281284c042591c6181426effd", "filesize": 111411200, - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=" + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=18977&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" }, { "filename": "VSR1000_HPE-CMW710-E0322P01-X64.qco", "version": "7.10.E0322P01", "md5sum": "0aa2dbe5910fa64eb8c623e083b21a5e", "filesize": 110428160, - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=" + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=18976&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" }, { "filename": "VSR1000_HPE-CMW710-E0322-X64.qco", "version": "7.10.E0322", "md5sum": "05e0dab6b7aa489f627448b4d79b1f50", "filesize": 113770496, - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=" + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=18975&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" }, { "filename": "VSR1000_HPE-CMW710-E0321P01-X64.qco", "version": "7.10.E0321P01", "md5sum": "26d4375fafeedc81f298f29f593de252", "filesize": 113639424, - "download_url": "https://h10145.www1.hp.com/Downloads/SoftwareReleases.aspx?ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SoftwareReleaseUId=11832&SerialNumber=&PurchaseDate=" + "download_url": "https://h10145.www1.hpe.com/Downloads/DownloadSoftware.aspx?SoftwareReleaseUId=16838&ProductNumber=JG811AAE&lang=en&cc=us&prodSeriesId=5443163&SaidNumber=" } ], "versions": [ + { + "name": "7.10.E0519L03", + "images": { + "hda_disk_image": "VSR1000_HPE-CMW710-E0519L03-X64.qco" + } + }, { "name": "7.10.R0327L01", "images": { diff --git a/gns3server/appliances/ipfire.gns3a b/gns3server/appliances/ipfire.gns3a index 3f671dc4..bfc08507 100644 --- a/gns3server/appliances/ipfire.gns3a +++ b/gns3server/appliances/ipfire.gns3a @@ -24,6 +24,42 @@ "kvm": "allow" }, "images": [ + { + "filename": "ipfire-2.21.2gb-ext4.x86_64-full-core129.img", + "version": "2.21.129", + "md5sum": "84801c588174763c585967a2851a7769", + "filesize": 1541160960, + "download_url": "http://www.ipfire.org/download", + "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.21-core129/ipfire-2.21.2gb-ext4.x86_64-full-core129.img.xz", + "compression": "xz" + }, + { + "filename": "ipfire-2.21.2gb-ext4.x86_64-full-core124.img", + "version": "2.21.124", + "md5sum": "970a5cafaa0cb4cfbf42772f41d24932", + "filesize": 1541160960, + "download_url": "http://www.ipfire.org/download", + "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.21-core124/ipfire-2.21.2gb-ext4.x86_64-full-core124.img.xz", + "compression": "xz" + }, + { + "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core119.img", + "version": "2.19.119", + "md5sum": "b57be976ff54569b71eae4ee66634b0d", + "filesize": 1063256064, + "download_url": "http://www.ipfire.org/download", + "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.19-core119/ipfire-2.19.1gb-ext4-scon.x86_64-full-core119.img.gz", + "compression": "gzip" + }, + { + "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core118.img", + "version": "2.19.118", + "md5sum": "4dbeb474848d87c16c20ff4e31feb204", + "filesize": 1063256064, + "download_url": "http://www.ipfire.org/download", + "direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.19-core118/ipfire-2.19.1gb-ext4-scon.x86_64-full-core118.img.gz", + "compression": "gzip" + }, { "filename": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core117.img", "version": "2.19.117", @@ -62,6 +98,30 @@ } ], "versions": [ + { + "name": "2.21.129", + "images": { + "hda_disk_image": "ipfire-2.21.2gb-ext4.x86_64-full-core129.img" + } + }, + { + "name": "2.21.124", + "images": { + "hda_disk_image": "ipfire-2.21.2gb-ext4.x86_64-full-core124.img" + } + }, + { + "name": "2.19.119", + "images": { + "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core119.img" + } + }, + { + "name": "2.19.118", + "images": { + "hda_disk_image": "ipfire-2.19.1gb-ext4-scon.x86_64-full-core118.img" + } + }, { "name": "2.19.117", "images": { diff --git a/gns3server/appliances/juniper-vmx-vcp.gns3a b/gns3server/appliances/juniper-vmx-vcp.gns3a index 96873a53..4d3ffc5b 100644 --- a/gns3server/appliances/juniper-vmx-vcp.gns3a +++ b/gns3server/appliances/juniper-vmx-vcp.gns3a @@ -18,67 +18,13 @@ "qemu": { "adapter_type": "e1000", "adapters": 2, - "ram": 2048, + "ram": 1024, "arch": "x86_64", "console_type": "telnet", "kvm": "require", "options": "-nographic -enable-kvm" }, "images": [ - { - "filename": "vcp_18.4R1.8-disk1.vmdk", - "version": "18.4R1.8-ESXi", - "md5sum": "82a02f8b8e3181a409f44e96270dbb80", - "filesize": 1145199104 - }, - { - "filename": "vcp_18.4R1.8-disk2.vmdk", - "version": "18.4R1.8-ESXi", - "md5sum": "338c7235d448067437d5f5bc0a4db2ed", - "filesize": 68608 - }, - { - "filename": "vcp_18.4R1.8-disk3.vmdk", - "version": "18.4R1.8-ESXi", - "md5sum": "e10c48024289ba81a375383ea2196f9f", - "filesize": 71680 - }, - { - "filename": "junos-vmx-x86-64-18.4R1.8.qcow2", - "version": "18.4R1.8-KVM", - "md5sum": "7e3cb628f67d31aad5bcd6b54fbb6052", - "filesize": 1419378688 - }, - { - "filename": "vmxhdd-18.4R1.8.img", - "version": "18.4R1.8-KVM", - "md5sum": "ae26e0f32605a53a5c85342bad677c9f", - "filesize": 197120 - }, - { - "filename": "metadata-usb-re-18.4R1.8.img", - "version": "18.4R1.8-KVM", - "md5sum": "b79bcce958cb3af6a7a048ae5d278960", - "filesize": 10485760 - }, - { - "filename": "vcp_17.4R1.16-disk1.vmdk", - "version": "17.4R1.16-ESXi", - "md5sum": "69450d850b76dbd0387dd8bb854c6229", - "filesize": 1196968960 - }, - { - "filename": "vcp_17.4R1.16-disk2.vmdk", - "version": "17.4R1.16-ESXi", - "md5sum": "0acfb272e7420de0ab8ddd80ac321b57", - "filesize": 5928960 - }, - { - "filename": "vcp_17.4R1.16-disk3.vmdk", - "version": "17.4R1.16-ESXi", - "md5sum": "a07f81beeaad964d70df55a653abb14d", - "filesize": 71680 - }, { "filename": "junos-vmx-x86-64-17.4R1.16.qcow2", "version": "17.4R1.16-KVM", @@ -97,6 +43,24 @@ "md5sum": "a5b125822b798c7167c35966ea00229a", "filesize": 16777216 }, + { + "filename": "junos-vmx-x86-64-17.3R2.10.qcow2", + "version": "17.3R2.10-KVM", + "md5sum": "11984eb87b471e8cc2677212c4277959", + "filesize": 1298137088 + }, + { + "filename": "vmxhdd-17.3R2.10.img", + "version": "17.3R2.10-KVM", + "md5sum": "9d843e5493d5e86d37853a72885d84c8", + "filesize": 108986368 + }, + { + "filename": "metadata-usb-re-17.3R2.10.img", + "version": "17.3R2.10-KVM", + "md5sum": "564ca5b7c03ed39680d2d42464d9489b", + "filesize": 16777216 + }, { "filename": "vcp_17.1R1.8-disk1.vmdk", "version": "17.1R1.8-ESXi", @@ -333,33 +297,27 @@ "md5sum": "af48f7e03f94ffcfeecd15a59a4f1567", "filesize": 16777216, "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/" + }, + { + "filename": "junos-vmx-x86-64-15.1F6.9.qcow2", + "version": "15.1F6.9-KVM", + "md5sum": "595f532b95d6d98590d0375a3d6d14b6", + "filesize": 994181120 + }, + { + "filename": "vmxhdd-15.1F6.9.img", + "version": "15.1F6.9-KVM", + "md5sum": "bae35d0bb72946d1e91ff9c5e7ddbf86", + "filesize": 108986368 + }, + { + "filename": "metadata-usb-re-15.1F6.9.img", + "version": "15.1F6.9-KVM", + "md5sum": "15238c3dbc987d1a641c919efe2731c5", + "filesize": 16777216 } ], "versions": [ - { - "name": "18.4R1.8-ESXi", - "images": { - "hda_disk_image": "vcp_18.4R1.8-disk1.vmdk", - "hdb_disk_image": "vcp_18.4R1.8-disk2.vmdk", - "hdc_disk_image": "vcp_18.4R1.8-disk3.vmdk" - } - }, - { - "name": "18.4R1.8-KVM", - "images": { - "hda_disk_image": "junos-vmx-x86-64-18.4R1.8.qcow2", - "hdb_disk_image": "vmxhdd-18.4R1.8.img", - "hdc_disk_image": "metadata-usb-re-18.4R1.8.img" - } - }, - { - "name": "17.4R1.16-ESXi", - "images": { - "hda_disk_image": "vcp_17.4R1.16-disk1.vmdk", - "hdb_disk_image": "vcp_17.4R1.16-disk2.vmdk", - "hdc_disk_image": "vcp_17.4R1.16-disk3.vmdk" - } - }, { "name": "17.4R1.16-KVM", "images": { @@ -368,6 +326,14 @@ "hdc_disk_image": "metadata-usb-re-17.4R1.16.img" } }, + { + "name": "17.3R2.10-KVM", + "images": { + "hda_disk_image": "junos-vmx-x86-64-17.3R2.10.qcow2", + "hdb_disk_image": "vmxhdd-17.3R2.10.img", + "hdc_disk_image": "metadata-usb-re-17.3R2.10.img" + } + }, { "name": "17.1R1.8-ESXi", "images": { @@ -471,6 +437,14 @@ "hdb_disk_image": "vmxhdd-15.1.img", "hdc_disk_image": "metadata-usb-15.1.img" } - } + }, + { + "name": "15.1F6.9", + "images": { + "hda_disk_image": "junos-vmx-x86-64-15.1F6.9.qcow2", + "hdb_disk_image": "vmxhdd-15.1F6.9.img", + "hdc_disk_image": "metadata-usb-re-15.1F6.9.img" + } + } ] } diff --git a/gns3server/appliances/juniper-vmx-vfp.gns3a b/gns3server/appliances/juniper-vmx-vfp.gns3a index 6ab3562b..697bfb0e 100644 --- a/gns3server/appliances/juniper-vmx-vfp.gns3a +++ b/gns3server/appliances/juniper-vmx-vfp.gns3a @@ -26,30 +26,16 @@ }, "images": [ { - "filename": "vfpc_18.4R1.8-disk1.vmdk", - "version": "18.4R1.8-ESXi", - "md5sum": "d3c3002be95b7835607a3a1ce5fb241e", - "filesize": 133520384, - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/" - }, - { - "filename": "vFPC-20181130.img", - "version": "18.4R1.8-KVM", - "md5sum": "08451e026235084aa2e6b4fccadf7227", + "filename": "vFPC-20171213.img", + "version": "17.4R1.16-KVM", + "md5sum": "848a6256da7296e8fede368a258c68e4", "filesize": 2313158656, "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/" }, { - "filename": "vfpc_17.4R1.16-disk1.vmdk", - "version": "17.4R1.16-ESXi", - "md5sum": "6292a758821ac823c3a6b6d2f7cc599a", - "filesize": 108361216, - "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/" - }, - { - "filename": "vFPC-20171213.img", - "version": "17.4R1.16-KVM", - "md5sum": "848a6256da7296e8fede368a258c68e4", + "filename": "vFPC-20180126.img", + "version": "17.3R2.10-KVM", + "md5sum": "02d6b719053485c52a511fe6f5a598e3", "filesize": 2313158656, "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/" }, @@ -59,7 +45,7 @@ "md5sum": "169dd487b8547d58b12b2918a5667360", "filesize": 102820352, "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/" - }, + }, { "filename": "vFPC-20170216.img", "version": "17.1R1.8-KVM", @@ -136,41 +122,36 @@ "md5sum": "5ccf252002184a21413cad23fd239c3f", "filesize": 2313158656, "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/" - }, + }, + { + "filename": "vFPC-15.1F6.9.img", + "version": "15.1F6.9-KVM", + "md5sum": "7328501fdfa9b160955bc136664f1e86", + "filesize": 2313158656, + "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/" + }, { "filename": "vFPC-20151203.img", "version": "15.1F4.15", "md5sum": "b3faa91b4d20836a9a6dd6bad2629dd1", "filesize": 2313158656, "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/" - } + } ], "versions": [ - { - "name": "18.4R1.8-ESXi", - "images": { - "hda_disk_image": "vfpc_18.4R1.8-disk1.vmdk" - } - }, - { - "name": "18.4R1.8-KVM", - "images": { - "hda_disk_image": "vFPC-20181130.img" - } - }, - { - "name": "17.4R1.16-ESXi", - "images": { - "hda_disk_image": "vfpc_17.4R1.16-disk1.vmdk" - } - }, { "name": "17.4R1.16-KVM", "images": { "hda_disk_image": "vFPC-20171213.img" } }, + { + "name": "17.3R2.10-KVM", + "images": { + "hda_disk_image": "vFPC-20180126.img" + } + }, { "name": "17.1R1.8-ESXi", "images": { @@ -243,12 +224,18 @@ "hda_disk_image": "vFPC-20160617.img" } }, + { + "name": "15.1F6.9-KVM", + "images": { + "hda_disk_image": "vFPC-15.1F6.9.img" + } + }, { "name": "15.1F4.15", "images": { "hda_disk_image": "vFPC-20151203.img" } } - + ] } diff --git a/gns3server/appliances/juniper-vqfx-pfe.gns3a b/gns3server/appliances/juniper-vqfx-pfe.gns3a index 7e15ad72..c84e8fa0 100644 --- a/gns3server/appliances/juniper-vqfx-pfe.gns3a +++ b/gns3server/appliances/juniper-vqfx-pfe.gns3a @@ -24,6 +24,13 @@ "options": "-nographic" }, "images": [ + { + "filename": "cosim_20180212.qcow2", + "version": "17.4R1", + "md5sum": "0372e9c1b7df3608099186ab8cbbf2ad", + "filesize": 1911291904, + "download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/" + }, { "filename": "vqfx10k-pfe-20160609-2.vmdk", "version": "15.1X53-D60", @@ -33,6 +40,12 @@ } ], "versions": [ + { + "name": "17.4R1", + "images": { + "hda_disk_image": "cosim_20180212.qcow2" + } + }, { "name": "15.1X53-D60", "images": { diff --git a/gns3server/appliances/juniper-vqfx-re.gns3a b/gns3server/appliances/juniper-vqfx-re.gns3a index 1506f409..2f08021f 100644 --- a/gns3server/appliances/juniper-vqfx-re.gns3a +++ b/gns3server/appliances/juniper-vqfx-re.gns3a @@ -24,6 +24,13 @@ "options": "-nographic -smp 2" }, "images": [ + { + "filename": "jinstall-vqfx-10-f-17.4R1.16.img", + "version": "17.4R1", + "md5sum": "dd83313b0f5beaf68488ed3d5e1e5240", + "filesize": 553910272, + "download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/" + }, { "filename": "vqfx10k-re-15.1X53-D60.vmdk", "version": "15.1X53-D60", @@ -33,6 +40,12 @@ } ], "versions": [ + { + "name": "17.4R1", + "images": { + "hda_disk_image": "jinstall-vqfx-10-f-17.4R1.16.img" + } + }, { "name": "15.1X53-D60", "images": { diff --git a/gns3server/appliances/juniper-vsrx.gns3a b/gns3server/appliances/juniper-vsrx.gns3a index 002b9bd9..ec24f68a 100644 --- a/gns3server/appliances/juniper-vsrx.gns3a +++ b/gns3server/appliances/juniper-vsrx.gns3a @@ -12,6 +12,7 @@ "maintainer": "GNS3 Team", "maintainer_email": "developers@gns3.net", "usage": "Initial username is root, no password.", + "first_port_name": "fxp0", "port_name_format": "ge-0/0/{0}", "qemu": { "adapter_type": "e1000", @@ -23,6 +24,13 @@ "options": "-smp 2" }, "images": [ + { + "filename": "junos-media-vsrx-vmdisk-18.1R1.9.qcow2", + "version": "18.1R1", + "md5sum": "4e9393142afc675d5d3d03c5071e70ce", + "filesize": 4418961408, + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/" + }, { "filename": "media-vsrx-vmdisk-17.4R1.16.qcow2", "version": "17.4R1", @@ -30,6 +38,13 @@ "filesize": 3965386752, "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/" }, + { + "filename": "media-vsrx-vmdisk-17.3R2.10.qcow2", + "version": "17.3R2", + "md5sum": "8f2adfb0515913e0c7db32628a5deb3e", + "filesize": 3784572928, + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/" + }, { "filename": "media-vsrx-vmdisk-17.3R1.10.qcow2", "version": "17.3R1", @@ -37,6 +52,13 @@ "filesize": 3782541312, "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/" }, + { + "filename": "media-vsrx-vmdisk-15.1X49-D130.6.qcow2", + "version": "15.1X49-D130", + "md5sum": "8ad03f4067b3fe5d2ed378733a5e8541", + "filesize": 3300917248, + "download_url": "https://www.juniper.net/us/en/dm/free-vsrx-trial/" + }, { "filename": "media-vsrx-vmdisk-15.1X49-D120.3.qcow2", "version": "15.1X49-D120", @@ -123,18 +145,36 @@ } ], "versions": [ + { + "name": "18.1R1", + "images": { + "hda_disk_image": "junos-media-vsrx-vmdisk-18.1R1.9.qcow2" + } + }, { "name": "17.4R1", "images": { "hda_disk_image": "media-vsrx-vmdisk-17.4R1.16.qcow2" } }, + { + "name": "17.3R2", + "images": { + "hda_disk_image": "media-vsrx-vmdisk-17.3R2.10.qcow2" + } + }, { "name": "17.3R1", "images": { "hda_disk_image": "media-vsrx-vmdisk-17.3R1.10.qcow2" } }, + { + "name": "15.1X49-D130", + "images": { + "hda_disk_image": "media-vsrx-vmdisk-15.1X49-D130.6.qcow2" + } + }, { "name": "15.1X49-D120", "images": { diff --git a/gns3server/appliances/kali-linux.gns3a b/gns3server/appliances/kali-linux.gns3a index 78732d07..65e5e9e7 100644 --- a/gns3server/appliances/kali-linux.gns3a +++ b/gns3server/appliances/kali-linux.gns3a @@ -20,6 +20,38 @@ "kvm": "require" }, "images": [ + { + "filename": "kali-linux-2019.1a-amd64.iso", + "version": "2019.1a", + "md5sum": "58c6111ed0be1919ea87267e7e65ab0f", + "filesize": 3483873280, + "download_url": "https://www.kali.org/downloads/", + "direct_download_url": "http://cdimage.kali.org/kali-2019.1a/kali-linux-2019.1a-amd64.iso" + }, + { + "filename": "kali-linux-2018.4-amd64.iso", + "version": "2018.4", + "md5sum": "1b2d598bb8d2003e6207c119c0ba42fe", + "filesize": 3139436544, + "download_url": "https://www.kali.org/downloads/", + "direct_download_url": "http://cdimage.kali.org/kali-2018.4/kali-linux-2018.4-amd64.iso" + }, + { + "filename": "kali-linux-2018.3a-amd64.iso", + "version": "2018.3a", + "md5sum": "2da675d016bd690c05e180e33aa98b94", + "filesize": 3192651776, + "download_url": "https://www.kali.org/downloads/", + "direct_download_url": "http://cdimage.kali.org/kali-2018.3a/kali-linux-2018.3a-amd64.iso" + }, + { + "filename": "kali-linux-2018.1-amd64.iso", + "version": "2018.1", + "md5sum": "a3feb90df5b71b3c7f4a02bdddf221d7", + "filesize": 3028500480, + "download_url": "https://www.kali.org/downloads/", + "direct_download_url": "http://cdimage.kali.org/kali-2018.1/kali-linux-2018.1-amd64.iso" + }, { "filename": "kali-linux-2017.3-amd64.iso", "version": "2017.3", @@ -70,6 +102,30 @@ } ], "versions": [ + { + "name": "2019.1a", + "images": { + "cdrom_image": "kali-linux-2019.1a-amd64.iso" + } + }, + { + "name": "2018.4", + "images": { + "cdrom_image": "kali-linux-2018.4-amd64.iso" + } + }, + { + "name": "2018.3a", + "images": { + "cdrom_image": "kali-linux-2018.3a-amd64.iso" + } + }, + { + "name": "2018.1", + "images": { + "cdrom_image": "kali-linux-2018.1-amd64.iso" + } + }, { "name": "2017.3", "images": { diff --git a/gns3server/appliances/kemp-vlm.gns3a b/gns3server/appliances/kemp-vlm.gns3a index b873db5c..16f1beb2 100644 --- a/gns3server/appliances/kemp-vlm.gns3a +++ b/gns3server/appliances/kemp-vlm.gns3a @@ -26,6 +26,13 @@ "options": "-smp 2" }, "images": [ + { + "filename": "LoadMaster-VLM-7.2.44.0.16685.RELEASE-Linux-KVM-XEN-FREE.disk", + "version": "7.2.44.0", + "md5sum": "90d2f84fcabe0ba530c84cf12fab87f1", + "filesize": 17179869185, + "download_url": "http://freeloadbalancer.com/download/" + }, { "filename": "LoadMaster-VLM-7.2.40.0.15707.RELEASE-Linux-KVM-XEN-FREE.disk", "version": "7.2.40.0", @@ -63,6 +70,12 @@ } ], "versions": [ + { + "name": "7.2.44.0", + "images": { + "hda_disk_image": "LoadMaster-VLM-7.2.44.0.16685.RELEASE-Linux-KVM-XEN-FREE.disk" + } + }, { "name": "7.2.40.0", "images": { diff --git a/gns3server/appliances/kerio-connect.gns3a b/gns3server/appliances/kerio-connect.gns3a index 741477d1..c5117fc2 100644 --- a/gns3server/appliances/kerio-connect.gns3a +++ b/gns3server/appliances/kerio-connect.gns3a @@ -24,6 +24,22 @@ "kvm": "require" }, "images": [ + { + "filename": "kerio-connect-appliance-9.2.7-4225-p3-vmware-amd64-disk1.vmdk", + "version": "9.2.7p3", + "md5sum": "12950c8244300f1d86c85c109f0b3413", + "filesize": 914165248, + "download_url": "http://www.kerio.com/support/kerio-connect", + "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.7-4225/kerio-connect-appliance-9.2.7-4225-p3-vmware-amd64-disk1.vmdk" + }, + { + "filename": "kerio-connect-appliance-9.2.6-3851-p1-vmware-amd64-disk1.vmdk", + "version": "9.2.6p1", + "md5sum": "c6ed064114c6fd70608b7951b707528c", + "filesize": 625852004, + "download_url": "http://www.kerio.com/support/kerio-connect", + "direct_download_url": "http://cdn.kerio.com/dwn/connect/connect-9.2.6-3851/kerio-connect-appliance-9.2.6-3851-p1-vmware-amd64-disk1.vmdk" + }, { "filename": "kerio-connect-appliance-9.2.5-3336-p3-vmware-amd64-disk1.vmdk", "version": "9.2.5p3", @@ -68,7 +84,19 @@ ], "versions": [ { - "name": "9.2.5", + "name": "9.2.7p3", + "images": { + "hda_disk_image": "kerio-connect-appliance-9.2.7-4225-p3-vmware-amd64-disk1.vmdk" + } + }, + { + "name": "9.2.6p1", + "images": { + "hda_disk_image": "kerio-connect-appliance-9.2.6-3851-p1-vmware-amd64-disk1.vmdk" + } + }, + { + "name": "9.2.5p3", "images": { "hda_disk_image": "kerio-connect-appliance-9.2.5-3336-p3-vmware-amd64-disk1.vmdk" } diff --git a/gns3server/appliances/kerio-control.gns3a b/gns3server/appliances/kerio-control.gns3a index 2b3f48db..1b2904e7 100644 --- a/gns3server/appliances/kerio-control.gns3a +++ b/gns3server/appliances/kerio-control.gns3a @@ -23,6 +23,30 @@ "kvm": "require" }, "images": [ + { + "filename": "kerio-control-appliance-9.3.0-3273-vmware-disk1.vmdk", + "version": "9.3.0", + "md5sum": "6e6faf64b4ffce8b5639cdfce11ba31e", + "filesize": 192825856, + "download_url": "http://www.kerio.com/support/kerio-control", + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.3.0-3273/kerio-control-appliance-9.3.0-3273-vmware-disk1.vmdk" + }, + { + "filename": "kerio-control-appliance-9.2.7-2921-vmware-disk1.vmdk", + "version": "9.2.7", + "md5sum": "d286a240be53f8dd9da5f80deb9086b0", + "filesize": 191135232, + "download_url": "http://www.kerio.com/support/kerio-control", + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.7-2921/kerio-control-appliance-9.2.7-2921-vmware-disk1.vmdk" + }, + { + "filename": "kerio-control-appliance-9.2.5-2641-p5-vmware-disk1.vmdk", + "version": "9.2.5p5", + "md5sum": "fbb2824eb91ca2502c952c2e9c4e635d", + "filesize": 190706688, + "download_url": "http://www.kerio.com/support/kerio-control", + "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.2.5-2641/kerio-control-appliance-9.2.5-2641-p5-vmware-disk1.vmdk" + }, { "filename": "kerio-control-appliance-9.2.4-2223-vmware-disk1.vmdk", "version": "9.2.4", @@ -63,6 +87,24 @@ "direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.1.4-1535/kerio-control-appliance-9.1.4-1535-vmware.vmdk" } ], "versions": [ + { + "name": "9.3.0", + "images": { + "hda_disk_image": "kerio-control-appliance-9.3.0-3273-vmware-disk1.vmdk" + } + }, + { + "name": "9.2.7", + "images": { + "hda_disk_image": "kerio-control-appliance-9.2.7-2921-vmware-disk1.vmdk" + } + }, + { + "name": "9.2.5p5", + "images": { + "hda_disk_image": "kerio-control-appliance-9.2.5-2641-p5-vmware-disk1.vmdk" + } + }, { "name": "9.2.4", "images": { diff --git a/gns3server/appliances/kerio-operator.gns3a b/gns3server/appliances/kerio-operator.gns3a index a193eb9c..7d4bf307 100644 --- a/gns3server/appliances/kerio-operator.gns3a +++ b/gns3server/appliances/kerio-operator.gns3a @@ -24,6 +24,22 @@ "kvm": "require" }, "images": [ + { + "filename": "kerio-operator-appliance-2.6.4-9320-vmware-disk1.vmdk", + "version": "2.6.4", + "md5sum": "3823565dbc96069dc556158ebbbfb977", + "filesize": 307840512, + "download_url": "http://www.kerio.com/support/kerio-operator", + "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.6.4-9320/kerio-operator-appliance-2.6.4-9320-vmware-disk1.vmdk" + }, + { + "filename": "kerio-operator-appliance-2.6.2-9085-vmware-disk1.vmdk", + "version": "2.6.2", + "md5sum": "abdfa7697e568b5d9a6396e11292e52a", + "filesize": 306665472, + "download_url": "http://www.kerio.com/support/kerio-operator", + "direct_download_url": "http://cdn.kerio.com/dwn/operator/operator-2.6.2-9085/kerio-operator-appliance-2.6.2-9085-vmware-disk1.vmdk" + }, { "filename": "kerio-operator-appliance-2.6.0-8413-vmware-disk1.vmdk", "version": "2.6.0", @@ -66,6 +82,18 @@ } ], "versions": [ + { + "name": "2.6.4", + "images": { + "hda_disk_image": "kerio-operator-appliance-2.6.4-9320-vmware-disk1.vmdk" + } + }, + { + "name": "2.6.2", + "images": { + "hda_disk_image": "kerio-operator-appliance-2.6.2-9085-vmware-disk1.vmdk" + } + }, { "name": "2.6.0", "images": { diff --git a/gns3server/appliances/mikrotik-chr.gns3a b/gns3server/appliances/mikrotik-chr.gns3a index 559b6bd0..ac0a42ba 100644 --- a/gns3server/appliances/mikrotik-chr.gns3a +++ b/gns3server/appliances/mikrotik-chr.gns3a @@ -26,6 +26,60 @@ "options": "-nographic" }, "images": [ + { + "filename": "chr-6.44.2.img", + "version": "6.44.2", + "md5sum": "f1ddaa47829e12c1f9f023d8c06b88cc", + "filesize": 67108864, + "download_url": "http://www.mikrotik.com/download", + "direct_download_url": "https://download.mikrotik.com/routeros/6.44.2/chr-6.44.2.img.zip", + "compression": "zip" + }, + { + "filename": "chr-6.43.8.img", + "version": "6.43.8", + "md5sum": "9437133fc7e77779dc3ff62b98f30dc2", + "filesize": 134217728, + "download_url": "http://www.mikrotik.com/download", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.43.8/chr-6.43.8.img.zip", + "compression": "zip" + }, + { + "filename": "chr-6.42.9.img", + "version": "6.42.9", + "md5sum": "1f856978cfc3ceb4b5e18e4e079f2e32", + "filesize": 134217728, + "download_url": "http://www.mikrotik.com/download", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.42.9/chr-6.42.9.img.zip", + "compression": "zip" + }, + { + "filename": "chr-6.42.img", + "version": "6.42", + "md5sum": "279bb518497b40f41c8585128916a2fb", + "filesize": 134217728, + "download_url": "http://www.mikrotik.com/download", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.42/chr-6.42.img.zip", + "compression": "zip" + }, + { + "filename": "chr-6.41.4.img", + "version": "6.41.4", + "md5sum": "63b555b2b7f0d78b79edb92f7e7d2ed7", + "filesize": 134217728, + "download_url": "http://www.mikrotik.com/download", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.41.4/chr-6.41.4.img.zip", + "compression": "zip" + }, + { + "filename": "chr-6.40.7.img", + "version": "6.40.7", + "md5sum": "424b897d631c4cac4324ca310e81b494", + "filesize": 134217728, + "download_url": "http://www.mikrotik.com/download", + "direct_download_url": "https://download2.mikrotik.com/routeros/6.40.7/chr-6.40.7.img.zip", + "compression": "zip" + }, { "filename": "chr-6.40.5.img", "version": "6.40.5", @@ -235,6 +289,36 @@ } ], "versions": [ + { + "name": "6.44.2", + "images": { + "hda_disk_image": "chr-6.44.2.img" + } + }, + { + "name": "6.43.8", + "images": { + "hda_disk_image": "chr-6.43.8.img" + } + }, + { + "name": "6.42.9", + "images": { + "hda_disk_image": "chr-6.42.9.img" + } + }, + { + "name": "6.41.4", + "images": { + "hda_disk_image": "chr-6.41.4.img" + } + }, + { + "name": "6.40.7", + "images": { + "hda_disk_image": "chr-6.40.7.img" + } + }, { "name": "6.40.5", "images": { diff --git a/gns3server/appliances/mininet.gns3a b/gns3server/appliances/mininet.gns3a new file mode 100644 index 00000000..80900c2b --- /dev/null +++ b/gns3server/appliances/mininet.gns3a @@ -0,0 +1,46 @@ +{ + "category": "guest", + "status": "stable", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "description": "Mininet creates a realistic virtual network, running real kernel, switch and application code, on a single machine (VM, cloud or native), in seconds, with a single command.", + "product_name": "Mininet", + "registry_version": 4, + "product_url": "http://mininet.org/", + "documentation_url": "http://mininet.org/walkthrough/", + "first_port_name": "eth0", + "usage": "Username: mininet\nPassword: mininet", + "port_name_format": "eth{0}", + "vendor_name": "Mininet Team", + "qemu": { + "adapters": 1, + "adapter_type": "virtio-net-pci", + "arch": "x86_64", + "ram": 2048, + "console_type": "vnc", + "hda_disk_interface": "virtio", + "kvm": "allow" + }, + "availability": "free", + "vendor_url": "http://mininet.org/", + "name": "Mininet", + "images": [ + { + "filename": "mininet-vm-x86_64.vmdk", + "version": "2.2.2", + "md5sum": "a683441642300bdaf37b8e614de85342", + "filesize": 2047868928, + "download_url": "https://github.com/mininet/mininet/releases/", + "direct_download_url": "https://github.com/mininet/mininet/releases/download/2.2.2/mininet-2.2.2-170321-ubuntu-14.04.4-server-amd64.zip", + "compression": "zip" + } + ], + "versions": [ + { + "images": { + "hda_disk_image": "mininet-vm-x86_64.vmdk" + }, + "name": "2.2.2" + } + ] +} diff --git a/gns3server/appliances/net_toolbox.gns3a b/gns3server/appliances/net_toolbox.gns3a new file mode 100644 index 00000000..8181fa8b --- /dev/null +++ b/gns3server/appliances/net_toolbox.gns3a @@ -0,0 +1,19 @@ +{ + "name": "Toolbox", + "category": "guest", + "description": "This appliance contains server side software for secondary management of network devices:\n- www (nginx) \n- ftp (vsftpd)\n- tftp (tftpd)\n- syslog (rsyslog)\n- dhcp (isc-dhcpd)\n- snmp server (snmpd + snmptrapd)", + "vendor_name": "Ubuntu", + "vendor_url": "https://www.ubuntu.com/", + "product_name": "Networkers' toolbox", + "registry_version": 3, + "status": "stable", + "maintainer": "Andras Dosztal", + "maintainer_email": "developers@gns3.net", + "symbol": "linux_guest.svg", + "usage": "Root password: gns3", + "docker": { + "adapters": 1, + "image": "adosztal/net_toolbox:latest", + "console_type": "telnet" + } +} diff --git a/gns3server/appliances/network_automation.gns3a b/gns3server/appliances/network_automation.gns3a index 54816047..b0607cf6 100644 --- a/gns3server/appliances/network_automation.gns3a +++ b/gns3server/appliances/network_automation.gns3a @@ -12,7 +12,7 @@ "symbol": "linux_guest.svg", "docker": { "adapters": 1, - "image": "gns3/network_automation:latest", + "image": "adosztal/network_automation:latest", "console_type": "telnet" } } diff --git a/gns3server/appliances/op5-monitor.gns3a b/gns3server/appliances/op5-monitor.gns3a index 9a612293..ee73a787 100644 --- a/gns3server/appliances/op5-monitor.gns3a +++ b/gns3server/appliances/op5-monitor.gns3a @@ -25,6 +25,13 @@ "kvm": "require" }, "images": [ + { + "filename": "op5-Monitor-Virtual-Appliance-7.4.10.x86_64-disk1.vmdk", + "version": "7.4.10", + "md5sum": "48ec6d7ee3809d9ed705a089c679e076", + "filesize": 1111941120, + "download_url": "https://www.op5.com/download/" + }, { "filename": "op5-Monitor-Virtual-Appliance-7.3.15.x86_64.vmdk", "version": "7.3.15", @@ -34,6 +41,12 @@ } ], "versions": [ + { + "name": "7.4.10", + "images": { + "hda_disk_image": "op5-Monitor-Virtual-Appliance-7.4.10.x86_64-disk1.vmdk" + } + }, { "name": "7.3.15", "images": { diff --git a/gns3server/appliances/openwrt.gns3a b/gns3server/appliances/openwrt.gns3a index 3e70cafc..84a1bdbc 100644 --- a/gns3server/appliances/openwrt.gns3a +++ b/gns3server/appliances/openwrt.gns3a @@ -11,31 +11,76 @@ "status": "stable", "maintainer": "GNS3 Team", "maintainer_email": "developers@gns3.net", - "usage": "Ethernet0 is the LAN link, Ethernet1 the WAN link.", + "usage": "Ethernet0 is the LAN link, Ethernet1 the WAN link, Ethernet2 and Ethernet3 are optional links.", "qemu": { "adapter_type": "virtio-net-pci", - "adapters": 2, - "ram": 64, - "arch": "i386", + "adapters": 4, + "ram": 128, + "arch": "x86_64", "console_type": "telnet", "kvm": "allow" }, "images": [ { - "filename": "openwrt-15.05.1-x86-kvm_guest-combined-ext4.img", + "filename": "openwrt-18.06.2-x86-64-combined-ext4.img", + "version": "18.06.2", + "md5sum": "d112cd432bf51e2ddadbf9513f272fd9", + "filesize": 285736960, + "download_url": "https://downloads.openwrt.org/releases/18.06.2/targets/x86/64/", + "direct_download_url": "https://downloads.openwrt.org/releases/18.06.2/targets/x86/64/openwrt-18.06.2-x86-64-combined-ext4.img.gz", + "compression": "gzip" + }, + { + "filename": "openwrt-18.06.1-x86-64-combined-ext4.img", + "version": "18.06.1", + "md5sum": "3e2da47c5c2496b6df364a60ded8f40a", + "filesize": 285736960, + "download_url": "https://downloads.openwrt.org/releases/18.06.1/targets/x86/64/", + "direct_download_url": "https://downloads.openwrt.org/releases/18.06.1/targets/x86/64/openwrt-18.06.1-x86-64-combined-ext4.img.gz", + "compression": "gzip" + }, + { + "filename": "lede-17.01.6-x86-64-combined-ext4.img", + "version": "17.01.6", + "md5sum": "015c0d5038ddd469fbdabce7eb5265dc", + "filesize": 285736960, + "download_url": "https://downloads.openwrt.org/releases/17.01.6/targets/x86/64/", + "direct_download_url": "https://downloads.openwrt.org/releases/17.01.6/targets/x86/64/lede-17.01.6-x86-64-combined-ext4.img.gz", + "compression": "gzip" + }, + { + "filename": "openwrt-15.05.1-x86-64-combined-ext4.img", "version": "15.05.1", - "md5sum": "d02f5224b7fbe929efa4d3f10f4dc996", + "md5sum": "307d8cdb11faeb1b5e27fe55078bd152", "filesize": 55050240, - "download_url": "http://downloads.openwrt.org/chaos_calmer/15.05.1/x86/kvm_guest/", - "direct_download_url": "https://downloads.openwrt.org/chaos_calmer/15.05.1/x86/kvm_guest/openwrt-15.05.1-x86-kvm_guest-combined-ext4.img.gz", + "download_url": "http://archive.openwrt.org/chaos_calmer/15.05.1/x86/64/", + "direct_download_url": "http://archive.openwrt.org/chaos_calmer/15.05.1/x86/64/openwrt-15.05.1-x86-64-combined-ext4.img.gz", "compression": "gzip" } ], "versions": [ { - "name": "Chaos Calmer 15.05.1", + "name": "openwrt 18.06.2", "images": { - "hda_disk_image": "openwrt-15.05.1-x86-kvm_guest-combined-ext4.img" + "hda_disk_image": "openwrt-18.06.2-x86-64-combined-ext4.img" + } + }, + { + "name": "openwrt 18.06.1", + "images": { + "hda_disk_image": "openwrt-18.06.1-x86-64-combined-ext4.img" + } + }, + { + "name": "openwrt/lede 17.01.6", + "images": { + "hda_disk_image": "lede-17.01.6-x86-64-combined-ext4.img" + } + }, + { + "name": "openwrt 15.05.1", + "images": { + "hda_disk_image": "openwrt-15.05.1-x86-64-combined-ext4.img" } } ] diff --git a/gns3server/appliances/opnsense.gns3a b/gns3server/appliances/opnsense.gns3a index 261cff76..5633d38e 100644 --- a/gns3server/appliances/opnsense.gns3a +++ b/gns3server/appliances/opnsense.gns3a @@ -25,18 +25,31 @@ }, "images": [ { - "filename": "OPNsense-17.7-OpenSSL-nano-amd64.img", - "version": "17.7", - "md5sum": "14cde5c7a15b2298a242238ad3c3b65a", - "filesize": 3221233664, - "download_url": "https://opnsense.org/download/" + "filename": "OPNsense-18.1.6-OpenSSL-nano-amd64.img", + "version": "18.1.6", + "md5sum": "042f328380ad0c8008759c43435e8843", + "filesize": 272003136, + "download_url": "https://opnsense.c0urier.net/releases/18.1/" + }, + { + "filename": "OPNsense-17.7.5-OpenSSL-nano-amd64.img", + "version": "17.7.5", + "md5sum": "6ec5b7f99cc727f904bbf2aaadcab0b8", + "filesize": 237038601, + "download_url": "https://opnsense.c0urier.net/releases/17.7/" } ], "versions": [ { - "name": "17.7", + "name": "18.1.6", "images": { - "hda_disk_image": "OPNsense-17.7-OpenSSL-nano-amd64.img" + "hda_disk_image": "OPNsense-18.1.6-OpenSSL-nano-amd64.img" + } + }, + { + "name": "17.7.5", + "images": { + "hda_disk_image": "OPNsense-17.7.5-OpenSSL-nano-amd64.img" } } ] diff --git a/gns3server/appliances/packetfence-zen.gns3a b/gns3server/appliances/packetfence-zen.gns3a index efc68820..90e34d17 100644 --- a/gns3server/appliances/packetfence-zen.gns3a +++ b/gns3server/appliances/packetfence-zen.gns3a @@ -22,6 +22,24 @@ "kvm": "require" }, "images": [ + { + "filename": "PacketFenceZEN_USB-8.3.0.img", + "version": "8.3.0", + "md5sum": "b9de52dc2513220ad42d350486da4884", + "filesize": 3221225472, + "download_url": "https://packetfence.org/download.html#/zen", + "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/8.3.0/PacketFenceZEN_USB-8.3.0.tar.bz2/download", + "compression": "bzip2" + }, + { + "filename": "PacketFenceZEN_USB-8.1.0.img", + "version": "8.1.0", + "md5sum": "f326f0e70b35d598c8b84ee3fc9c611f", + "filesize": 3221225472, + "download_url": "https://packetfence.org/download.html#/zen", + "direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/8.1.0/PacketFenceZEN_USB-8.1.0.tar.bz2/download", + "compression": "bzip2" + }, { "filename": "PacketFenceZEN_USB-7.4.0.img", "version": "7.4.0", @@ -105,6 +123,18 @@ } ], "versions": [ + { + "name": "8.3.0", + "images": { + "hda_disk_image": "PacketFenceZEN_USB-8.3.0.img" + } + }, + { + "name": "8.1.0", + "images": { + "hda_disk_image": "PacketFenceZEN_USB-8.1.0.img" + } + }, { "name": "7.4.0", "images": { diff --git a/gns3server/appliances/pan-vm-fw.gns3a b/gns3server/appliances/pan-vm-fw.gns3a index 9a196132..dc560715 100644 --- a/gns3server/appliances/pan-vm-fw.gns3a +++ b/gns3server/appliances/pan-vm-fw.gns3a @@ -1,85 +1,123 @@ -{ - "name": "PA-VM", - "category": "firewall", - "description": "The VM-Series combines next-generation firewall security and advanced threat prevention to protect your virtualized environments from advanced cyberthreats. The VM-Series natively analyzes all traffic in a single pass to determine the application identity, the content within, and the user identity.", - "vendor_name": "Palo Alto Networks", - "vendor_url": "http://www.paloaltonetworks.com/", - "documentation_url": "https://www.paloaltonetworks.com/documentation/80/virtualization/virtualization", - "product_name": "PAN VM-Series Firewall", - "product_url": "https://www.paloaltonetworks.com/products/secure-the-network/virtualized-next-generation-firewall/vm-series", - "registry_version": 3, - "status": "experimental", - "maintainer": "Community", - "maintainer_email": "", - "usage": "Default Username: admin\r\nDefault Password: admin\r\nPAN-VM goes through several iterations of host prompts during boot. This is normal and expected.\r\nLogin is available when prompt is PA-VM login:\r\n\r\nGetting Started:\r\nTo configure a static IP address at the console enter the following commands:\r\n\r\nconfigure\r\nset deviceconfig system ip-address netmask default-gateway type static\r\nset deviceconfig system dns-setting servers primary secondary \r\ncommit\r\n", - "symbol": "pan-vm-fw.svg", - "first_port_name": "management", - "port_name_format": "ethernet1/{port1}", - "qemu": { - "adapter_type": "virtio-net-pci", - "adapters": 25, - "ram": 4096, - "arch": "x86_64", - "console_type": "telnet", - "hda_disk_interface": "virtio", - "kvm": "require", - "options": "-smp 2" - }, - "images": [ - { - "filename": "PA-VM-ESX-6.1.0-disk1.vmdk", - "version": "6.1.0 (ESX)", - "md5sum": "64b1e81cd54008318235832ea6d71424", - "filesize": 2959736832, - "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" - }, - { - "filename": "PA-VM-KVM-7.1.0.qcow2", - "version": "7.1.0", - "md5sum": "da300253709740068927408239c2e321", - "filesize": 1858797568, - "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" - }, - { - "filename": "PA-VM-ESX-7.1.0-disk1.vmdk", - "version": "7.1.0 (ESX)", - "md5sum": "e044dc649b7146ee4f619edb0e5f6675", - "filesize": 1871149056, - "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" - }, - { - "filename": "PA-VM-KVM-8.0.0.qcow2", - "version": "8.0.0", - "md5sum": "b6a1ddc8552aff87f05f9c0d4cb54dc3", - "filesize": 1987444736, - "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" - } - - ], - "versions": [ - { - "name": "6.1.0 (ESX)", - "images": { - "hda_disk_image": "PA-VM-ESX-6.1.0-disk1.vmdk" - } - }, - { - "name": "7.1.0", - "images": { - "hda_disk_image": "PA-VM-KVM-7.1.0.qcow2" - } - }, - { - "name": "7.1.0 (ESX)", - "images": { - "hda_disk_image": "PA-VM-ESX-7.1.0-disk1.vmdk" - } - }, - { - "name": "8.0.0", - "images": { - "hda_disk_image": "PA-VM-KVM-8.0.0.qcow2" - } - } - ] -} +{ + "name": "PA-VM", + "category": "firewall", + "description": "The VM-Series combines next-generation firewall security and advanced threat prevention to protect your virtualized environments from advanced cyberthreats. The VM-Series natively analyzes all traffic in a single pass to determine the application identity, the content within, and the user identity.", + "vendor_name": "Palo Alto Networks", + "vendor_url": "http://www.paloaltonetworks.com/", + "documentation_url": "https://www.paloaltonetworks.com/documentation/80/virtualization/virtualization", + "product_name": "PAN VM-Series Firewall", + "product_url": "https://www.paloaltonetworks.com/products/secure-the-network/virtualized-next-generation-firewall/vm-series", + "registry_version": 3, + "status": "experimental", + "maintainer": "Community", + "maintainer_email": "", + "usage": "Default Username: admin\r\nDefault Password: admin\r\nPAN-VM goes through several iterations of host prompts during boot. This is normal and expected.\r\nLogin is available when prompt is PA-VM login:\r\n\r\nGetting Started:\r\nTo configure a static IP address at the console enter the following commands:\r\n\r\nconfigure\r\nset deviceconfig system ip-address netmask default-gateway type static\r\nset deviceconfig system dns-setting servers primary secondary \r\ncommit\r\n", + "symbol": "pan-vm-fw.svg", + "first_port_name": "management", + "port_name_format": "ethernet1/{port1}", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 25, + "ram": 4096, + "arch": "x86_64", + "console_type": "telnet", + "hda_disk_interface": "virtio", + "kvm": "require", + "options": "-smp 2" + }, + "images": [ + { + "filename": "PA-VM-ESX-8.1.0-disk1.vmdk", + "version": "8.1.0", + "md5sum": "49af8e8225c2e90414bde0be15eaf421", + "filesize": 2281454080, + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" + }, + { + "filename": "PA-VM-KVM-8.1.0.qcow2", + "version": "8.1.0", + "md5sum": "459558515b965b2e43fde2842abbae66", + "filesize": 2260467712, + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" + }, + { + "filename": "PA-VM-ESX-8.0.0-disk1.vmdk", + "version": "8.0.0", + "md5sum": "a505fb1dbcc855ecf98630fd5d329f9a", + "filesize": 2002713088, + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" + }, + { + "filename": "PA-VM-KVM-8.0.0.qcow2", + "version": "8.0.0", + "md5sum": "b6a1ddc8552aff87f05f9c0d4cb54dc3", + "filesize": 1987444736, + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" + }, + { + "filename": "PA-VM-ESX-7.1.0-disk1.vmdk", + "version": "7.1.0 (ESX)", + "md5sum": "e044dc649b7146ee4f619edb0e5f6675", + "filesize": 1871149056, + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" + }, + { + "filename": "PA-VM-KVM-7.1.0.qcow2", + "version": "7.1.0", + "md5sum": "da300253709740068927408239c2e321", + "filesize": 1858797568, + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" + }, + { + "filename": "PA-VM-ESX-6.1.0-disk1.vmdk", + "version": "6.1.0 (ESX)", + "md5sum": "64b1e81cd54008318235832ea6d71424", + "filesize": 2959736832, + "download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/" + } + ], + "versions": [ + { + "name": "8.1.0 (ESX)", + "images": { + "hda_disk_image": "PA-VM-ESX-8.1.0-disk1.vmdk" + } + }, + { + "name": "8.1.0", + "images": { + "hda_disk_image": "PA-VM-KVM-8.1.0.qcow2" + } + }, + { + "name": "8.0.0 (ESX)", + "images": { + "hda_disk_image": "PA-VM-ESX-8.0.0-disk1.vmdk" + } + }, + { + "name": "8.0.0", + "images": { + "hda_disk_image": "PA-VM-KVM-8.0.0.qcow2" + } + }, + { + "name": "7.1.0 (ESX)", + "images": { + "hda_disk_image": "PA-VM-ESX-7.1.0-disk1.vmdk" + } + }, + { + "name": "7.1.0", + "images": { + "hda_disk_image": "PA-VM-KVM-7.1.0.qcow2" + } + }, + { + "name": "6.1.0 (ESX)", + "images": { + "hda_disk_image": "PA-VM-ESX-6.1.0-disk1.vmdk" + } + } + ] +} diff --git a/gns3server/appliances/parrot-os.gns3a b/gns3server/appliances/parrot-os.gns3a new file mode 100644 index 00000000..1146ed32 --- /dev/null +++ b/gns3server/appliances/parrot-os.gns3a @@ -0,0 +1,53 @@ +{ + "name": "ParrotOS", + "category": "guest", + "description": " Parrot is a GNU/Linux distribution based on Debian Testing and designed with Security, Development and Privacy in mind. It includes a full portable laboratory for security and digital forensics experts, but it also includes all you need to develop your own software or protect your privacy while surfing the net.", + "vendor_name": "Parrot Project", + "vendor_url": "https://parrotsec.org/", + "documentation_url": "https://docs.parrotsec.org/doku.php", + "product_name": "ParrotOS", + "product_url": "https://parrotsec.org/", + "registry_version": 3, + "status": "stable", + "maintainer": "Brent Stewart", + "maintainer_email": "brent@stewart.tc", + "usage": "Passwords are set during installation.", + "symbol": "parrotlogo.png", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "ram": 2048, + "arch": "x86_64", + "console_type": "vnc", + "kvm": "require" + }, + "images": [ + { + "filename": "Parrot-security-3.11_amd64.iso", + "version": "Security Build 3.11", + "md5sum": "71c94474fb474f682da0844d95f0040b", + "filesize": 3788668928, + "download_url": "https://www.parrotsec.org/download.fx", + "direct_download_url": "https://www.parrotsec.org/download-full.fx" + }, + { + "filename": "empty30G.qcow2", + "version": "1.0", + "md5sum": "3411a599e822f2ac6be560a26405821a", + "filesize": 197120, + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%30disk/", + "direct_download_url": "http://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download" + } + + ], + "versions": [ + { + "name": "Security Build 3.11", + "images": { + "hda_disk_image": "empty30G.qcow2", + "cdrom_image": "Parrot-security-3.11_amd64.iso" + } + } + +] +} diff --git a/gns3server/appliances/pfsense.gns3a b/gns3server/appliances/pfsense.gns3a index 38ac6b6d..ae66160b 100644 --- a/gns3server/appliances/pfsense.gns3a +++ b/gns3server/appliances/pfsense.gns3a @@ -2,117 +2,50 @@ "name": "pfSense", "category": "firewall", "description": "The pfSense project is a free network firewall distribution, based on the FreeBSD operating system with a custom kernel and including third party free software packages for additional functionality. pfSense software, with the help of the package system, is able to provide the same functionality or more of common commercial firewalls, without any of the artificial limitations. It has successfully replaced every big name commercial firewall you can imagine in numerous installations around the world, including Check Point, Cisco PIX, Cisco ASA, Juniper, Sonicwall, Netgear, Watchguard, Astaro, and more.", - "vendor_name": "Electric Sheep Fencing LLC", + "vendor_name": "Rubicon Communications, LLC (Netgate)", "vendor_url": "https://www.pfsense.org", "documentation_url": "https://doc.pfsense.org/index.php/Main_Page", "product_name": "pfSense", "registry_version": 3, "status": "stable", - "maintainer": "GNS3 Team", - "maintainer_email": "developers@gns3.net", + "maintainer": "Jose Phillips", + "maintainer_email": "jose@latinol.com", + "usage": "Credentials: admin / pfsense\nTo install pfSense use all the defaults settings.\n\nNote:The default LAN port is em1.", "port_name_format": "em{0}", "qemu": { "adapter_type": "e1000", "adapters": 6, "ram": 2048, "arch": "x86_64", - "console_type": "telnet", - "boot_priority": "dc", + "console_type": "vnc", + "hda_disk_interface": "virtio", "kvm": "allow", "process_priority": "normal" }, "images": [ { - "filename": "pfSense-CE-2.3.5-RELEASE-2g-amd64-nanobsd.img", - "version": "2.3.5", - "md5sum": "b6cb76adba3e1113892f84ea01894228", - "filesize": 1989969408, + "filename": "pfSense-CE-2.4.4-RELEASE-amd64.iso", + "version": "2.4.4", + "md5sum": "71386433238f96fc167d14cec9c708c6", + "filesize": 685557760, "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads" }, { - "filename": "pfSense-CE-2.3.4-RELEASE-2g-amd64-nanobsd.img", - "version": "2.3.4", - "md5sum": "0c9871b54f932be2d550908f7c23b302", - "filesize": 1989969408, - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads" - }, - { - "filename": "pfSense-CE-2.3.3-RELEASE-2g-amd64-nanobsd.img", - "version": "2.3.3", - "md5sum": "200f073c4f0a4ba6690920079f23d5dd", - "filesize": 1989969408, - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads" - }, - { - "filename": "pfSense-CE-2.3.2-RELEASE-2g-amd64-nanobsd.img", - "version": "2.3.2", - "md5sum": "c91f2c8e287f4930695e65a6793cb8fe", - "filesize": 1989969408, - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads" - }, - { - "filename": "pfSense-CE-2.3.1-RELEASE-2g-amd64-nanobsd.img", - "version": "2.3.1", - "md5sum": "719149eed51e03872a8cfd235d958d2e", - "filesize": 1989969408, - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads" - }, - { - "filename": "pfSense-CE-2.3-RELEASE-2g-amd64-nanobsd.img", - "version": "2.3", - "md5sum": "8ab5047bd4c5bbabf71055fb75177d85", - "filesize": 1989969408, - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads" - }, - { - "filename": "pfSense-2.2.6-RELEASE-1g-amd64-nanobsd.img", - "version": "2.2.6", - "md5sum": "7bbe39c4ec698685c9f9b615926820a9", - "filesize": 997097472, - "download_url": "https://www.pfsense.org/download/mirror.php?section=downloads" + "filename": "empty100G.qcow2", + "version": "1.0", + "md5sum": "1e6409a4523ada212dea2ebc50e50a65", + "filesize": 197120, + "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/", + "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download" } + ], "versions": [ { - "name": "2.3.5", + "name": "2.4.4", "images": { - "hda_disk_image": "pfSense-CE-2.3.5-RELEASE-2g-amd64-nanobsd.img" - } - }, - { - "name": "2.3.4", - "images": { - "hda_disk_image": "pfSense-CE-2.3.4-RELEASE-2g-amd64-nanobsd.img" - } - }, - { - "name": "2.3.3", - "images": { - "hda_disk_image": "pfSense-CE-2.3.3-RELEASE-2g-amd64-nanobsd.img" - } - }, - { - "name": "2.3.2", - "images": { - "hda_disk_image": "pfSense-CE-2.3.2-RELEASE-2g-amd64-nanobsd.img" - } - }, - { - "name": "2.3.1", - "images": { - "hda_disk_image": "pfSense-CE-2.3.1-RELEASE-2g-amd64-nanobsd.img" - } - }, - { - "name": "2.3", - "images": { - "hda_disk_image": "pfSense-CE-2.3-RELEASE-2g-amd64-nanobsd.img" - } - }, - { - "name": "2.2.6", - "images": { - "hda_disk_image": "pfSense-2.2.6-RELEASE-1g-amd64-nanobsd.img" + "hda_disk_image": "empty100G.qcow2", + "cdrom_image": "pfSense-CE-2.4.4-RELEASE-amd64.iso" } } ] diff --git a/gns3server/appliances/proxmox-mg.gns3a b/gns3server/appliances/proxmox-mg.gns3a index 56d2a774..2f00d6e6 100644 --- a/gns3server/appliances/proxmox-mg.gns3a +++ b/gns3server/appliances/proxmox-mg.gns3a @@ -24,6 +24,14 @@ "kvm": "require" }, "images": [ + { + "filename": "proxmox-mailgateway_5.1-1.iso", + "version": "5.1-1", + "md5sum": "e629d5ff3213ff3ffbe5a8ab8ef87489", + "filesize": 724660224, + "download_url": "http://www.proxmox.com/en/downloads", + "direct_download_url": "https://www.proxmox.com/en/downloads?task=callelement&format=raw&item_id=415&element=f85c494b-2b32-4109-b8c1-083cca2b7db6&method=download&args[0]=7348486df9daacc8bd891a1d7ef1e5cb" + }, { "filename": "proxmox-mailgateway_4.1-5.iso", "version": "4.1-5", @@ -42,6 +50,13 @@ } ], "versions": [ + { + "name": "5.1-1", + "images": { + "hda_disk_image": "empty30G.qcow2", + "cdrom_image": "proxmox-mailgateway_5.1-1.iso" + } + }, { "name": "4.1-5", "images": { diff --git a/gns3server/appliances/python-go-perl-php.gns3a b/gns3server/appliances/python-go-perl-php.gns3a index 0a31376a..0e229881 100644 --- a/gns3server/appliances/python-go-perl-php.gns3a +++ b/gns3server/appliances/python-go-perl-php.gns3a @@ -11,6 +11,6 @@ "maintainer_email": "developers@gns3.net", "docker": { "adapters": 1, - "image": "gns3/python-go-perl-php:latest" + "image": "adosztal/python-go-perl-php:latest" } } diff --git a/gns3server/appliances/security-onion.gns3a b/gns3server/appliances/security-onion.gns3a index c2011f4d..f894fbe1 100644 --- a/gns3server/appliances/security-onion.gns3a +++ b/gns3server/appliances/security-onion.gns3a @@ -22,12 +22,20 @@ "kvm": "allow" }, "images": [ + { + "filename": "securityonion-16.04.5.3.iso", + "version": "16.04.5.3", + "md5sum": "886b369548c9c3841bc820cc3ab02bd9", + "filesize": 1895825408, + "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/", + "direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v16.04.5.3_20181010/securityonion-16.04.5.3.iso" + }, { "filename": "securityonion-14.04.5.4.iso", "version": "14.04.5.4", "md5sum": "9c7cab756b675beb10de4274a3ad3bc6", "filesize": 1874853888, - "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.4.iso", + "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/", "direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.4.iso" }, { @@ -35,7 +43,7 @@ "version": "14.04.5.3", "md5sum": "fb80ccb2d3c0f3f511823fa5858f87d1", "filesize": 1889533952, - "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.3.iso", + "download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/", "direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.3.iso" }, { @@ -49,6 +57,13 @@ ], "versions": [ + { + "name": "16.04.5.3", + "images": { + "hda_disk_image": "empty30G.qcow2", + "cdrom_image": "securityonion-16.04.5.3.iso" + } + }, { "name": "14.04.5.4", "images": { diff --git a/gns3server/appliances/sophos-iview.gns3a b/gns3server/appliances/sophos-iview.gns3a index 0ef5a699..59670f7a 100644 --- a/gns3server/appliances/sophos-iview.gns3a +++ b/gns3server/appliances/sophos-iview.gns3a @@ -24,6 +24,13 @@ "kvm": "require" }, "images": [ + { + "filename": "VI-SIVOS_03.01.2.KVM-009-PRIMARY.qcow2", + "version": "3.1.2", + "md5sum": "62551f70f71e08283d3a23929321eba9", + "filesize": 644218880, + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx" + }, { "filename": "VI-SIVOS_02.00.0_MR-2.KVM-776-PRIMARY.qcow2", "version": "2.0.0 MR2", @@ -32,7 +39,7 @@ "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx" }, { - "filename": "VI-SIVOS_02.00.0_MR-2.KVM-776-AUXILARY.qcow2", + "filename": "VI-SIVOS-AUXILARY.qcow2", "version": "2.0.0 MR2", "md5sum": "a52d8cedb1ccd4b5b9f2723dfb41588b", "filesize": 204800, @@ -40,11 +47,18 @@ } ], "versions": [ + { + "name": "3.1.2", + "images": { + "hda_disk_image": "VI-SIVOS_03.01.2.KVM-009-PRIMARY.qcow2", + "hdb_disk_image": "VI-SIVOS-AUXILARY.qcow2" + } + }, { "name": "2.0.0 MR2", "images": { "hda_disk_image": "VI-SIVOS_02.00.0_MR-2.KVM-776-PRIMARY.qcow2", - "hdb_disk_image": "VI-SIVOS_02.00.0_MR-2.KVM-776-AUXILARY.qcow2" + "hdb_disk_image": "VI-SIVOS-AUXILARY.qcow2" } } ] diff --git a/gns3server/appliances/sophos-utm.gns3a b/gns3server/appliances/sophos-utm.gns3a index 30584d40..431e991c 100644 --- a/gns3server/appliances/sophos-utm.gns3a +++ b/gns3server/appliances/sophos-utm.gns3a @@ -24,6 +24,13 @@ "kvm": "allow" }, "images": [ + { + "filename": "asg-9.510-5.1.iso", + "version": "9.510-5.1", + "md5sum": "ae21f96686f238c25941fd3240c7da5b", + "filesize": 871266304, + "download_url": "https://www.sophos.com/en-us/support/utm-downloads.aspx" + }, { "filename": "asg-9.506-2.1.iso", "version": "9.506-2.1", @@ -139,6 +146,13 @@ } ], "versions": [ + { + "name": "9.510-5.1", + "images": { + "hda_disk_image": "empty30G.qcow2", + "cdrom_image": "asg-9.510-5.1.iso" + } + }, { "name": "9.506-2.1", "images": { diff --git a/gns3server/appliances/sophos-xg.gns3a b/gns3server/appliances/sophos-xg.gns3a index d190ee48..e17a9b67 100644 --- a/gns3server/appliances/sophos-xg.gns3a +++ b/gns3server/appliances/sophos-xg.gns3a @@ -23,6 +23,20 @@ "kvm": "require" }, "images": [ + { + "filename": "VI-17.1.3_MR-3.KVM-250-PRIMARY.qcow2", + "version": "17.1.3 MR3", + "md5sum": "f11c4f63656bcdacbd27c44c52416941", + "filesize": 298844160, + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx" + }, + { + "filename": "VI-17.1.3_MR-3.KVM-250-AUXILARY.qcow2", + "version": "17.1.3 MR3", + "md5sum": "fbea59f7aa81f305bea78c86f82dc3a6", + "filesize": 59441152, + "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx" + }, { "filename": "VI-SFOS_17.0.2_MR-2.KVM-116-PRIMARY.qcow2", "version": "17.0.2 MR2", @@ -32,7 +46,7 @@ }, { "filename": "VI-SFOS_17.0.2_MR-2.KVM-116-AUXILARY.qcow2", - "version": "16.05.1 MR1", + "version": "17.0.2 MR2", "md5sum": "c3ef795423dbfc01771348b0daa75125", "filesize": 59441152, "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx" @@ -46,7 +60,7 @@ }, { "filename": "VI-SFOS_16.05.4_MR-4.KVM-215-AUXILARY.qcow2", - "version": "16.05.1 MR1", + "version": "16.05.4 MR4", "md5sum": "cafac2d997a3ead087d5823b86ce6cb4", "filesize": 59441152, "download_url": "https://secure2.sophos.com/en-us/products/next-gen-firewall/free-trial.aspx" @@ -109,6 +123,13 @@ } ], "versions": [ + { + "name": "17.1.3 MR3", + "images": { + "hda_disk_image": "VI-17.1.3_MR-3.KVM-250-PRIMARY.qcow2", + "hdb_disk_image": "VI-17.1.3_MR-3.KVM-250-AUXILARY.qcow2" + } + }, { "name": "17.0.2 MR2", "images": { diff --git a/gns3server/appliances/tacacs-gui.gns3a b/gns3server/appliances/tacacs-gui.gns3a new file mode 100644 index 00000000..c135df72 --- /dev/null +++ b/gns3server/appliances/tacacs-gui.gns3a @@ -0,0 +1,43 @@ +{ + "name": "TacacsGUI", + "category": "guest", + "description": "TacacsGUI Free Access Control Server for Your Network Devices. GUI for powerful daemon. The project of Alexey Mochalin, based on tacacs daemon by Marc Huber", + "vendor_name": "TacacsGUI", + "vendor_url": "https://tacacsgui.com/", + "documentation_url": "https://tacacsgui.com/documentation/", + "product_name": "TacacsGUI", + "product_url": "https://drive.google.com/open?id=1U8tbj14NqEyCmarayhZm54qTyjgsJm4B", + "registry_version": 3, + "status": "stable", + "maintainer": "GNS3 Team", + "maintainer_email": "developers@gns3.net", + "usage": "Credentials: SSH ---> username: root ---> password: 1234 MySQL DB: ---> username: root --> password: tacacs Web interface: ---> username: tacgui ---> password: abc123", + "port_name_format": "Port{port1}", + "qemu": { + "adapter_type": "e1000", + "adapters": 1, + "ram": 1024, + "hda_disk_interface": "ide", + "arch": "x86_64", + "console_type": "telnet", + "boot_priority": "c", + "kvm": "allow" + }, + "images": [ + { + "filename": "tac_plus.qcow2", + "version": "201710201114", + "md5sum": "6b5e66590051124dae586b8640b2eb11", + "filesize": 160301056, + "download_url": "https://drive.google.com/open?id=1U8tbj14NqEyCmarayhZm54qTyjgsJm4B" + } + ], + "versions": [ + { + "name": "201710201114", + "images": { + "hda_disk_image": "tac_plus.qcow2" + } + } + ] +} diff --git a/gns3server/appliances/turnkey-wordpress.gns3a b/gns3server/appliances/turnkey-wordpress.gns3a index bb8a13b9..978f49fb 100644 --- a/gns3server/appliances/turnkey-wordpress.gns3a +++ b/gns3server/appliances/turnkey-wordpress.gns3a @@ -13,7 +13,7 @@ "usage": "For security reasons there are no default passwords. All passwords are set at system initialization time.", "docker": { "adapters": 1, - "image": "turnkeylinux/wordpress-14.2:latest", + "image": "turnkeylinux/wordpress:latest", "console_type": "telnet" } } diff --git a/gns3server/appliances/ubuntu-cloud.gns3a b/gns3server/appliances/ubuntu-cloud.gns3a index e8bb8040..67fe81f7 100644 --- a/gns3server/appliances/ubuntu-cloud.gns3a +++ b/gns3server/appliances/ubuntu-cloud.gns3a @@ -26,53 +26,53 @@ }, "images": [ { - "filename": "ubuntu-17.10-server-cloudimg-amd64.img", - "version": "17.10", - "md5sum": "5d221878d8b2e49c5de7ebb58a2b35e3", - "filesize": 318373888, - "download_url": "https://cloud-images.ubuntu.com/releases/17.10/release/" + "filename": "ubuntu-18.04-server-cloudimg-amd64.img", + "version": "18.04", + "md5sum": "f4134e7fa16d7fa766c7467cbe25c949", + "filesize": 336134144, + "download_url": "https://cloud-images.ubuntu.com/releases/18.04/release-20180426.2/ubuntu-18.04-server-cloudimg-amd64.img" }, { - "filename": "ubuntu-17.04-server-cloudimg-amd64.img", - "version": "17.04", - "md5sum": "d4da8157dbf2e64f2fa1fb5d121398e5", - "filesize": 351993856, - "download_url": "https://cloud-images.ubuntu.com/releases/17.04/release/" + "filename": "ubuntu-17.10-server-cloudimg-amd64.img", + "version": "17.10", + "md5sum": "331b44f2b05858c251b3ea92c8b65152", + "filesize": 320405504, + "download_url": "https://cloud-images.ubuntu.com/releases/17.10/release-20180404/ubuntu-17.10-server-cloudimg-amd64.img" }, { "filename": "ubuntu-16.04-server-cloudimg-amd64-disk1.img", - "version": "16.04.3", - "md5sum": "bd0c168a83b1f483bd240b3d874edd6c", - "filesize": 288686080, - "download_url": "https://cloud-images.ubuntu.com/releases/16.04/release/" + "version": "16.04", + "md5sum": "22c124ba65ea096cdef8b0a197dd613a", + "filesize": 290193408, + "download_url": "https://cloud-images.ubuntu.com/releases/16.04/release-20180405/ubuntu-16.04-server-cloudimg-amd64-disk1.img" }, { "filename": "ubuntu-14.04-server-cloudimg-amd64-disk1.img", - "version": "14.04.5", - "md5sum": "d7b4112c7d797e5e77ef9995d06a76f1", - "filesize": 262406656, - "download_url": "https://cloud-images.ubuntu.com/releases/14.04/release/" + "version": "14.04", + "md5sum": "d11b89321d41d0eeddcacf73bf0d2262", + "filesize": 262668800, + "download_url": "https://cloud-images.ubuntu.com/releases/14.04/release-20180404/ubuntu-14.04-server-cloudimg-amd64-disk1.img" }, { "filename": "ubuntu-cloud-init-data.iso", "version": "1.0", "md5sum": "328469100156ae8dbf262daa319c27ff", "filesize": 131072, - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/ubuntu-cloud-init-data.iso/download" + "download_url": "https://github.com/asenci/gns3-ubuntu-cloud-init-data/raw/master/ubuntu-cloud-init-data.iso" } ], "versions": [ { - "name": "17.10", + "name": "18.04 (LTS)", "images": { - "hda_disk_image": "ubuntu-17.10-server-cloudimg-amd64.img", + "hda_disk_image": "ubuntu-18.04-server-cloudimg-amd64.img", "cdrom_image": "ubuntu-cloud-init-data.iso" } }, { - "name": "17.04", + "name": "17.10", "images": { - "hda_disk_image": "ubuntu-17.04-server-cloudimg-amd64.img", + "hda_disk_image": "ubuntu-17.10-server-cloudimg-amd64.img", "cdrom_image": "ubuntu-cloud-init-data.iso" } }, diff --git a/gns3server/appliances/untangle.gns3a b/gns3server/appliances/untangle.gns3a index 6c26cac7..26958027 100644 --- a/gns3server/appliances/untangle.gns3a +++ b/gns3server/appliances/untangle.gns3a @@ -24,6 +24,27 @@ "kvm": "allow" }, "images": [ + { + "filename": "untangle_1410_x64.iso", + "version": "14.1.0", + "md5sum": "49bb09e4796f225f482ca1d9c93de66b", + "filesize": 682622976, + "download_url": "https://www.untangle.com/get-untangle/" + }, + { + "filename": "untangle_1401_x64.iso", + "version": "14.0.1", + "md5sum": "d9c01afd8bf4b5dfdc40c22aa3b2fd98", + "filesize": 680525824, + "download_url": "https://www.untangle.com/get-untangle/" + }, + { + "filename": "untangle_1321_x64.iso", + "version": "13.2.1", + "md5sum": "4ce49535372f85565922c7e90bc11ba3", + "filesize": 627048448, + "download_url": "https://www.untangle.com/get-untangle/" + }, { "filename": "untangle_1320_x64.iso", "version": "13.2.0", @@ -97,6 +118,27 @@ } ], "versions": [ + { + "name": "14.1.0", + "images": { + "hda_disk_image": "empty30G.qcow2", + "cdrom_image": "untangle_1410_x64.iso" + } + }, + { + "name": "14.0.1", + "images": { + "hda_disk_image": "empty30G.qcow2", + "cdrom_image": "untangle_1401_x64.iso" + } + }, + { + "name": "13.2.1", + "images": { + "hda_disk_image": "empty30G.qcow2", + "cdrom_image": "untangle_1321_x64.iso" + } + }, { "name": "13.2.0", "images": { diff --git a/gns3server/appliances/vpp.gns3a b/gns3server/appliances/vpp.gns3a new file mode 100644 index 00000000..cbd39997 --- /dev/null +++ b/gns3server/appliances/vpp.gns3a @@ -0,0 +1,46 @@ +{ + "name": "VPP", + "category": "router", + "description": "Vector Packet Processing (VPP) platform", + "vendor_name": "FD.IO VPP router", + "vendor_url": "https://fd.io/", + "documentation_url": "https://fd.io/resources/", + "product_name": "VPP", + "registry_version": 4, + "status": "experimental", + "availability": "free", + "maintainer": "Virginijus Magelinskas", + "maintainer_email": "virginijus.m@gmail.com", + "usage": "Login: root , pass: vpp. This appliance requires >2 vCPUs and 4GB of RAM to run", + "port_name_format": "eth{0}", + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 5, + "ram": 4096, + "hda_disk_interface": "ide", + "arch": "x86_64", + "console_type": "telnet", + "boot_priority": "c", + "kvm": "require", + "options": "-nographic -cpu host -smp 2" + }, + "images": [ + { + "filename": "vpp_public-18.10-07.qcow2", + "version": "0.7", + "md5sum": "3e962985e5bbda0de4dc7893e60f6366", + "filesize": 2065825792, + "direct_download_url": "https://sigaba.net/vpp/vpp_public-18.10-07.qcow2" + } + ], + "versions": [ + + { + "name": "18.10-07", + "images": { + "hda_disk_image": "vpp_public-18.10-07.qcow2" + } + } + ] +} + diff --git a/gns3server/appliances/vyos.gns3a b/gns3server/appliances/vyos.gns3a index fc68dedd..7e3cd601 100644 --- a/gns3server/appliances/vyos.gns3a +++ b/gns3server/appliances/vyos.gns3a @@ -80,6 +80,13 @@ "cdrom_image": "vyos-1.2.0-beta1-amd64.iso" } }, + { + "name": "1.1.8", + "images": { + "hda_disk_image": "empty8G.qcow2", + "cdrom_image": "vyos-1.1.8-amd64.iso" + } + }, { "name": "1.1.7", "images": { diff --git a/gns3server/appliances/windows.gns3a b/gns3server/appliances/windows.gns3a index ac84deee..d8c0dc83 100644 --- a/gns3server/appliances/windows.gns3a +++ b/gns3server/appliances/windows.gns3a @@ -27,10 +27,10 @@ }, "images": [ { - "filename": "MSEdge-Win10-VMWare-disk1.vmdk", + "filename": "MSEdge-Win10-VMware-disk1.vmdk", "version": "10 w/ Edge", - "md5sum": "fef74c69e1949480d4e2095324a169af", - "filesize": 5636608512, + "md5sum": "670f3c2b03a5629dc85d0d1c261e5929", + "filesize": 7293386240, "download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/" }, { @@ -80,7 +80,7 @@ { "name": "10 w/ Edge", "images": { - "hda_disk_image": "MSEdge-Win10-VMWare-disk1.vmdk" + "hda_disk_image": "MSEdge-Win10-VMware-disk1.vmdk" } }, { diff --git a/gns3server/appliances/zentyal-server.gns3a b/gns3server/appliances/zentyal-server.gns3a index 49cb6caa..1370eeec 100644 --- a/gns3server/appliances/zentyal-server.gns3a +++ b/gns3server/appliances/zentyal-server.gns3a @@ -24,6 +24,22 @@ "kvm": "require" }, "images": [ + { + "filename": "zentyal-6.0-development-amd64.iso", + "version": "6.0", + "md5sum": "e1765d2c4d86debc9d9cbab2b7a8adbd", + "filesize": 895483904, + "download_url": "http://download.zentyal.com/", + "direct_download_url": "http://download.zentyal.com/zentyal-6.0-development-amd64.iso" + }, + { + "filename": "zentyal-5.1-development-amd64.iso", + "version": "5.1", + "md5sum": "dac5623b92c1b361d7805ab8c95c0d99", + "filesize": 947912704, + "download_url": "http://download.zentyal.com/", + "direct_download_url": "http://download.zentyal.com/zentyal-5.1-development-amd64.iso" + }, { "filename": "zentyal-5.0.1-development-amd64.iso", "version": "5.0.1", @@ -74,6 +90,20 @@ } ], "versions": [ + { + "name": "6.0", + "images": { + "hda_disk_image": "empty100G.qcow2", + "cdrom_image": "zentyal-6.0-development-amd64.iso" + } + }, + { + "name": "5.1", + "images": { + "hda_disk_image": "empty100G.qcow2", + "cdrom_image": "zentyal-5.1-development-amd64.iso" + } + }, { "name": "5.0.1", "images": { diff --git a/gns3server/compute/__init__.py b/gns3server/compute/__init__.py index 5d454a86..7de7eac9 100644 --- a/gns3server/compute/__init__.py +++ b/gns3server/compute/__init__.py @@ -24,15 +24,14 @@ from .virtualbox import VirtualBox from .dynamips import Dynamips from .qemu import Qemu from .vmware import VMware +from .traceng import TraceNG -MODULES = [Builtin, VPCS, VirtualBox, Dynamips, Qemu, VMware] +MODULES = [Builtin, VPCS, VirtualBox, Dynamips, Qemu, VMware, TraceNG] if sys.platform.startswith("linux") or hasattr(sys, "_called_from_test") or os.environ.get("PYTEST_BUILD_DOCUMENTATION") == "1": - - from .docker import Docker - MODULES.append(Docker) - - # IOU runs only on Linux but testsuite work on UNIX platform + # IOU & Docker only runs on Linux but test suite works on UNIX platform if not sys.platform.startswith("win"): + from .docker import Docker + MODULES.append(Docker) from .iou import IOU MODULES.append(IOU) diff --git a/gns3server/compute/base_manager.py b/gns3server/compute/base_manager.py index f383a197..0eb6426a 100644 --- a/gns3server/compute/base_manager.py +++ b/gns3server/compute/base_manager.py @@ -20,12 +20,17 @@ import os import struct import stat import asyncio +import aiofiles + import aiohttp import socket import shutil import re import logging + +from gns3server.utils.asyncio import cancellable_wait_run_in_executor + log = logging.getLogger(__name__) from uuid import UUID, uuid4 @@ -42,6 +47,8 @@ from .nios.nio_ethernet import NIOEthernet from ..utils.images import md5sum, remove_checksum, images_directories, default_images_directory, list_images from .error import NodeError, ImageMissingError +CHUNK_SIZE = 1024 * 8 # 8KB + class BaseManager: @@ -64,6 +71,7 @@ class BaseManager: """ :returns: Array of supported node type on this computer """ + # By default we transform DockerVM => docker but you can override this (see builtins) return [cls._NODE_CLASS.__name__.rstrip('VM').lower()] @@ -72,6 +80,7 @@ class BaseManager: """ List of nodes manage by the module """ + return self._nodes.values() @classmethod @@ -103,6 +112,7 @@ class BaseManager: :returns: Port manager """ + if self._port_manager is None: self._port_manager = PortManager.instance() return self._port_manager @@ -122,15 +132,14 @@ class BaseManager: return self._config - @asyncio.coroutine - def unload(self): + async def unload(self): tasks = [] for node_id in self._nodes.keys(): - tasks.append(asyncio.async(self.close_node(node_id))) + tasks.append(asyncio.ensure_future(self.close_node(node_id))) if tasks: - done, _ = yield from asyncio.wait(tasks) + done, _ = await asyncio.wait(tasks) for future in done: try: future.result() @@ -171,8 +180,7 @@ class BaseManager: return node - @asyncio.coroutine - def convert_old_project(self, project, legacy_id, name): + async def convert_old_project(self, project, legacy_id, name): """ Convert projects made before version 1.3 @@ -191,7 +199,7 @@ class BaseManager: log.info("Converting old project...") try: log.info('Moving "{}" to "{}"'.format(legacy_project_files_path, new_project_files_path)) - yield from wait_run_in_executor(shutil.move, legacy_project_files_path, new_project_files_path) + await wait_run_in_executor(shutil.move, legacy_project_files_path, new_project_files_path) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not move project files directory: {} to {} {}".format(legacy_project_files_path, new_project_files_path, e)) @@ -204,7 +212,7 @@ class BaseManager: log.info("Converting old remote project...") try: log.info('Moving "{}" to "{}"'.format(legacy_remote_project_path, new_remote_project_path)) - yield from wait_run_in_executor(shutil.move, legacy_remote_project_path, new_remote_project_path) + await wait_run_in_executor(shutil.move, legacy_remote_project_path, new_remote_project_path) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not move directory: {} to {} {}".format(legacy_remote_project_path, new_remote_project_path, e)) @@ -218,15 +226,14 @@ class BaseManager: if os.path.exists(legacy_vm_working_path) and not os.path.exists(new_vm_working_path): try: log.info('Moving "{}" to "{}"'.format(legacy_vm_working_path, new_vm_working_path)) - yield from wait_run_in_executor(shutil.move, legacy_vm_working_path, new_vm_working_path) + await wait_run_in_executor(shutil.move, legacy_vm_working_path, new_vm_working_path) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not move vm working directory: {} to {} {}".format(legacy_vm_working_path, new_vm_working_path, e)) return new_id - @asyncio.coroutine - def create_node(self, name, project_id, node_id, *args, **kwargs): + async def create_node(self, name, project_id, node_id, *args, **kwargs): """ Create a new node @@ -241,23 +248,22 @@ class BaseManager: project = ProjectManager.instance().get_project(project_id) if node_id and isinstance(node_id, int): # old project - with (yield from BaseManager._convert_lock): - node_id = yield from self.convert_old_project(project, node_id, name) + async with BaseManager._convert_lock: + node_id = await self.convert_old_project(project, node_id, name) if not node_id: node_id = str(uuid4()) node = self._NODE_CLASS(name, node_id, project, self, *args, **kwargs) if asyncio.iscoroutinefunction(node.create): - yield from node.create() + await node.create() else: node.create() self._nodes[node.id] = node project.add_node(node) return node - @asyncio.coroutine - def duplicate_node(self, source_node_id, destination_node_id): + async def duplicate_node(self, source_node_id, destination_node_id): """ Duplicate a node @@ -265,6 +271,7 @@ class BaseManager: :param destination_node_id: Destination node identifier :returns: New node instance """ + source_node = self.get_node(source_node_id) destination_node = self.get_node(destination_node_id) @@ -275,11 +282,11 @@ class BaseManager: destination_dir = destination_node.working_dir try: shutil.rmtree(destination_dir) - shutil.copytree(source_node.working_dir, destination_dir) + shutil.copytree(source_node.working_dir, destination_dir, symlinks=True, ignore_dangling_symlinks=True) except OSError as e: - raise aiohttp.web.HTTPConflict(text="Can't duplicate node data: {}".format(e)) + raise aiohttp.web.HTTPConflict(text="Cannot duplicate node data: {}".format(e)) - # We force a refresh of the name. This force the rewrite + # We force a refresh of the name. This forces the rewrite # of some configuration files node_name = destination_node.name destination_node.name = node_name + str(uuid4()) @@ -287,8 +294,7 @@ class BaseManager: return destination_node - @asyncio.coroutine - def close_node(self, node_id): + async def close_node(self, node_id): """ Close a node @@ -299,13 +305,12 @@ class BaseManager: node = self.get_node(node_id) if asyncio.iscoroutinefunction(node.close): - yield from node.close() + await node.close() else: node.close() return node - @asyncio.coroutine - def project_closing(self, project): + async def project_closing(self, project): """ Called when a project is about to be closed. @@ -314,8 +319,7 @@ class BaseManager: pass - @asyncio.coroutine - def project_closed(self, project): + async def project_closed(self, project): """ Called when a project is closed. @@ -326,8 +330,7 @@ class BaseManager: if node.id in self._nodes: del self._nodes[node.id] - @asyncio.coroutine - def delete_node(self, node_id): + async def delete_node(self, node_id): """ Delete a node. The node working directory will be destroyed when a commit is received. @@ -338,11 +341,11 @@ class BaseManager: node = None try: node = self.get_node(node_id) - yield from self.close_node(node_id) + await self.close_node(node_id) finally: if node: node.project.emit("node.deleted", node) - yield from node.project.remove_node(node) + await node.project.remove_node(node) if node.id in self._nodes: del self._nodes[node.id] return node @@ -409,8 +412,9 @@ class BaseManager: sock.connect(sa) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e)) - filters = nio_settings.get("filters", {}) - nio = NIOUDP(lport, rhost, rport, filters) + nio = NIOUDP(lport, rhost, rport) + nio.filters = nio_settings.get("filters", {}) + nio.suspend = nio_settings.get("suspend", False) elif nio_settings["type"] == "nio_tap": tap_device = nio_settings["tap_device"] # if not is_interface_up(tap_device): @@ -427,12 +431,52 @@ class BaseManager: assert nio is not None return nio - def get_abs_image_path(self, path): + async def stream_pcap_file(self, nio, project_id, request, response): + """ + Streams a PCAP file. + + :param nio: NIO object + :param project_id: Project identifier + :param request: request object + :param response: response object + """ + + if not nio.capturing: + raise aiohttp.web.HTTPConflict(text="Nothing to stream because there is no packet capture active") + + project = ProjectManager.instance().get_project(project_id) + path = os.path.normpath(os.path.join(project.capture_working_directory(), nio.pcap_output_file)) + # Raise an error if user try to escape + #if path[0] == ".": + # raise aiohttp.web.HTTPForbidden() + #path = os.path.join(project.path, path) + + response.content_type = "application/vnd.tcpdump.pcap" + response.set_status(200) + response.enable_chunked_encoding() + + try: + with open(path, "rb") as f: + await response.prepare(request) + while nio.capturing: + data = f.read(CHUNK_SIZE) + if not data: + await asyncio.sleep(0.1) + continue + await response.write(data) + except FileNotFoundError: + raise aiohttp.web.HTTPNotFound() + except PermissionError: + raise aiohttp.web.HTTPForbidden() + + def get_abs_image_path(self, path, extra_dir=None): """ Get the absolute path of an image :param path: file path - :return: file path + :param extra_dir: an additional directory to be added to the search path + + :returns: file path """ if not path: @@ -441,6 +485,9 @@ class BaseManager: server_config = self.config.get_section_config("Server") img_directory = self.get_images_directory() + valid_directory_prefices = images_directories(self._NODE_TYPE) + if extra_dir: + valid_directory_prefices.append(extra_dir) # Windows path should not be send to a unix server if not sys.platform.startswith("win"): @@ -448,7 +495,7 @@ class BaseManager: raise NodeError("{} is not allowed on this remote server. Please use only a filename in {}.".format(path, img_directory)) if not os.path.isabs(path): - for directory in images_directories(self._NODE_TYPE): + for directory in valid_directory_prefices: path = self._recursive_search_file_in_directory(directory, orig_path) if path: return force_unix_path(path) @@ -460,15 +507,16 @@ class BaseManager: return path raise ImageMissingError(orig_path) - # For non local server we disallow using absolute path outside image directory + # For local server we allow using absolute path outside image directory if server_config.getboolean("local", False) is True: path = force_unix_path(path) if os.path.exists(path): return path raise ImageMissingError(orig_path) + # Check to see if path is an absolute path to a valid directory path = force_unix_path(path) - for directory in images_directories(self._NODE_TYPE): + for directory in valid_directory_prefices: if os.path.commonprefix([directory, path]) == directory: if os.path.exists(path): return path @@ -492,23 +540,29 @@ class BaseManager: return path return None - def get_relative_image_path(self, path): + def get_relative_image_path(self, path, extra_dir=None): """ Get a path relative to images directory path or an abspath if the path is not located inside image directory :param path: file path - :return: file path + :param extra_dir: an additional directory to be added to the search path + + :returns: file path """ if not path: return "" - path = force_unix_path(self.get_abs_image_path(path)) + path = force_unix_path(self.get_abs_image_path(path, extra_dir)) img_directory = self.get_images_directory() - for directory in images_directories(self._NODE_TYPE): + valid_directory_prefices = images_directories(self._NODE_TYPE) + if extra_dir: + valid_directory_prefices.append(extra_dir) + + for directory in valid_directory_prefices: if os.path.commonprefix([directory, path]) == directory: relpath = os.path.relpath(path, directory) # We don't allow to recurse search from the top image directory just for image type directory (compatibility with old releases) @@ -516,8 +570,7 @@ class BaseManager: return relpath return path - @asyncio.coroutine - def list_images(self): + async def list_images(self): """ Return the list of available images for this node type @@ -533,31 +586,32 @@ class BaseManager: """ Get the image directory on disk """ + if hasattr(self, "_NODE_TYPE"): return default_images_directory(self._NODE_TYPE) raise NotImplementedError - @asyncio.coroutine - def write_image(self, filename, stream): + async def write_image(self, filename, stream): + directory = self.get_images_directory() path = os.path.abspath(os.path.join(directory, *os.path.split(filename))) if os.path.commonprefix([directory, path]) != directory: raise aiohttp.web.HTTPForbidden(text="Could not write image: {}, {} is forbidden".format(filename, path)) - log.info("Writing image file %s", path) + log.info("Writing image file to '{}'".format(path)) try: remove_checksum(path) # We store the file under his final name only when the upload is finished tmp_path = path + ".tmp" os.makedirs(os.path.dirname(path), exist_ok=True) - with open(tmp_path, 'wb') as f: + async with aiofiles.open(tmp_path, 'wb') as f: while True: - packet = yield from stream.read(4096) - if not packet: + chunk = await stream.read(CHUNK_SIZE) + if not chunk: break - f.write(packet) + await f.write(chunk) os.chmod(tmp_path, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC) shutil.move(tmp_path, path) - md5sum(path) + await cancellable_wait_run_in_executor(md5sum, path) except OSError as e: raise aiohttp.web.HTTPConflict(text="Could not write image: {} because {}".format(filename, e)) diff --git a/gns3server/compute/base_node.py b/gns3server/compute/base_node.py index c2a4e68e..3fae6e0f 100644 --- a/gns3server/compute/base_node.py +++ b/gns3server/compute/base_node.py @@ -29,7 +29,7 @@ import re from gns3server.utils.interfaces import interfaces from ..compute.port_manager import PortManager -from ..utils.asyncio import wait_run_in_executor, locked_coroutine +from ..utils.asyncio import wait_run_in_executor, locking from ..utils.asyncio.telnet_server import AsyncioTelnetServer from ..ubridge.hypervisor import Hypervisor from ..ubridge.ubridge_error import UbridgeError @@ -76,10 +76,16 @@ class BaseNode: self._allocate_aux = allocate_aux self._wrap_console = wrap_console self._wrapper_telnet_server = None + self._internal_console_port = None + self._custom_adapters = [] + self._ubridge_require_privileged_access = False if self._console is not None: if console_type == "vnc": + # VNC is a special case and the range must be 5900-6000 self._console = self._manager.port_manager.reserve_tcp_port(self._console, self._project, port_range_start=5900, port_range_end=6000) + elif console_type == "none": + self._console = None else: self._console = self._manager.port_manager.reserve_tcp_port(self._console, self._project) @@ -91,7 +97,7 @@ class BaseNode: if console_type == "vnc": # VNC is a special case and the range must be 5900-6000 self._console = self._manager.port_manager.get_free_tcp_port(self._project, port_range_start=5900, port_range_end=6000) - else: + elif console_type != "none": self._console = self._manager.port_manager.get_free_tcp_port(self._project) if self._wrap_console: @@ -119,6 +125,14 @@ class BaseNode: def linked_clone(self, val): self._linked_clone = val + @property + def custom_adapters(self): + return self._custom_adapters + + @custom_adapters.setter + def custom_adapters(self, val): + self._custom_adapters = val + @property def status(self): """ @@ -260,18 +274,18 @@ class BaseNode: name=self.name, id=self.id)) - @asyncio.coroutine - def delete(self): + async def delete(self): """ Delete the node (including all its files). """ + def set_rw(operation, name, exc): os.chmod(name, stat.S_IWRITE) directory = self.project.node_working_directory(self) if os.path.exists(directory): try: - yield from wait_run_in_executor(shutil.rmtree, directory, onerror=set_rw) + await wait_run_in_executor(shutil.rmtree, directory, onerror=set_rw) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not delete the node working directory: {}".format(e)) @@ -282,14 +296,12 @@ class BaseNode: raise NotImplementedError - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stop the node process. """ - if self._wrapper_telnet_server: - self._wrapper_telnet_server.close() - yield from self._wrapper_telnet_server.wait_closed() + + await self.stop_wrap_console() self.status = "stopped" def suspend(self): @@ -299,8 +311,7 @@ class BaseNode: raise NotImplementedError - @asyncio.coroutine - def close(self): + async def close(self): """ Close the node process. """ @@ -326,33 +337,44 @@ class BaseNode: self._closed = True return True - @asyncio.coroutine - def start_wrap_console(self): + async def start_wrap_console(self): """ Start a telnet proxy for the console allowing multiple client connected at the same time """ + if not self._wrap_console or self._console_type != "telnet": return remaining_trial = 60 while True: try: - (reader, writer) = yield from asyncio.open_connection(host="127.0.0.1", port=self._internal_console_port) + (reader, writer) = await asyncio.open_connection(host="127.0.0.1", port=self._internal_console_port) break except (OSError, ConnectionRefusedError) as e: if remaining_trial <= 0: raise e - yield from asyncio.sleep(0.1) + await asyncio.sleep(0.1) remaining_trial -= 1 - yield from AsyncioTelnetServer.write_client_intro(writer, echo=True) + await AsyncioTelnetServer.write_client_intro(writer, echo=True) server = AsyncioTelnetServer(reader=reader, writer=writer, binary=True, echo=True) - self._wrapper_telnet_server = yield from asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console) + # warning: this will raise OSError exception if there is a problem... + self._wrapper_telnet_server = await asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console) + + async def stop_wrap_console(self): + """ + Stops the telnet proxy. + """ + + if self._wrapper_telnet_server: + self._wrapper_telnet_server.close() + await self._wrapper_telnet_server.wait_closed() @property def allocate_aux(self): """ :returns: Boolean allocate or not an aux console """ + return self._allocate_aux @allocate_aux.setter @@ -360,6 +382,7 @@ class BaseNode: """ :returns: Boolean allocate or not an aux console """ + self._allocate_aux = allocate_aux @property @@ -411,11 +434,11 @@ class BaseNode: :params console: Console port (integer) or None to free the port """ - if console == self._console: + if console == self._console or self._console_type == "none": return if self._console_type == "vnc" and console is not None and console < 5900: - raise NodeError("VNC console require a port superior or equal to 5900 currently it's {}".format(console)) + raise NodeError("VNC console require a port superior or equal to 5900, current port is {}".format(console)) if self._console: self._manager.port_manager.release_tcp_port(self._console, self._project) @@ -451,18 +474,23 @@ class BaseNode: if console_type != self._console_type: # get a new port if the console type change - self._manager.port_manager.release_tcp_port(self._console, self._project) - if console_type == "vnc": + if self._console: + self._manager.port_manager.release_tcp_port(self._console, self._project) + if console_type == "none": + # no need to allocate a port when the console type is none + self._console = None + elif console_type == "vnc": # VNC is a special case and the range must be 5900-6000 self._console = self._manager.port_manager.get_free_tcp_port(self._project, 5900, 6000) else: self._console = self._manager.port_manager.get_free_tcp_port(self._project) self._console_type = console_type - log.info("{module}: '{name}' [{id}]: console type set to {console_type}".format(module=self.manager.module_name, - name=self.name, - id=self.id, - console_type=console_type)) + log.info("{module}: '{name}' [{id}]: console type set to {console_type} (console port is {console})".format(module=self.manager.module_name, + name=self.name, + id=self.id, + console_type=console_type, + console=self.console)) @property def ubridge(self): @@ -498,8 +526,7 @@ class BaseNode: path = shutil.which(path) return path - @asyncio.coroutine - def _ubridge_send(self, command): + async def _ubridge_send(self, command): """ Sends a command to uBridge hypervisor. @@ -507,16 +534,16 @@ class BaseNode: """ if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): - yield from self._start_ubridge() + await self._start_ubridge(self._ubridge_require_privileged_access) if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): raise NodeError("Cannot send command '{}': uBridge is not running".format(command)) try: - yield from self._ubridge_hypervisor.send(command) + await self._ubridge_hypervisor.send(command) except UbridgeError as e: - raise UbridgeError("{}: {}".format(e, self._ubridge_hypervisor.read_stdout())) + raise UbridgeError("Error while sending command '{}': {}: {}".format(command, e, self._ubridge_hypervisor.read_stdout())) - @locked_coroutine - def _start_ubridge(self): + @locking + async def _start_ubridge(self, require_privileged_access=False): """ Starts uBridge (handles connections to and from this node). """ @@ -528,7 +555,7 @@ class BaseNode: if self.ubridge_path is None: raise NodeError("uBridge is not available, path doesn't exist, or you just installed GNS3 and need to restart your user session to refresh user permissions.") - if not self._manager.has_privileged_access(self.ubridge_path): + if require_privileged_access and not self._manager.has_privileged_access(self.ubridge_path): raise NodeError("uBridge requires root access or the capability to interact with network adapters") server_config = self._manager.config.get_section_config("Server") @@ -536,24 +563,24 @@ class BaseNode: if not self.ubridge: self._ubridge_hypervisor = Hypervisor(self._project, self.ubridge_path, self.working_dir, server_host) log.info("Starting new uBridge hypervisor {}:{}".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port)) - yield from self._ubridge_hypervisor.start() + await self._ubridge_hypervisor.start() if self._ubridge_hypervisor: log.info("Hypervisor {}:{} has successfully started".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port)) - yield from self._ubridge_hypervisor.connect() + await self._ubridge_hypervisor.connect() + # save if privileged are required in case uBridge needs to be restarted in self._ubridge_send() + self._ubridge_require_privileged_access = require_privileged_access - @asyncio.coroutine - def _stop_ubridge(self): + async def _stop_ubridge(self): """ Stops uBridge. """ if self._ubridge_hypervisor and self._ubridge_hypervisor.is_running(): log.info("Stopping uBridge hypervisor {}:{}".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port)) - yield from self._ubridge_hypervisor.stop() + await self._ubridge_hypervisor.stop() self._ubridge_hypervisor = None - @asyncio.coroutine - def add_ubridge_udp_connection(self, bridge_name, source_nio, destination_nio): + async def add_ubridge_udp_connection(self, bridge_name, source_nio, destination_nio): """ Creates an UDP connection in uBridge. @@ -562,55 +589,55 @@ class BaseNode: :param destination_nio: destination NIO instance """ - yield from self._ubridge_send("bridge create {name}".format(name=bridge_name)) + await self._ubridge_send("bridge create {name}".format(name=bridge_name)) if not isinstance(destination_nio, NIOUDP): raise NodeError("Destination NIO is not UDP") - yield from self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name, + await self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name, lport=source_nio.lport, rhost=source_nio.rhost, rport=source_nio.rport)) - yield from self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name, + await self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name, lport=destination_nio.lport, rhost=destination_nio.rhost, rport=destination_nio.rport)) if destination_nio.capturing: - yield from self._ubridge_send('bridge start_capture {name} "{pcap_file}"'.format(name=bridge_name, + await self._ubridge_send('bridge start_capture {name} "{pcap_file}"'.format(name=bridge_name, pcap_file=destination_nio.pcap_output_file)) - yield from self._ubridge_send('bridge start {name}'.format(name=bridge_name)) - yield from self._ubridge_apply_filters(bridge_name, destination_nio.filters) + await self._ubridge_send('bridge start {name}'.format(name=bridge_name)) + await self._ubridge_apply_filters(bridge_name, destination_nio.filters) - @asyncio.coroutine - def update_ubridge_udp_connection(self, bridge_name, source_nio, destination_nio): + async def update_ubridge_udp_connection(self, bridge_name, source_nio, destination_nio): if destination_nio: - yield from self._ubridge_apply_filters(bridge_name, destination_nio.filters) + await self._ubridge_apply_filters(bridge_name, destination_nio.filters) - def ubridge_delete_bridge(self, name): + async def ubridge_delete_bridge(self, name): """ :params name: Delete the bridge with this name """ - if self.ubridge: - yield from self._ubridge_send("bridge delete {name}".format(name=name)) - @asyncio.coroutine - def _ubridge_apply_filters(self, bridge_name, filters): + if self.ubridge: + await self._ubridge_send("bridge delete {name}".format(name=name)) + + async def _ubridge_apply_filters(self, bridge_name, filters): """ Apply packet filters :param bridge_name: bridge name in uBridge :param filters: Array of filter dictionary """ - yield from self._ubridge_send('bridge reset_packet_filters ' + bridge_name) + + await self._ubridge_send('bridge reset_packet_filters ' + bridge_name) for packet_filter in self._build_filter_list(filters): cmd = 'bridge add_packet_filter {} {}'.format(bridge_name, packet_filter) try: - yield from self._ubridge_send(cmd) + await self._ubridge_send(cmd) except UbridgeError as e: - match = re.search("Cannot compile filter '(.*)': syntax error", str(e)) + match = re.search(r"Cannot compile filter '(.*)': syntax error", str(e)) if match: message = "Warning: ignoring BPF packet filter '{}' due to syntax error".format(self.name, match.group(1)) log.warning(message) @@ -622,6 +649,7 @@ class BaseNode: """ :returns: Iterator building a list of filter """ + i = 0 for (filter_type, values) in filters.items(): if isinstance(values[0], str): @@ -639,8 +667,7 @@ class BaseNode: filter_value=" ".join([str(v) for v in values])) i += 1 - @asyncio.coroutine - def _add_ubridge_ethernet_connection(self, bridge_name, ethernet_interface, block_host_traffic=False): + async def _add_ubridge_ethernet_connection(self, bridge_name, ethernet_interface, block_host_traffic=False): """ Creates a connection with an Ethernet interface in uBridge. @@ -651,7 +678,7 @@ class BaseNode: if sys.platform.startswith("linux") and block_host_traffic is False: # on Linux we use RAW sockets by default excepting if host traffic must be blocked - yield from self._ubridge_send('bridge add_nio_linux_raw {name} "{interface}"'.format(name=bridge_name, interface=ethernet_interface)) + await self._ubridge_send('bridge add_nio_linux_raw {name} "{interface}"'.format(name=bridge_name, interface=ethernet_interface)) elif sys.platform.startswith("win"): # on Windows we use Winpcap/Npcap windows_interfaces = interfaces() @@ -666,26 +693,26 @@ class BaseNode: npf_id = interface["id"] source_mac = interface["mac_address"] if npf_id: - yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, + await self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, interface=npf_id)) else: raise NodeError("Could not find NPF id for interface {}".format(ethernet_interface)) if block_host_traffic: if source_mac: - yield from self._ubridge_send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=bridge_name, mac=source_mac)) + await self._ubridge_send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=bridge_name, mac=source_mac)) log.info('PCAP filter applied on "{interface}" for source MAC {mac}'.format(interface=ethernet_interface, mac=source_mac)) else: log.warning("Could not block host network traffic on {} (no MAC address found)".format(ethernet_interface)) else: # on other platforms we just rely on the pcap library - yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, interface=ethernet_interface)) + await self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, interface=ethernet_interface)) source_mac = None for interface in interfaces(): if interface["name"] == ethernet_interface: source_mac = interface["mac_address"] if source_mac: - yield from self._ubridge_send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=bridge_name, mac=source_mac)) + await self._ubridge_send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=bridge_name, mac=source_mac)) log.info('PCAP filter applied on "{interface}" for source MAC {mac}'.format(interface=ethernet_interface, mac=source_mac)) def _create_local_udp_tunnel(self): @@ -735,3 +762,10 @@ class BaseNode: percentage_left, platform.node()) self.project.emit("log.warning", {"message": message}) + + def _get_custom_adapter_settings(self, adapter_number): + + for custom_adapter in self.custom_adapters: + if custom_adapter["adapter_number"] == adapter_number: + return custom_adapter + return {} diff --git a/gns3server/compute/builtin/nodes/cloud.py b/gns3server/compute/builtin/nodes/cloud.py index 31796964..02bcdce5 100644 --- a/gns3server/compute/builtin/nodes/cloud.py +++ b/gns3server/compute/builtin/nodes/cloud.py @@ -16,7 +16,6 @@ # along with this program. If not, see . import sys -import asyncio import subprocess from ...error import NodeError @@ -42,11 +41,16 @@ class Cloud(BaseNode): :param manager: Parent VM Manager """ - def __init__(self, name, node_id, project, manager, ports=[]): + def __init__(self, name, node_id, project, manager, ports=None): super().__init__(name, node_id, project, manager) self._nios = {} - # If the cloud is not configured we fill it with host interfaces + self._remote_console_host = "" + self._remote_console_port = 23 + self._remote_console_type = "none" + self._remote_console_http_path = "/" + + # Populate the cloud with host interfaces if it is not configured if not ports or len(ports) == 0: self._ports_mapping = [] for interface in self._interfaces(): @@ -83,12 +87,96 @@ class Cloud(BaseNode): return {"name": self.name, "node_id": self.id, "project_id": self.project.id, + "remote_console_host": self.remote_console_host, + "remote_console_port": self.remote_console_port, + "remote_console_type": self.remote_console_type, + "remote_console_http_path": self.remote_console_http_path, "ports_mapping": self._ports_mapping, "interfaces": host_interfaces, "status": self.status, "node_directory": self.working_path } + @property + def remote_console_host(self): + """ + Returns the remote console host for this cloud. + + :returns: remote console host + """ + + return self._remote_console_host + + @remote_console_host.setter + def remote_console_host(self, remote_console_host): + """ + Sets the remote console host for this cloud. + + :param remote_console_host: remote console host + """ + + self._remote_console_host = remote_console_host + + @property + def remote_console_port(self): + """ + Returns the remote console port for this cloud. + + :returns: remote console port + """ + + return self._remote_console_port + + @remote_console_port.setter + def remote_console_port(self, remote_console_port): + """ + Sets the remote console port for this cloud. + + :param remote_console_port: remote console port + """ + + self._remote_console_port = remote_console_port + + @property + def remote_console_type(self): + """ + Returns the remote console type for this cloud. + + :returns: remote console host + """ + + return self._remote_console_type + + @remote_console_type.setter + def remote_console_type(self, remote_console_type): + """ + Sets the remote console type for this cloud. + + :param remote_console_type: remote console type + """ + + self._remote_console_type = remote_console_type + + @property + def remote_console_http_path(self): + """ + Returns the remote console HTTP path for this cloud. + + :returns: remote console HTTP path + """ + + return self._remote_console_http_path + + @remote_console_http_path.setter + def remote_console_http_path(self, remote_console_http_path): + """ + Sets the remote console HTTP path for this cloud. + + :param remote_console_http_path: remote console HTTP path + """ + + self._remote_console_http_path = remote_console_http_path + @property def ports_mapping(self): """ @@ -109,7 +197,7 @@ class Cloud(BaseNode): if ports != self._ports_mapping: if len(self._nios) > 0: - raise NodeError("Can't modify a cloud already connected.") + raise NodeError("Cannot modify a cloud that is already connected.") port_number = 0 for port in ports: @@ -118,53 +206,56 @@ class Cloud(BaseNode): self._ports_mapping = ports - @asyncio.coroutine - def create(self): + async def create(self): """ Creates this cloud. """ - yield from self.start() + await self.start() log.info('Cloud "{name}" [{id}] has been created'.format(name=self._name, id=self._id)) - @asyncio.coroutine - def start(self): + async def start(self): + """ + Starts this cloud. + """ + if self.status != "started": if self._ubridge_hypervisor and self._ubridge_hypervisor.is_running(): - yield from self._stop_ubridge() - yield from self._start_ubridge() + await self._stop_ubridge() + await self._start_ubridge() for port_number in self._nios: if self._nios[port_number]: try: - yield from self._add_ubridge_connection(self._nios[port_number], port_number) + await self._add_ubridge_connection(self._nios[port_number], port_number) except (UbridgeError, NodeError) as e: self.status = "stopped" raise e self.status = "started" - @asyncio.coroutine - def close(self): + async def close(self): """ Closes this cloud. """ - if not (yield from super().close()): + if not (await super().close()): return False for nio in self._nios.values(): if nio and isinstance(nio, NIOUDP): self.manager.port_manager.release_udp_port(nio.lport, self._project) - yield from self._stop_ubridge() + await self._stop_ubridge() log.info('Cloud "{name}" [{id}] has been closed'.format(name=self._name, id=self._id)) - @asyncio.coroutine - def _is_wifi_adapter_osx(self, adapter_name): + async def _is_wifi_adapter_osx(self, adapter_name): + """ + Detects a Wifi adapter on Mac. + """ try: - output = yield from gns3server.utils.asyncio.subprocess_check_output("networksetup", "-listallhardwareports") - except (FileNotFoundError, subprocess.SubprocessError) as e: - log.warn("Could not execute networksetup: {}".format(e)) + output = await gns3server.utils.asyncio.subprocess_check_output("networksetup", "-listallhardwareports") + except (OSError, subprocess.SubprocessError) as e: + log.warning("Could not execute networksetup: {}".format(e)) return False is_wifi = False @@ -178,8 +269,7 @@ class Cloud(BaseNode): is_wifi = True return False - @asyncio.coroutine - def _add_ubridge_connection(self, nio, port_number): + async def _add_ubridge_connection(self, nio, port_number): """ Creates a connection in uBridge. @@ -198,56 +288,58 @@ class Cloud(BaseNode): port_number=port_number)) bridge_name = "{}-{}".format(self._id, port_number) - yield from self._ubridge_send("bridge create {name}".format(name=bridge_name)) + await self._ubridge_send("bridge create {name}".format(name=bridge_name)) if not isinstance(nio, NIOUDP): raise NodeError("Source NIO is not UDP") - yield from self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name, - lport=nio.lport, - rhost=nio.rhost, - rport=nio.rport)) + await self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name, + lport=nio.lport, + rhost=nio.rhost, + rport=nio.rport)) - yield from self._ubridge_apply_filters(bridge_name, nio.filters) + await self._ubridge_apply_filters(bridge_name, nio.filters) if port_info["type"] in ("ethernet", "tap"): + if not self.manager.has_privileged_access(self.ubridge_path): + raise NodeError("uBridge requires root access or the capability to interact with Ethernet and TAP adapters") + if sys.platform.startswith("win"): - yield from self._add_ubridge_ethernet_connection(bridge_name, port_info["interface"]) + await self._add_ubridge_ethernet_connection(bridge_name, port_info["interface"]) else: - if port_info["type"] == "ethernet": network_interfaces = [interface["name"] for interface in self._interfaces()] if not port_info["interface"] in network_interfaces: - raise NodeError("Interface '{}' could not be found on this system".format(port_info["interface"])) + raise NodeError("Interface '{}' could not be found on this system, please update '{}'".format(port_info["interface"], self.name)) if sys.platform.startswith("linux"): - yield from self._add_linux_ethernet(port_info, bridge_name) + await self._add_linux_ethernet(port_info, bridge_name) elif sys.platform.startswith("darwin"): - yield from self._add_osx_ethernet(port_info, bridge_name) + await self._add_osx_ethernet(port_info, bridge_name) else: - yield from self._add_windows_ethernet(port_info, bridge_name) + await self._add_windows_ethernet(port_info, bridge_name) elif port_info["type"] == "tap": - yield from self._ubridge_send('bridge add_nio_tap {name} "{interface}"'.format(name=bridge_name, interface=port_info["interface"])) + await self._ubridge_send('bridge add_nio_tap {name} "{interface}"'.format(name=bridge_name, interface=port_info["interface"])) elif port_info["type"] == "udp": - yield from self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name, + await self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=bridge_name, lport=port_info["lport"], rhost=port_info["rhost"], rport=port_info["rport"])) if nio.capturing: - yield from self._ubridge_send('bridge start_capture {name} "{pcap_file}"'.format(name=bridge_name, + await self._ubridge_send('bridge start_capture {name} "{pcap_file}"'.format(name=bridge_name, pcap_file=nio.pcap_output_file)) - yield from self._ubridge_send('bridge start {name}'.format(name=bridge_name)) + await self._ubridge_send('bridge start {name}'.format(name=bridge_name)) - @asyncio.coroutine - def _add_linux_ethernet(self, port_info, bridge_name): + async def _add_linux_ethernet(self, port_info, bridge_name): """ - Use raw sockets on Linux. + Connects an Ethernet interface on Linux using raw sockets. - If interface is a bridge we connect a tap to it + A TAP is used if the interface is a bridge """ + interface = port_info["interface"] if gns3server.utils.interfaces.is_interface_bridge(interface): @@ -259,33 +351,38 @@ class Cloud(BaseNode): break i += 1 - yield from self._ubridge_send('bridge add_nio_tap "{name}" "{interface}"'.format(name=bridge_name, interface=tap)) - yield from self._ubridge_send('brctl addif "{interface}" "{tap}"'.format(tap=tap, interface=interface)) + await self._ubridge_send('bridge add_nio_tap "{name}" "{interface}"'.format(name=bridge_name, interface=tap)) + await self._ubridge_send('brctl addif "{interface}" "{tap}"'.format(tap=tap, interface=interface)) else: - yield from self._ubridge_send('bridge add_nio_linux_raw {name} "{interface}"'.format(name=bridge_name, interface=interface)) + await self._ubridge_send('bridge add_nio_linux_raw {name} "{interface}"'.format(name=bridge_name, interface=interface)) + + async def _add_osx_ethernet(self, port_info, bridge_name): + """ + Connects an Ethernet interface on OSX using libpcap. + """ - @asyncio.coroutine - def _add_osx_ethernet(self, port_info, bridge_name): # Wireless adapters are not well supported by the libpcap on OSX - if (yield from self._is_wifi_adapter_osx(port_info["interface"])): + if (await self._is_wifi_adapter_osx(port_info["interface"])): raise NodeError("Connecting to a Wireless adapter is not supported on Mac OS") if port_info["interface"].startswith("vmnet"): # Use a special NIO to connect to VMware vmnet interfaces on OSX (libpcap doesn't support them) - yield from self._ubridge_send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=bridge_name, + await self._ubridge_send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=bridge_name, interface=port_info["interface"])) return if not gns3server.utils.interfaces.has_netmask(port_info["interface"]): raise NodeError("Interface {} has no netmask, interface down?".format(port_info["interface"])) - yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, interface=port_info["interface"])) + await self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, interface=port_info["interface"])) + + async def _add_windows_ethernet(self, port_info, bridge_name): + """ + Connects an Ethernet interface on Windows. + """ - @asyncio.coroutine - def _add_windows_ethernet(self, port_info, bridge_name): if not gns3server.utils.interfaces.has_netmask(port_info["interface"]): raise NodeError("Interface {} has no netmask, interface down?".format(port_info["interface"])) - yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, interface=port_info["interface"])) + await self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=bridge_name, interface=port_info["interface"])) - @asyncio.coroutine - def add_nio(self, nio, port_number): + async def add_nio(self, nio, port_number): """ Adds a NIO as new port on this cloud. @@ -301,23 +398,16 @@ class Cloud(BaseNode): nio=nio, port=port_number)) try: - yield from self.start() - yield from self._add_ubridge_connection(nio, port_number) + await self.start() + await self._add_ubridge_connection(nio, port_number) self._nios[port_number] = nio - except NodeError as e: - self.project.emit("log.error", {"message": str(e)}) - yield from self._stop_ubridge() + except (NodeError, UbridgeError) as e: + await self._stop_ubridge() self.status = "stopped" self._nios[port_number] = nio - # Cleanup stuff - except UbridgeError as e: self.project.emit("log.error", {"message": str(e)}) - yield from self._stop_ubridge() - self.status = "stopped" - self._nios[port_number] = nio - @asyncio.coroutine - def update_nio(self, port_number, nio): + async def update_nio(self, port_number, nio): """ Update an nio on this node @@ -327,10 +417,9 @@ class Cloud(BaseNode): bridge_name = "{}-{}".format(self._id, port_number) if self._ubridge_hypervisor and self._ubridge_hypervisor.is_running(): - yield from self._ubridge_apply_filters(bridge_name, nio.filters) + await self._ubridge_apply_filters(bridge_name, nio.filters) - @asyncio.coroutine - def _delete_ubridge_connection(self, port_number): + async def _delete_ubridge_connection(self, port_number): """ Deletes a connection in uBridge. @@ -338,10 +427,9 @@ class Cloud(BaseNode): """ bridge_name = "{}-{}".format(self._id, port_number) - yield from self._ubridge_send("bridge delete {name}".format(name=bridge_name)) + await self._ubridge_send("bridge delete {name}".format(name=bridge_name)) - @asyncio.coroutine - def remove_nio(self, port_number): + async def remove_nio(self, port_number): """ Removes the specified NIO as member of cloud. @@ -353,6 +441,7 @@ class Cloud(BaseNode): if port_number not in self._nios: raise NodeError("Port {} is not allocated".format(port_number)) + await self.stop_capture(port_number) nio = self._nios[port_number] if isinstance(nio, NIOUDP): self.manager.port_manager.release_udp_port(nio.lport, self._project) @@ -364,12 +453,31 @@ class Cloud(BaseNode): del self._nios[port_number] if self._ubridge_hypervisor and self._ubridge_hypervisor.is_running(): - yield from self._delete_ubridge_connection(port_number) - yield from self.start() + await self._delete_ubridge_connection(port_number) + await self.start() return nio - @asyncio.coroutine - def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): + def get_nio(self, port_number): + """ + Gets a port NIO binding. + + :param port_number: port number + + :returns: NIO instance + """ + + if not [port["port_number"] for port in self._ports_mapping if port_number == port["port_number"]]: + raise NodeError("Port {port_number} doesn't exist on cloud '{name}'".format(name=self.name, + port_number=port_number)) + + if port_number not in self._nios: + raise NodeError("Port {} is not connected".format(port_number)) + + nio = self._nios[port_number] + + return nio + + async def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): """ Starts a packet capture. @@ -378,44 +486,30 @@ class Cloud(BaseNode): :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB """ - if not [port["port_number"] for port in self._ports_mapping if port_number == port["port_number"]]: - raise NodeError("Port {port_number} doesn't exist on cloud '{name}'".format(name=self.name, - port_number=port_number)) - - if port_number not in self._nios: - raise NodeError("Port {} is not connected".format(port_number)) - - nio = self._nios[port_number] - + nio = self.get_nio(port_number) if nio.capturing: raise NodeError("Packet capture is already activated on port {port_number}".format(port_number=port_number)) - nio.startPacketCapture(output_file) + nio.start_packet_capture(output_file) bridge_name = "{}-{}".format(self._id, port_number) - yield from self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name=bridge_name, + await self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name=bridge_name, output_file=output_file)) log.info("Cloud '{name}' [{id}]: starting packet capture on port {port_number}".format(name=self.name, id=self.id, port_number=port_number)) - @asyncio.coroutine - def stop_capture(self, port_number): + async def stop_capture(self, port_number): """ Stops a packet capture. :param port_number: allocated port number """ - if not [port["port_number"] for port in self._ports_mapping if port_number == port["port_number"]]: - raise NodeError("Port {port_number} doesn't exist on cloud '{name}'".format(name=self.name, - port_number=port_number)) - - if port_number not in self._nios: - raise NodeError("Port {} is not connected".format(port_number)) - - nio = self._nios[port_number] - nio.stopPacketCapture() + nio = self.get_nio(port_number) + if not nio.capturing: + return + nio.stop_packet_capture() bridge_name = "{}-{}".format(self._id, port_number) - yield from self._ubridge_send("bridge stop_capture {name}".format(name=bridge_name)) + await self._ubridge_send("bridge stop_capture {name}".format(name=bridge_name)) log.info("Cloud'{name}' [{id}]: stopping packet capture on port {port_number}".format(name=self.name, id=self.id, diff --git a/gns3server/compute/builtin/nodes/ethernet_hub.py b/gns3server/compute/builtin/nodes/ethernet_hub.py index ebc561ec..6137b588 100644 --- a/gns3server/compute/builtin/nodes/ethernet_hub.py +++ b/gns3server/compute/builtin/nodes/ethernet_hub.py @@ -44,8 +44,7 @@ class EthernetHub(BaseNode): "node_id": self.id, "project_id": self.project.id} - @asyncio.coroutine - def create(self): + async def create(self): """ Creates this hub. """ @@ -53,16 +52,14 @@ class EthernetHub(BaseNode): super().create() log.info('Ethernet hub "{name}" [{id}] has been created'.format(name=self._name, id=self._id)) - @asyncio.coroutine - def delete(self): + async def delete(self): """ Deletes this hub. """ raise NotImplementedError() - @asyncio.coroutine - def add_nio(self, nio, port_number): + async def add_nio(self, nio, port_number): """ Adds a NIO as new port on this hub. @@ -72,8 +69,7 @@ class EthernetHub(BaseNode): raise NotImplementedError() - @asyncio.coroutine - def remove_nio(self, port_number): + async def remove_nio(self, port_number): """ Removes the specified NIO as member of this hub. @@ -84,8 +80,7 @@ class EthernetHub(BaseNode): raise NotImplementedError() - @asyncio.coroutine - def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): + async def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): """ Starts a packet capture. @@ -96,8 +91,7 @@ class EthernetHub(BaseNode): raise NotImplementedError() - @asyncio.coroutine - def stop_capture(self, port_number): + async def stop_capture(self, port_number): """ Stops a packet capture. diff --git a/gns3server/compute/builtin/nodes/ethernet_switch.py b/gns3server/compute/builtin/nodes/ethernet_switch.py index 523c3d01..69c5b736 100644 --- a/gns3server/compute/builtin/nodes/ethernet_switch.py +++ b/gns3server/compute/builtin/nodes/ethernet_switch.py @@ -44,8 +44,7 @@ class EthernetSwitch(BaseNode): "node_id": self.id, "project_id": self.project.id} - @asyncio.coroutine - def create(self): + async def create(self): """ Creates this switch. """ @@ -53,16 +52,14 @@ class EthernetSwitch(BaseNode): super().create() log.info('Ethernet switch "{name}" [{id}] has been created'.format(name=self._name, id=self._id)) - @asyncio.coroutine - def delete(self): + async def delete(self): """ Deletes this switch. """ raise NotImplementedError() - @asyncio.coroutine - def add_nio(self, nio, port_number): + async def add_nio(self, nio, port_number): """ Adds a NIO as new port on this switch. @@ -72,8 +69,7 @@ class EthernetSwitch(BaseNode): raise NotImplementedError() - @asyncio.coroutine - def remove_nio(self, port_number): + async def remove_nio(self, port_number): """ Removes the specified NIO as member of this switch. @@ -84,8 +80,7 @@ class EthernetSwitch(BaseNode): raise NotImplementedError() - @asyncio.coroutine - def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): + async def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): """ Starts a packet capture. @@ -96,8 +91,7 @@ class EthernetSwitch(BaseNode): raise NotImplementedError() - @asyncio.coroutine - def stop_capture(self, port_number): + async def stop_capture(self, port_number): """ Stops a packet capture. diff --git a/gns3server/compute/builtin/nodes/nat.py b/gns3server/compute/builtin/nodes/nat.py index 59c8f072..35984315 100644 --- a/gns3server/compute/builtin/nodes/nat.py +++ b/gns3server/compute/builtin/nodes/nat.py @@ -21,27 +21,34 @@ from .cloud import Cloud from ...error import NodeError import gns3server.utils.interfaces +from gns3server.config import Config + +import logging +log = logging.getLogger(__name__) class Nat(Cloud): """ - A portable and preconfigured node allowing topology to get a - nat access to the outside + A portable and pre-configured node allowing topologies to get a + NAT access. """ - def __init__(self, *args, **kwargs): + def __init__(self, name, node_id, project, manager, ports=None): if sys.platform.startswith("linux"): - if "virbr0" not in [interface["name"] for interface in gns3server.utils.interfaces.interfaces()]: - raise NodeError("virbr0 is missing. You need to install libvirt") - interface = "virbr0" + nat_interface = Config.instance().get_section_config("Server").get("default_nat_interface", "virbr0") + if nat_interface not in [interface["name"] for interface in gns3server.utils.interfaces.interfaces()]: + raise NodeError("NAT interface {} is missing, please install libvirt".format(nat_interface)) + interface = nat_interface else: - interfaces = list(filter(lambda x: 'vmnet8' in x.lower(), + nat_interface = Config.instance().get_section_config("Server").get("default_nat_interface", "vmnet8") + interfaces = list(filter(lambda x: nat_interface in x.lower(), [interface["name"] for interface in gns3server.utils.interfaces.interfaces()])) if not len(interfaces): - raise NodeError("vmnet8 is missing. You need to install VMware or use the NAT node on GNS3 VM") + raise NodeError("NAT interface {} is missing. You need to install VMware or use the NAT node on GNS3 VM".format(nat_interface)) interface = interfaces[0] # take the first available interface containing the vmnet8 name + log.info("NAT node '{}' configured to use NAT interface '{}'".format(name, interface)) ports = [ { "name": "nat0", @@ -50,7 +57,7 @@ class Nat(Cloud): "port_number": 0 } ] - super().__init__(*args, ports=ports) + super().__init__(name, node_id, project, manager, ports=ports) @property def ports_mapping(self): diff --git a/gns3server/compute/docker/__init__.py b/gns3server/compute/docker/__init__.py index d2fca166..1a13d1af 100644 --- a/gns3server/compute/docker/__init__.py +++ b/gns3server/compute/docker/__init__.py @@ -25,7 +25,7 @@ import asyncio import logging import aiohttp from gns3server.utils import parse_version -from gns3server.utils.asyncio import locked_coroutine +from gns3server.utils.asyncio import locking from gns3server.compute.base_manager import BaseManager from gns3server.compute.docker.docker_vm import DockerVM from gns3server.compute.docker.docker_error import DockerError, DockerHttp304Error, DockerHttp404Error @@ -33,10 +33,11 @@ from gns3server.compute.docker.docker_error import DockerError, DockerHttp304Err log = logging.getLogger(__name__) -# Be carefull to keep it consistent +# Be careful to keep it consistent DOCKER_MINIMUM_API_VERSION = "1.25" DOCKER_MINIMUM_VERSION = "1.13" DOCKER_PREFERRED_API_VERSION = "1.30" +CHUNK_SIZE = 1024 * 8 # 8KB class Docker(BaseManager): @@ -44,6 +45,7 @@ class Docker(BaseManager): _NODE_CLASS = DockerVM def __init__(self): + super().__init__() self._server_url = '/var/run/docker.sock' self._connected = False @@ -53,13 +55,13 @@ class Docker(BaseManager): self._session = None self._api_version = DOCKER_MINIMUM_API_VERSION - @asyncio.coroutine - def _check_connection(self): + async def _check_connection(self): + if not self._connected: try: self._connected = True connector = self.connector() - version = yield from self.query("GET", "version") + version = await self.query("GET", "version") except (aiohttp.ClientOSError, FileNotFoundError): self._connected = False raise DockerError("Can't connect to docker daemon") @@ -76,6 +78,7 @@ class Docker(BaseManager): self._api_version = DOCKER_PREFERRED_API_VERSION def connector(self): + if self._connector is None or self._connector.closed: if not sys.platform.startswith("linux"): raise DockerError("Docker is supported only on Linux") @@ -85,17 +88,18 @@ class Docker(BaseManager): raise DockerError("Can't connect to docker daemon") return self._connector - @asyncio.coroutine - def unload(self): - yield from super().unload() + async def unload(self): + + await super().unload() if self._connected: if self._connector and not self._connector.closed: - self._connector.close() + await self._connector.close() + if self._session and not self._session.closed: + await self._session.close() - @asyncio.coroutine - def query(self, method, path, data={}, params={}): + async def query(self, method, path, data={}, params={}): """ - Make a query to the docker daemon and decode the request + Makes a query to the Docker daemon and decode the request :param method: HTTP method :param path: Endpoint in API @@ -103,8 +107,9 @@ class Docker(BaseManager): :param params: Parameters added as a query arg """ - response = yield from self.http_query(method, path, data=data, params=params) - body = yield from response.read() + response = await self.http_query(method, path, data=data, params=params) + body = await response.read() + response.close() if body and len(body): if response.headers['CONTENT-TYPE'] == 'application/json': body = json.loads(body.decode("utf-8")) @@ -113,10 +118,9 @@ class Docker(BaseManager): log.debug("Query Docker %s %s params=%s data=%s Response: %s", method, path, params, data, body) return body - @asyncio.coroutine - def http_query(self, method, path, data={}, params={}, timeout=300): + async def http_query(self, method, path, data={}, params={}, timeout=300): """ - Make a query to the docker daemon + Makes a query to the docker daemon :param method: HTTP method :param path: Endpoint in API @@ -125,6 +129,7 @@ class Docker(BaseManager): :param timeout: Timeout :returns: HTTP response """ + data = json.dumps(data) if timeout is None: timeout = 60 * 60 * 24 * 31 # One month timeout @@ -135,24 +140,22 @@ class Docker(BaseManager): url = "http://docker/v" + DOCKER_MINIMUM_API_VERSION + "/" + path try: if path != "version": # version is use by check connection - yield from self._check_connection() + await self._check_connection() if self._session is None or self._session.closed: connector = self.connector() self._session = aiohttp.ClientSession(connector=connector) - response = yield from self._session.request( - method, - url, - params=params, - data=data, - headers={"content-type": "application/json", }, - timeout=timeout - ) + response = await self._session.request(method, + url, + params=params, + data=data, + headers={"content-type": "application/json", }, + timeout=timeout) except (aiohttp.ClientResponseError, aiohttp.ClientOSError) as e: raise DockerError("Docker has returned an error: {}".format(str(e))) except (asyncio.TimeoutError): raise DockerError("Docker timeout " + method + " " + path) if response.status >= 300: - body = yield from response.read() + body = await response.read() try: body = json.loads(body.decode("utf-8"))["message"] except ValueError: @@ -166,10 +169,9 @@ class Docker(BaseManager): raise DockerError("Docker has returned an error: {} {}".format(response.status, body)) return response - @asyncio.coroutine - def websocket_query(self, path, params={}): + async def websocket_query(self, path, params={}): """ - Open a websocket connection + Opens a websocket connection :param path: Endpoint in API :param params: Parameters added as a query arg @@ -177,35 +179,40 @@ class Docker(BaseManager): """ url = "http://docker/v" + self._api_version + "/" + path - connection = yield from self._session.ws_connect(url, - origin="http://docker", - autoping=True) + connection = await self._session.ws_connect(url, origin="http://docker", autoping=True) return connection - @locked_coroutine - def pull_image(self, image, progress_callback=None): + @locking + async def pull_image(self, image, progress_callback=None): """ - Pull image from docker repository + Pulls an image from the Docker repository :params image: Image name :params progress_callback: A function that receive a log message about image download progress """ try: - yield from self.query("GET", "images/{}/json".format(image)) + await self.query("GET", "images/{}/json".format(image)) return # We already have the image skip the download except DockerHttp404Error: pass if progress_callback: - progress_callback("Pull {} from docker hub".format(image)) - response = yield from self.http_query("POST", "images/create", params={"fromImage": image}, timeout=None) + progress_callback("Pulling '{}' from docker hub".format(image)) + try: + response = await self.http_query("POST", "images/create", params={"fromImage": image}, timeout=None) + except DockerError as e: + raise DockerError("Could not pull the '{}' image from Docker Hub, please check your Internet connection (original error: {})".format(image, e)) # The pull api will stream status via an HTTP JSON stream content = "" while True: try: - chunk = yield from response.content.read(1024) + chunk = await response.content.read(CHUNK_SIZE) except aiohttp.ServerDisconnectedError: + log.error("Disconnected from server while pulling Docker image '{}' from docker hub".format(image)) + break + except asyncio.TimeoutError: + log.error("Timeout while pulling Docker image '{}' from docker hub".format(image)) break if not chunk: break @@ -224,15 +231,16 @@ class Docker(BaseManager): if progress_callback: progress_callback("Success pulling image {}".format(image)) - @asyncio.coroutine - def list_images(self): - """Gets Docker image list. + async def list_images(self): + """ + Gets Docker image list. :returns: list of dicts :rtype: list """ + images = [] - for image in (yield from self.query("GET", "images/json", params={"all": 0})): + for image in (await self.query("GET", "images/json", params={"all": 0})): if image['RepoTags']: for tag in image['RepoTags']: if tag != ":": diff --git a/gns3server/compute/docker/docker_vm.py b/gns3server/compute/docker/docker_vm.py index 3d291550..27053ea4 100644 --- a/gns3server/compute/docker/docker_vm.py +++ b/gns3server/compute/docker/docker_vm.py @@ -24,11 +24,14 @@ import shutil import psutil import shlex import aiohttp +import subprocess import os +import re from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer from gns3server.utils.asyncio.raw_command_server import AsyncioRawCommandServer from gns3server.utils.asyncio import wait_for_file_creation +from gns3server.utils.asyncio import monitor_process from gns3server.utils.get_resource import get_resource from gns3server.ubridge.ubridge_error import UbridgeError, UbridgeNamespaceError @@ -61,11 +64,13 @@ class DockerVM(BaseNode): :param console_resolution: Resolution of the VNC display :param console_http_port: Port to redirect HTTP queries :param console_http_path: Url part with the path of the web interface + :param extra_hosts: Hosts which will be written into /etc/hosts into docker conainer + :param extra_volumes: Additional directories to make persistent """ def __init__(self, name, node_id, project, manager, image, console=None, aux=None, start_command=None, adapters=None, environment=None, console_type="telnet", console_resolution="1024x768", - console_http_port=80, console_http_path="/"): + console_http_port=80, console_http_path="/", extra_hosts=None, extra_volumes=[]): super().__init__(name, node_id, project, manager, console=console, aux=aux, allocate_aux=True, console_type=console_type) @@ -79,11 +84,18 @@ class DockerVM(BaseNode): self._ethernet_adapters = [] self._temporary_directory = None self._telnet_servers = [] - self._x11vnc_process = None + self._xvfb_process = None + self._vnc_process = None self._console_resolution = console_resolution self._console_http_path = console_http_path self._console_http_port = console_http_port self._console_websocket = None + self._extra_hosts = extra_hosts + self._extra_volumes = extra_volumes or [] + self._permissions_fixed = False + self._display = None + self._closing = False + self._volumes = [] # Keep a list of created bridge self._bridges = set() @@ -100,6 +112,7 @@ class DockerVM(BaseNode): def __json__(self): return { "name": self._name, + "usage": self.usage, "node_id": self._id, "container_id": self._cid, "project_id": self._project.id, @@ -114,7 +127,9 @@ class DockerVM(BaseNode): "start_command": self.start_command, "status": self.status, "environment": self.environment, - "node_directory": self.working_path + "node_directory": self.working_path, + "extra_hosts": self.extra_hosts, + "extra_volumes": self.extra_volumes, } def _get_free_display_port(self): @@ -178,15 +193,32 @@ class DockerVM(BaseNode): def environment(self, command): self._environment = command - @asyncio.coroutine - def _get_container_state(self): - """Returns the container state (e.g. running, paused etc.) + @property + def extra_hosts(self): + return self._extra_hosts + + @extra_hosts.setter + def extra_hosts(self, extra_hosts): + self._extra_hosts = extra_hosts + + @property + def extra_volumes(self): + return self._extra_volumes + + @extra_volumes.setter + def extra_volumes(self, extra_volumes): + self._extra_volumes = extra_volumes + + async def _get_container_state(self): + """ + Returns the container state (e.g. running, paused etc.) :returns: state :rtype: str """ + try: - result = yield from self.manager.query("GET", "containers/{}/json".format(self._cid)) + result = await self.manager.query("GET", "containers/{}/json".format(self._cid)) except DockerError: return "exited" @@ -196,33 +228,43 @@ class DockerVM(BaseNode): return "running" return "exited" - @asyncio.coroutine - def _get_image_information(self): + async def _get_image_information(self): """ :returns: Dictionary information about the container image """ - result = yield from self.manager.query("GET", "images/{}/json".format(self._image)) + + result = await self.manager.query("GET", "images/{}/json".format(self._image)) return result - def _mount_binds(self, image_infos): + def _mount_binds(self, image_info): """ :returns: Return the path that we need to map to local folders """ - ressources = get_resource("compute/docker/resources") - if not os.path.exists(ressources): - raise DockerError("{} is missing can't start Docker containers".format(ressources)) - binds = ["{}:/gns3:ro".format(ressources)] + + resources = get_resource("compute/docker/resources") + if not os.path.exists(resources): + raise DockerError("{} is missing can't start Docker containers".format(resources)) + binds = ["{}:/gns3:ro".format(resources)] # We mount our own etc/network - network_config = self._create_network_config() + try: + network_config = self._create_network_config() + except OSError as e: + raise DockerError("Could not create network config in the container: {}".format(e)) binds.append("{}:/gns3volumes/etc/network:rw".format(network_config)) self._volumes = ["/etc/network"] - - volumes = image_infos.get("Config", {}).get("Volumes") - if volumes is None: - return binds - for volume in volumes.keys(): + volumes = list((image_info.get("Config", {}).get("Volumes") or {}).keys()) + for volume in self._extra_volumes: + if not volume.strip() or volume[0] != "/" or volume.find("..") >= 0: + raise DockerError("Persistent volume '{}' has invalid format. It must start with a '/' and not contain '..'.".format(volume)) + volumes.extend(self._extra_volumes) + # define lambdas for validation checks + nf = lambda x: re.sub(r"//+", "/", (x if x.endswith("/") else x + "/")) + incompatible = lambda v1, v2: nf(v1).startswith(nf(v2)) or nf(v2).startswith(nf(v1)) + for volume in volumes: + if [ v for v in self._volumes if incompatible(v, volume) ] : + raise DockerError("Duplicate persistent volume {} detected.\n\nVolumes specified in docker image as well as user specified persistent volumes must be unique.".format(volume)) source = os.path.join(self.working_dir, os.path.relpath(volume, "/")) os.makedirs(source, exist_ok=True) binds.append("{}:/gns3volumes{}".format(source, volume)) @@ -264,18 +306,20 @@ class DockerVM(BaseNode): # iface eth{adapter} inet dhcp""".format(adapter=adapter)) return path - @asyncio.coroutine - def create(self): - """Creates the Docker container.""" + async def create(self): + """ + Creates the Docker container. + """ try: - image_infos = yield from self._get_image_information() + image_infos = await self._get_image_information() except DockerHttp404Error: - log.info("Image %s is missing pulling it from docker hub", self._image) - yield from self.pull_image(self._image) - image_infos = yield from self._get_image_information() - if image_infos is None: - raise DockerError("Can't get image informations, please try again.") + log.info("Image '{}' is missing, pulling it from Docker hub...".format(self._image)) + await self.pull_image(self._image) + image_infos = await self._get_image_information() + + if image_infos is None: + raise DockerError("Cannot get information for image '{}', please try again.".format(self._image)) params = { "Hostname": self._name, @@ -288,20 +332,23 @@ class DockerVM(BaseNode): "HostConfig": { "CapAdd": ["ALL"], "Privileged": True, - "Binds": self._mount_binds(image_infos) + "Binds": self._mount_binds(image_infos), }, "Volumes": {}, "Env": ["container=docker"], # Systemd compliant: https://github.com/GNS3/gns3-server/issues/573 "Cmd": [], - "Entrypoint": image_infos.get("Config", {"Entrypoint": []})["Entrypoint"] + "Entrypoint": image_infos.get("Config", {"Entrypoint": []}).get("Entrypoint") } if params["Entrypoint"] is None: params["Entrypoint"] = [] if self._start_command: - params["Cmd"] = shlex.split(self._start_command) + try: + params["Cmd"] = shlex.split(self._start_command) + except ValueError as e: + raise DockerError("Invalid start command '{}': {}".format(self._start_command, e)) if len(params["Cmd"]) == 0: - params["Cmd"] = image_infos.get("Config", {"Cmd": []})["Cmd"] + params["Cmd"] = image_infos.get("Config", {"Cmd": []}).get("Cmd") if params["Cmd"] is None: params["Cmd"] = [] if len(params["Cmd"]) == 0 and len(params["Entrypoint"]) == 0: @@ -313,162 +360,273 @@ class DockerVM(BaseNode): # Give the information to the container the list of volume path mounted params["Env"].append("GNS3_VOLUMES={}".format(":".join(self._volumes))) + # Pass user configured for image to init script + if image_infos.get("Config", {"User": ""}).get("User"): + params["User"] = "root" + params["Env"].append("GNS3_USER={}".format(image_infos.get("Config", {"User": ""})["User"])) + + variables = self.project.variables + if not variables: + variables = [] + + for var in variables: + formatted = self._format_env(variables, var.get('value', '')) + params["Env"].append("{}={}".format(var["name"], formatted)) + if self._environment: for e in self._environment.strip().split("\n"): e = e.strip() + if e.split("=")[0] == "": + self.project.emit("log.warning", {"message": "{} has invalid environment variable: {}".format(self.name, e)}) + continue if not e.startswith("GNS3_"): - params["Env"].append(e) + formatted = self._format_env(variables, e) + params["Env"].append(formatted) if self._console_type == "vnc": - yield from self._start_vnc() + await self._start_vnc() params["Env"].append("QT_GRAPHICSSYSTEM=native") # To fix a Qt issue: https://github.com/GNS3/gns3-server/issues/556 params["Env"].append("DISPLAY=:{}".format(self._display)) params["HostConfig"]["Binds"].append("/tmp/.X11-unix/:/tmp/.X11-unix/") - result = yield from self.manager.query("POST", "containers/create", data=params) + if self._extra_hosts: + extra_hosts = self._format_extra_hosts(self._extra_hosts) + if extra_hosts: + params["Env"].append("GNS3_EXTRA_HOSTS={}".format(extra_hosts)) + + result = await self.manager.query("POST", "containers/create", data=params) self._cid = result['Id'] - log.info("Docker container '{name}' [{id}] created".format( - name=self._name, id=self._id)) + log.info("Docker container '{name}' [{id}] created".format(name=self._name, id=self._id)) return True - @asyncio.coroutine - def update(self): + def _format_env(self, variables, env): + for variable in variables: + env = env.replace('${' + variable["name"] + '}', variable.get("value", "")) + return env + + def _format_extra_hosts(self, extra_hosts): + lines = [h.strip() for h in self._extra_hosts.split("\n") if h.strip() != ""] + hosts = [] + try: + for host in lines: + hostname, ip = host.split(":") + hostname = hostname.strip() + ip = ip.strip() + if hostname and ip: + hosts.append((hostname, ip)) + except ValueError: + raise DockerError("Can't apply `ExtraHosts`, wrong format: {}".format(extra_hosts)) + return "\n".join(["{}\t{}".format(h[1], h[0]) for h in hosts]) + + async def update(self): """ Destroy an recreate the container with the new settings """ + # We need to save the console and state and restore it console = self.console aux = self.aux - state = yield from self._get_container_state() + state = await self._get_container_state() - yield from self.reset() - yield from self.create() + # reset the docker container, but don't release the NIO UDP ports + await self.reset(False) + await self.create() self.console = console self.aux = aux if state == "running": - yield from self.start() + await self.start() - @asyncio.coroutine - def start(self): - """Starts this Docker container.""" + async def start(self): + """ + Starts this Docker container. + """ try: - state = yield from self._get_container_state() + state = await self._get_container_state() except DockerHttp404Error: raise DockerError("Docker container '{name}' with ID {cid} does not exist or is not ready yet. Please try again in a few seconds.".format(name=self.name, cid=self._cid)) if state == "paused": - yield from self.unpause() + await self.unpause() elif state == "running": return else: - yield from self._clean_servers() - yield from self.manager.query("POST", "containers/{}/start".format(self._cid)) - self._namespace = yield from self._get_namespace() + if self._console_type == "vnc" and not self._vnc_process: + # restart the vnc process in case it had previously crashed + await self._start_vnc_process(restart=True) + monitor_process(self._vnc_process, self._vnc_callback) - yield from self._start_ubridge() + await self._clean_servers() + + await self.manager.query("POST", "containers/{}/start".format(self._cid)) + self._namespace = await self._get_namespace() + + await self._start_ubridge(require_privileged_access=True) for adapter_number in range(0, self.adapters): nio = self._ethernet_adapters[adapter_number].get_nio(0) - with (yield from self.manager.ubridge_lock): + async with self.manager.ubridge_lock: try: - yield from self._add_ubridge_connection(nio, adapter_number) + await self._add_ubridge_connection(nio, adapter_number) except UbridgeNamespaceError: log.error("Container %s failed to start", self.name) - yield from self.stop() + await self.stop() # The container can crash soon after the start, this means we can not move the interface to the container namespace - logdata = yield from self._get_log() + logdata = await self._get_log() for line in logdata.split('\n'): log.error(line) raise DockerError(logdata) if self.console_type == "telnet": - yield from self._start_console() + await self._start_console() elif self.console_type == "http" or self.console_type == "https": - yield from self._start_http() + await self._start_http() if self.allocate_aux: - yield from self._start_aux() + await self._start_aux() + self._permissions_fixed = False self.status = "started" log.info("Docker container '{name}' [{image}] started listen for {console_type} on {console}".format(name=self._name, image=self._image, console=self.console, console_type=self.console_type)) - @asyncio.coroutine - def _start_aux(self): + async def _start_aux(self): """ - Start an auxilary console + Start an auxiliary console """ # We can not use the API because docker doesn't expose a websocket api for exec # https://github.com/GNS3/gns3-gui/issues/1039 - process = yield from asyncio.subprocess.create_subprocess_exec( - "docker", "exec", "-i", self._cid, "/gns3/bin/busybox", "script", "-qfc", "while true; do TERM=vt100 /gns3/bin/busybox sh; done", "/dev/null", - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.STDOUT, - stdin=asyncio.subprocess.PIPE) + try: + process = await asyncio.subprocess.create_subprocess_exec( + "docker", "exec", "-i", self._cid, "/gns3/bin/busybox", "script", "-qfc", "while true; do TERM=vt100 /gns3/bin/busybox sh; done", "/dev/null", + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.STDOUT, + stdin=asyncio.subprocess.PIPE) + except OSError as e: + raise DockerError("Could not start auxiliary console process: {}".format(e)) server = AsyncioTelnetServer(reader=process.stdout, writer=process.stdin, binary=True, echo=True) - self._telnet_servers.append((yield from asyncio.start_server(server.run, self._manager.port_manager.console_host, self.aux))) - log.debug("Docker container '%s' started listen for auxilary telnet on %d", self.name, self.aux) + try: + self._telnet_servers.append((await asyncio.start_server(server.run, self._manager.port_manager.console_host, self.aux))) + except OSError as e: + raise DockerError("Could not start Telnet server on socket {}:{}: {}".format(self._manager.port_manager.console_host, self.aux, e)) + log.debug("Docker container '%s' started listen for auxiliary telnet on %d", self.name, self.aux) - @asyncio.coroutine - def _fix_permissions(self): + async def _fix_permissions(self): """ Because docker run as root we need to fix permission and ownership to allow user to interact with it from their filesystem and do operation like file delete """ - state = yield from self._get_container_state() + state = await self._get_container_state() + log.info("Docker container '{name}' fix ownership, state = {state}".format(name=self._name, state=state)) if state == "stopped" or state == "exited": # We need to restart it to fix permissions - yield from self.manager.query("POST", "containers/{}/start".format(self._cid)) + await self.manager.query("POST", "containers/{}/start".format(self._cid)) for volume in self._volumes: log.debug("Docker container '{name}' [{image}] fix ownership on {path}".format( name=self._name, image=self._image, path=volume)) - process = yield from asyncio.subprocess.create_subprocess_exec( - "docker", - "exec", - self._cid, - "/gns3/bin/busybox", - "sh", - "-c", - "(" - "/gns3/bin/busybox find \"{path}\" -depth -print0" - " | /gns3/bin/busybox xargs -0 /gns3/bin/busybox stat -c '%a:%u:%g:%n' > \"{path}/.gns3_perms\"" - ")" - " && /gns3/bin/busybox chmod -R u+rX \"{path}\"" - " && /gns3/bin/busybox chown {uid}:{gid} -R \"{path}\"" - .format(uid=os.getuid(), gid=os.getgid(), path=volume), - ) - yield from process.wait() - @asyncio.coroutine - def _start_vnc(self): + try: + process = await asyncio.subprocess.create_subprocess_exec( + "docker", + "exec", + self._cid, + "/gns3/bin/busybox", + "sh", + "-c", + "(" + "/gns3/bin/busybox find \"{path}\" -depth -print0" + " | /gns3/bin/busybox xargs -0 /gns3/bin/busybox stat -c '%a:%u:%g:%n' > \"{path}/.gns3_perms\"" + ")" + " && /gns3/bin/busybox chmod -R u+rX \"{path}\"" + " && /gns3/bin/busybox chown {uid}:{gid} -R \"{path}\"" + .format(uid=os.getuid(), gid=os.getgid(), path=volume), + ) + except OSError as e: + raise DockerError("Could not fix permissions for {}: {}".format(volume, e)) + await process.wait() + self._permissions_fixed = True + + async def _start_vnc_process(self, restart=False): """ - Start a VNC server for this container + Starts the VNC process. """ self._display = self._get_free_display_port() - if shutil.which("Xvfb") is None or shutil.which("x11vnc") is None: - raise DockerError("Please install Xvfb and x11vnc before using the VNC support") - self._xvfb_process = yield from asyncio.create_subprocess_exec("Xvfb", "-nolisten", "tcp", ":{}".format(self._display), "-screen", "0", self._console_resolution + "x16") - # We pass a port for TCPV6 due to a crash in X11VNC if not here: https://github.com/GNS3/gns3-server/issues/569 - self._x11vnc_process = yield from asyncio.create_subprocess_exec("x11vnc", "-forever", "-nopw", "-shared", "-geometry", self._console_resolution, "-display", "WAIT:{}".format(self._display), "-rfbport", str(self.console), "-rfbportv6", str(self.console), "-noncache", "-listen", self._manager.port_manager.console_host) + if not (shutil.which("Xtigervnc") or shutil.which("Xvfb") and shutil.which("x11vnc")): + raise DockerError("Please install tigervnc-standalone-server (recommended) or Xvfb + x11vnc before using VNC support") - x11_socket = os.path.join("/tmp/.X11-unix/", "X{}".format(self._display)) - yield from wait_for_file_creation(x11_socket) + if shutil.which("Xtigervnc"): + with open(os.path.join(self.working_dir, "vnc.log"), "w") as fd: + self._vnc_process = await asyncio.create_subprocess_exec("Xtigervnc", + "-geometry", self._console_resolution, + "-depth", "16", + "-interface", self._manager.port_manager.console_host, + "-rfbport", str(self.console), + "-AlwaysShared", + "-SecurityTypes", "None", + ":{}".format(self._display), + stdout=fd, stderr=subprocess.STDOUT) + else: + if restart is False: + self._xvfb_process = await asyncio.create_subprocess_exec("Xvfb", + "-nolisten", + "tcp", ":{}".format(self._display), + "-screen", "0", + self._console_resolution + "x16") - @asyncio.coroutine - def _start_http(self): + # We pass a port for TCPV6 due to a crash in X11VNC if not here: https://github.com/GNS3/gns3-server/issues/569 + with open(os.path.join(self.working_dir, "vnc.log"), "w") as fd: + self._vnc_process = await asyncio.create_subprocess_exec("x11vnc", + "-forever", + "-nopw", + "-shared", + "-geometry", self._console_resolution, + "-display", "WAIT:{}".format(self._display), + "-rfbport", str(self.console), + "-rfbportv6", str(self.console), + "-noncache", + "-listen", self._manager.port_manager.console_host, + stdout=fd, stderr=subprocess.STDOUT) + + async def _start_vnc(self): """ - Start an HTTP tunnel to container localhost. It's not perfect + Starts a VNC server for this container + """ + + self._display = self._get_free_display_port() + if not (shutil.which("Xtigervnc") or shutil.which("Xvfb") and shutil.which("x11vnc")): + raise DockerError("Please install tigervnc-standalone-server (recommended) or Xvfb + x11vnc before using VNC support") + await self._start_vnc_process() + x11_socket = os.path.join("/tmp/.X11-unix/", "X{}".format(self._display)) + await wait_for_file_creation(x11_socket) + + # sometimes the VNC process can crash + monitor_process(self._vnc_process, self._vnc_callback) + + def _vnc_callback(self, returncode): + """ + Called when the process has stopped. + + :param returncode: Process returncode + """ + + if returncode != 0 and self._closing is False: + self.project.emit("log.error", {"message": "The vnc process has stopped with return code {} for node '{}'. Please restart this node.".format(returncode, self.name)}) + self._vnc_process = None + + async def _start_http(self): + """ + Starts an HTTP tunnel to container localhost. It's not perfect but the only way we have to inject network packet is using nc. """ + log.debug("Forward HTTP for %s to %d", self.name, self._console_http_port) command = ["docker", "exec", "-i", self._cid, "/gns3/bin/busybox", "nc", "127.0.0.1", str(self._console_http_port)] # We replace host and port in the server answer otherwise some link could be broken @@ -482,12 +640,24 @@ class DockerVM(BaseNode): ':{}'.format(self.console).encode(), ) ]) - self._telnet_servers.append((yield from asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console))) + self._telnet_servers.append((await asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console))) - @asyncio.coroutine - def _start_console(self): + async def _window_size_changed_callback(self, columns, rows): """ - Start streaming the console via telnet + Called when the console window size has been changed. + (when naws is enabled in the Telnet server) + + :param columns: number of columns + :param rows: number of rows + """ + + # resize the container TTY. + await self._manager.query("POST", "containers/{}/resize?h={}&w={}".format(self._cid, rows, columns)) + + + async def _start_console(self): + """ + Starts streaming the console via telnet """ class InputStream: @@ -498,105 +668,110 @@ class DockerVM(BaseNode): def write(self, data): self._data += data - @asyncio.coroutine - def drain(self): + async def drain(self): if not self.ws.closed: - self.ws.send_bytes(self._data) + await self.ws.send_bytes(self._data) self._data = b"" output_stream = asyncio.StreamReader() input_stream = InputStream() + telnet = AsyncioTelnetServer(reader=output_stream, writer=input_stream, echo=True, naws=True, window_size_changed_callback=self._window_size_changed_callback) + try: + self._telnet_servers.append((await asyncio.start_server(telnet.run, self._manager.port_manager.console_host, self.console))) + except OSError as e: + raise DockerError("Could not start Telnet server on socket {}:{}: {}".format(self._manager.port_manager.console_host, self.console, e)) - telnet = AsyncioTelnetServer(reader=output_stream, writer=input_stream, echo=True) - self._telnet_servers.append((yield from asyncio.start_server(telnet.run, self._manager.port_manager.console_host, self.console))) - - self._console_websocket = yield from self.manager.websocket_query("containers/{}/attach/ws?stream=1&stdin=1&stdout=1&stderr=1".format(self._cid)) + self._console_websocket = await self.manager.websocket_query("containers/{}/attach/ws?stream=1&stdin=1&stdout=1&stderr=1".format(self._cid)) input_stream.ws = self._console_websocket output_stream.feed_data(self.name.encode() + b" console is now available... Press RETURN to get started.\r\n") - asyncio.async(self._read_console_output(self._console_websocket, output_stream)) + asyncio.ensure_future(self._read_console_output(self._console_websocket, output_stream)) - @asyncio.coroutine - def _read_console_output(self, ws, out): + async def _read_console_output(self, ws, out): """ - Read Websocket and forward it to the telnet + Reads Websocket and forward it to the telnet :param ws: Websocket connection :param out: Output stream """ while True: - msg = yield from ws.receive() - if msg.tp == aiohttp.WSMsgType.text: + msg = await ws.receive() + if msg.type == aiohttp.WSMsgType.TEXT: out.feed_data(msg.data.encode()) - elif msg.tp == aiohttp.WSMsgType.BINARY: + elif msg.type == aiohttp.WSMsgType.BINARY: out.feed_data(msg.data) - elif msg.tp == aiohttp.WSMsgType.ERROR: - log.critical("Docker WebSocket Error: {}".format(msg.data)) + elif msg.type == aiohttp.WSMsgType.ERROR: + log.critical("Docker WebSocket Error: {}".format(ws.exception())) else: out.feed_eof() - ws.close() + await ws.close() break - yield from self.stop() + await self.stop() - @asyncio.coroutine - def is_running(self): - """Checks if the container is running. + async def is_running(self): + """ + Checks if the container is running. :returns: True or False :rtype: bool """ - state = yield from self._get_container_state() + + state = await self._get_container_state() if state == "running": return True if self.status == "started": # The container crashed we need to clean - yield from self.stop() + await self.stop() return False - @asyncio.coroutine - def restart(self): - """Restart this Docker container.""" - yield from self.manager.query("POST", "containers/{}/restart".format(self._cid)) + async def restart(self): + """ + Restart this Docker container. + """ + + await self.manager.query("POST", "containers/{}/restart".format(self._cid)) log.info("Docker container '{name}' [{image}] restarted".format( name=self._name, image=self._image)) - @asyncio.coroutine - def _clean_servers(self): + async def _clean_servers(self): """ Clean the list of running console servers """ + if len(self._telnet_servers) > 0: for telnet_server in self._telnet_servers: telnet_server.close() - yield from telnet_server.wait_closed() + await telnet_server.wait_closed() self._telnet_servers = [] - @asyncio.coroutine - def stop(self): - """Stops this Docker container.""" + async def stop(self): + """ + Stops this Docker container. + """ try: - yield from self._clean_servers() - yield from self._stop_ubridge() + await self._clean_servers() + await self._stop_ubridge() try: - state = yield from self._get_container_state() + state = await self._get_container_state() except DockerHttp404Error: self.status = "stopped" return if state == "paused": - yield from self.unpause() + await self.unpause() - yield from self._fix_permissions() - state = yield from self._get_container_state() + if not self._permissions_fixed: + await self._fix_permissions() + + state = await self._get_container_state() if state != "stopped" or state != "exited": # t=5 number of seconds to wait before killing the container try: - yield from self.manager.query("POST", "containers/{}/stop".format(self._cid), params={"t": 5}) - log.info("Docker container '{name}' [{image}] stopped".format( - name=self._name, image=self._image)) + await self.manager.query("POST", "containers/{}/stop".format(self._cid), params={"t": 5}) + log.info("Docker container '{name}' [{image}] stopped".format(name=self._name, image=self._image)) except DockerHttp304Error: # Container is already stopped pass @@ -606,67 +781,84 @@ class DockerVM(BaseNode): return self.status = "stopped" - @asyncio.coroutine - def pause(self): - """Pauses this Docker container.""" - yield from self.manager.query("POST", "containers/{}/pause".format(self._cid)) + async def pause(self): + """ + Pauses this Docker container. + """ + + await self.manager.query("POST", "containers/{}/pause".format(self._cid)) self.status = "suspended" log.info("Docker container '{name}' [{image}] paused".format(name=self._name, image=self._image)) - @asyncio.coroutine - def unpause(self): - """Unpauses this Docker container.""" - yield from self.manager.query("POST", "containers/{}/unpause".format(self._cid)) + async def unpause(self): + """ + Unpauses this Docker container. + """ + + await self.manager.query("POST", "containers/{}/unpause".format(self._cid)) self.status = "started" log.info("Docker container '{name}' [{image}] unpaused".format(name=self._name, image=self._image)) - @asyncio.coroutine - def close(self): - """Closes this Docker container.""" + async def close(self): + """ + Closes this Docker container. + """ - if not (yield from super().close()): + self._closing = True + if not (await super().close()): return False - yield from self.reset() + await self.reset() + + async def reset(self, release_nio_udp_ports=True): - @asyncio.coroutine - def reset(self): try: - state = yield from self._get_container_state() + state = await self._get_container_state() if state == "paused" or state == "running": - yield from self.stop() + await self.stop() + if self.console_type == "vnc": - if self._x11vnc_process: + if self._vnc_process: try: - self._x11vnc_process.terminate() - yield from self._x11vnc_process.wait() + self._vnc_process.terminate() + await self._vnc_process.wait() except ProcessLookupError: pass + if self._xvfb_process: try: self._xvfb_process.terminate() - yield from self._xvfb_process.wait() + await self._xvfb_process.wait() except ProcessLookupError: pass + + if self._display: + display = "/tmp/.X11-unix/X{}".format(self._display) + try: + if os.path.exists(display): + os.remove(display) + except OSError as e: + log.warning("Could not remove display {}: {}".format(display, e)) + # v – 1/True/true or 0/False/false, Remove the volumes associated to the container. Default false. # force - 1/True/true or 0/False/false, Kill then remove the container. Default false. try: - yield from self.manager.query("DELETE", "containers/{}".format(self._cid), params={"force": 1, "v": 1}) + await self.manager.query("DELETE", "containers/{}".format(self._cid), params={"force": 1, "v": 1}) except DockerError: pass log.info("Docker container '{name}' [{image}] removed".format( name=self._name, image=self._image)) - for adapter in self._ethernet_adapters: - if adapter is not None: - for nio in adapter.ports.values(): - if nio and isinstance(nio, NIOUDP): - self.manager.port_manager.release_udp_port(nio.lport, self._project) + if release_nio_udp_ports: + for adapter in self._ethernet_adapters: + if adapter is not None: + for nio in adapter.ports.values(): + if nio and isinstance(nio, NIOUDP): + self.manager.port_manager.release_udp_port(nio.lport, self._project) # Ignore runtime error because when closing the server except (DockerHttp404Error, RuntimeError) as e: log.debug("Docker error when closing: {}".format(str(e))) return - @asyncio.coroutine - def _add_ubridge_connection(self, nio, adapter_number): + async def _add_ubridge_connection(self, nio, adapter_number): """ Creates a connection in uBridge. @@ -688,48 +880,48 @@ class DockerVM(BaseNode): raise DockerError("Adapter {adapter_number} couldn't allocate interface on Docker container '{name}'. Too many Docker interfaces already exists".format(name=self.name, adapter_number=adapter_number)) bridge_name = 'bridge{}'.format(adapter_number) - yield from self._ubridge_send('bridge create {}'.format(bridge_name)) + await self._ubridge_send('bridge create {}'.format(bridge_name)) self._bridges.add(bridge_name) - yield from self._ubridge_send('bridge add_nio_tap bridge{adapter_number} {hostif}'.format(adapter_number=adapter_number, + await self._ubridge_send('bridge add_nio_tap bridge{adapter_number} {hostif}'.format(adapter_number=adapter_number, hostif=adapter.host_ifc)) log.debug("Move container %s adapter %s to namespace %s", self.name, adapter.host_ifc, self._namespace) try: - yield from self._ubridge_send('docker move_to_ns {ifc} {ns} eth{adapter}'.format(ifc=adapter.host_ifc, + await self._ubridge_send('docker move_to_ns {ifc} {ns} eth{adapter}'.format(ifc=adapter.host_ifc, ns=self._namespace, adapter=adapter_number)) except UbridgeError as e: raise UbridgeNamespaceError(e) if nio: - yield from self._connect_nio(adapter_number, nio) + await self._connect_nio(adapter_number, nio) - @asyncio.coroutine - def _get_namespace(self): - result = yield from self.manager.query("GET", "containers/{}/json".format(self._cid)) + async def _get_namespace(self): + + result = await self.manager.query("GET", "containers/{}/json".format(self._cid)) return int(result['State']['Pid']) - @asyncio.coroutine - def _connect_nio(self, adapter_number, nio): + async def _connect_nio(self, adapter_number, nio): + bridge_name = 'bridge{}'.format(adapter_number) - yield from self._ubridge_send('bridge add_nio_udp {bridge_name} {lport} {rhost} {rport}'.format(bridge_name=bridge_name, + await self._ubridge_send('bridge add_nio_udp {bridge_name} {lport} {rhost} {rport}'.format(bridge_name=bridge_name, lport=nio.lport, rhost=nio.rhost, rport=nio.rport)) if nio.capturing: - yield from self._ubridge_send('bridge start_capture {bridge_name} "{pcap_file}"'.format(bridge_name=bridge_name, + await self._ubridge_send('bridge start_capture {bridge_name} "{pcap_file}"'.format(bridge_name=bridge_name, pcap_file=nio.pcap_output_file)) - yield from self._ubridge_send('bridge start {bridge_name}'.format(bridge_name=bridge_name)) - yield from self._ubridge_apply_filters(bridge_name, nio.filters) - - @asyncio.coroutine - def adapter_add_nio_binding(self, adapter_number, nio): - """Adds an adapter NIO binding. + await self._ubridge_send('bridge start {bridge_name}'.format(bridge_name=bridge_name)) + await self._ubridge_apply_filters(bridge_name, nio.filters) + async def adapter_add_nio_binding(self, adapter_number, nio): + """ + Adds an adapter NIO binding. :param adapter_number: adapter number :param nio: NIO instance to add to the slot/port """ + try: adapter = self._ethernet_adapters[adapter_number] except IndexError: @@ -737,7 +929,7 @@ class DockerVM(BaseNode): adapter_number=adapter_number)) if self.status == "started" and self.ubridge: - yield from self._connect_nio(adapter_number, nio) + await self._connect_nio(adapter_number, nio) adapter.add_nio(0, nio) log.info("Docker container '{name}' [{id}]: {nio} added to adapter {adapter_number}".format(name=self.name, @@ -745,22 +937,20 @@ class DockerVM(BaseNode): nio=nio, adapter_number=adapter_number)) - @asyncio.coroutine - def adapter_update_nio_binding(self, adapter_number, nio): + async def adapter_update_nio_binding(self, adapter_number, nio): """ - Update a port NIO binding. + Update an adapter NIO binding. :param adapter_number: adapter number - :param nio: NIO instance to add to the adapter + :param nio: NIO instance to update the adapter """ if self.ubridge: bridge_name = 'bridge{}'.format(adapter_number) if bridge_name in self._bridges: - yield from self._ubridge_apply_filters(bridge_name, nio.filters) + await self._ubridge_apply_filters(bridge_name, nio.filters) - @asyncio.coroutine - def adapter_remove_nio_binding(self, adapter_number): + async def adapter_remove_nio_binding(self, adapter_number): """ Removes an adapter NIO binding. @@ -768,17 +958,19 @@ class DockerVM(BaseNode): :returns: NIO instance """ + try: adapter = self._ethernet_adapters[adapter_number] except IndexError: raise DockerError("Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format(name=self.name, adapter_number=adapter_number)) + await self.stop_capture(adapter_number) if self.ubridge: nio = adapter.get_nio(0) bridge_name = 'bridge{}'.format(adapter_number) - yield from self._ubridge_send("bridge stop {}".format(bridge_name)) - yield from self._ubridge_send('bridge remove_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number, + await self._ubridge_send("bridge stop {}".format(bridge_name)) + await self._ubridge_send('bridge remove_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number, lport=nio.lport, rhost=nio.rhost, rport=nio.rport)) @@ -790,18 +982,43 @@ class DockerVM(BaseNode): nio=adapter.host_ifc, adapter_number=adapter_number)) + def get_nio(self, adapter_number): + """ + Gets an adapter NIO binding. + + :param adapter_number: adapter number + + :returns: NIO instance + """ + + try: + adapter = self._ethernet_adapters[adapter_number] + except KeyError: + raise DockerError("Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format(name=self.name, + adapter_number=adapter_number)) + + nio = adapter.get_nio(0) + + if not nio: + raise DockerError("Adapter {} is not connected".format(adapter_number)) + + return nio + @property def adapters(self): - """Returns the number of Ethernet adapters for this Docker VM. + """ + Returns the number of Ethernet adapters for this Docker VM. :returns: number of adapters :rtype: int """ + return len(self._ethernet_adapters) @adapters.setter def adapters(self, adapters): - """Sets the number of Ethernet adapters for this Docker container. + """ + Sets the number of Ethernet adapters for this Docker container. :param adapters: number of adapters """ @@ -817,19 +1034,18 @@ class DockerVM(BaseNode): id=self._id, adapters=adapters)) - @asyncio.coroutine - def pull_image(self, image): + async def pull_image(self, image): """ - Pull image from docker repository + Pulls an image from Docker repository """ + def callback(msg): self.project.emit("log.info", {"message": msg}) - yield from self.manager.pull_image(image, progress_callback=callback) + await self.manager.pull_image(image, progress_callback=callback) - @asyncio.coroutine - def _start_ubridge_capture(self, adapter_number, output_file): + async def _start_ubridge_capture(self, adapter_number, output_file): """ - Start a packet capture in uBridge. + Starts a packet capture in uBridge. :param adapter_number: adapter number :param output_file: PCAP destination file for the capture @@ -838,12 +1054,11 @@ class DockerVM(BaseNode): adapter = "bridge{}".format(adapter_number) if not self.ubridge: raise DockerError("Cannot start the packet capture: uBridge is not running") - yield from self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name=adapter, output_file=output_file)) + await self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name=adapter, output_file=output_file)) - @asyncio.coroutine - def _stop_ubridge_capture(self, adapter_number): + async def _stop_ubridge_capture(self, adapter_number): """ - Stop a packet capture in uBridge. + Stops a packet capture in uBridge. :param adapter_number: adapter number """ @@ -851,10 +1066,9 @@ class DockerVM(BaseNode): adapter = "bridge{}".format(adapter_number) if not self.ubridge: raise DockerError("Cannot stop the packet capture: uBridge is not running") - yield from self._ubridge_send("bridge stop_capture {name}".format(name=adapter)) + await self._ubridge_send("bridge stop_capture {name}".format(name=adapter)) - @asyncio.coroutine - def start_capture(self, adapter_number, output_file): + async def start_capture(self, adapter_number, output_file): """ Starts a packet capture. @@ -862,71 +1076,50 @@ class DockerVM(BaseNode): :param output_file: PCAP destination file for the capture """ - try: - adapter = self._ethernet_adapters[adapter_number] - except KeyError: - raise DockerError("Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format(name=self.name, - adapter_number=adapter_number)) - - nio = adapter.get_nio(0) - - if not nio: - raise DockerError("Adapter {} is not connected".format(adapter_number)) - + nio = self.get_nio(adapter_number) if nio.capturing: raise DockerError("Packet capture is already activated on adapter {adapter_number}".format(adapter_number=adapter_number)) - nio.startPacketCapture(output_file) - + nio.start_packet_capture(output_file) if self.status == "started" and self.ubridge: - yield from self._start_ubridge_capture(adapter_number, output_file) + await self._start_ubridge_capture(adapter_number, output_file) log.info("Docker VM '{name}' [{id}]: starting packet capture on adapter {adapter_number}".format(name=self.name, id=self.id, adapter_number=adapter_number)) - def stop_capture(self, adapter_number): + async def stop_capture(self, adapter_number): """ Stops a packet capture. :param adapter_number: adapter number """ - try: - adapter = self._ethernet_adapters[adapter_number] - except KeyError: - raise DockerError("Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format(name=self.name, - adapter_number=adapter_number)) - - nio = adapter.get_nio(0) - - if not nio: - raise DockerError("Adapter {} is not connected".format(adapter_number)) - - nio.stopPacketCapture() - + nio = self.get_nio(adapter_number) + if not nio.capturing: + return + nio.stop_packet_capture() if self.status == "started" and self.ubridge: - yield from self._stop_ubridge_capture(adapter_number) + await self._stop_ubridge_capture(adapter_number) log.info("Docker VM '{name}' [{id}]: stopping packet capture on adapter {adapter_number}".format(name=self.name, id=self.id, adapter_number=adapter_number)) - @asyncio.coroutine - def _get_log(self): + async def _get_log(self): """ - Return the log from the container + Returns the log from the container :returns: string """ - result = yield from self.manager.query("GET", "containers/{}/logs".format(self._cid), params={"stderr": 1, "stdout": 1}) + result = await self.manager.query("GET", "containers/{}/logs".format(self._cid), params={"stderr": 1, "stdout": 1}) return result - @asyncio.coroutine - def delete(self): + async def delete(self): """ - Delete the VM (including all its files). + Deletes the VM (including all its files). """ - yield from self.close() - yield from super().delete() + + await self.close() + await super().delete() diff --git a/gns3server/compute/docker/resources/init.sh b/gns3server/compute/docker/resources/init.sh index ee98bebd..bc33ea1c 100755 --- a/gns3server/compute/docker/resources/init.sh +++ b/gns3server/compute/docker/resources/init.sh @@ -20,7 +20,7 @@ # the start command of the container # OLD_PATH="$PATH" -PATH=/gns3/bin:/tmp/gns3/bin +PATH=/gns3/bin:/tmp/gns3/bin:/sbin # bootstrap busybox commands if [ ! -d /tmp/gns3/bin ]; then @@ -60,6 +60,14 @@ ff02::1 ip6-allnodes ff02::2 ip6-allrouters __EOF__ +# imitate docker's `ExtraHosts` behaviour +sed -i '/GNS3_EXTRA_HOSTS_START/,/GNS3_EXTRA_HOSTS_END/d' /etc/hosts +[ -n "$GNS3_EXTRA_HOSTS" ] && cat >> /etc/hosts << __EOF__ +# GNS3_EXTRA_HOSTS_START +$GNS3_EXTRA_HOSTS +# GNS3_EXTRA_HOSTS_END +__EOF__ + # configure loopback interface ip link set dev lo up @@ -79,6 +87,9 @@ done ifup -a -f # continue normal docker startup -PATH="$OLD_PATH" -exec "$@" - +GNS3_CMD="PATH=$OLD_PATH exec" +while test "$#" -gt 0 ; do + GNS3_CMD="${GNS3_CMD} \"${1//\"/\\\"}\"" + shift +done +exec su ${GNS3_USER-root} -p -c "$GNS3_CMD" diff --git a/gns3server/compute/dynamips/__init__.py b/gns3server/compute/dynamips/__init__.py index 0254d969..c7b35147 100644 --- a/gns3server/compute/dynamips/__init__.py +++ b/gns3server/compute/dynamips/__init__.py @@ -165,17 +165,16 @@ class Dynamips(BaseManager): if dynamips_id in self._dynamips_ids[project_id]: self._dynamips_ids[project_id].remove(dynamips_id) - @asyncio.coroutine - def unload(self): + async def unload(self): - yield from BaseManager.unload(self) + await BaseManager.unload(self) tasks = [] for device in self._devices.values(): - tasks.append(asyncio.async(device.hypervisor.stop())) + tasks.append(asyncio.ensure_future(device.hypervisor.stop())) if tasks: - done, _ = yield from asyncio.wait(tasks) + done, _ = await asyncio.wait(tasks) for future in done: try: future.result() @@ -183,37 +182,35 @@ class Dynamips(BaseManager): log.error("Could not stop device hypervisor {}".format(e), exc_info=1) continue - @asyncio.coroutine - def project_closing(self, project): + async def project_closing(self, project): """ Called when a project is about to be closed. :param project: Project instance """ - yield from super().project_closing(project) + await super().project_closing(project) # delete the Dynamips devices corresponding to the project tasks = [] for device in self._devices.values(): if device.project.id == project.id: - tasks.append(asyncio.async(device.delete())) + tasks.append(asyncio.ensure_future(device.delete())) if tasks: - done, _ = yield from asyncio.wait(tasks) + done, _ = await asyncio.wait(tasks) for future in done: try: future.result() except (Exception, GeneratorExit) as e: log.error("Could not delete device {}".format(e), exc_info=1) - @asyncio.coroutine - def project_closed(self, project): + async def project_closed(self, project): """ Called when a project is closed. :param project: Project instance """ - yield from super().project_closed(project) + await super().project_closed(project) # delete useless Dynamips files project_dir = project.module_working_path(self.module_name.lower()) @@ -229,9 +226,9 @@ class Dynamips(BaseManager): log.debug("Deleting file {}".format(file)) if file in self._ghost_files: self._ghost_files.remove(file) - yield from wait_run_in_executor(os.remove, file) + await wait_run_in_executor(os.remove, file) except OSError as e: - log.warn("Could not delete file {}: {}".format(file, e)) + log.warning("Could not delete file {}: {}".format(file, e)) continue # Release the dynamips ids if we want to reload the same project @@ -266,8 +263,7 @@ class Dynamips(BaseManager): self._dynamips_path = dynamips_path return dynamips_path - @asyncio.coroutine - def start_new_hypervisor(self, working_dir=None): + async def start_new_hypervisor(self, working_dir=None): """ Creates a new Dynamips process and start it. @@ -305,27 +301,25 @@ class Dynamips(BaseManager): hypervisor = Hypervisor(self._dynamips_path, working_dir, server_host, port, port_manager.console_host) log.info("Creating new hypervisor {}:{} with working directory {}".format(hypervisor.host, hypervisor.port, working_dir)) - yield from hypervisor.start() + await hypervisor.start() log.info("Hypervisor {}:{} has successfully started".format(hypervisor.host, hypervisor.port)) - yield from hypervisor.connect() + await hypervisor.connect() if parse_version(hypervisor.version) < parse_version('0.2.11'): raise DynamipsError("Dynamips version must be >= 0.2.11, detected version is {}".format(hypervisor.version)) return hypervisor - @asyncio.coroutine - def ghost_ios_support(self, vm): + async def ghost_ios_support(self, vm): ghost_ios_support = self.config.get_section_config("Dynamips").getboolean("ghost_ios_support", True) if ghost_ios_support: - with (yield from Dynamips._ghost_ios_lock): + async with Dynamips._ghost_ios_lock: try: - yield from self._set_ghost_ios(vm) + await self._set_ghost_ios(vm) except GeneratorExit: log.warning("Could not create ghost IOS image {} (GeneratorExit)".format(vm.name)) - @asyncio.coroutine - def create_nio(self, node, nio_settings): + async def create_nio(self, node, nio_settings): """ Creates a new NIO. @@ -350,7 +344,9 @@ class Dynamips(BaseManager): sock.connect(sa) except OSError as e: raise DynamipsError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e)) - nio = NIOUDP(node, lport, rhost, rport, nio_settings.get("filters", {})) + nio = NIOUDP(node, lport, rhost, rport) + nio.filters = nio_settings.get("filters", {}) + nio.suspend = nio_settings.get("suspend", False) elif nio_settings["type"] == "nio_generic_ethernet": ethernet_device = nio_settings["ethernet_device"] if sys.platform.startswith("win"): @@ -391,11 +387,10 @@ class Dynamips(BaseManager): else: raise aiohttp.web.HTTPConflict(text="NIO of type {} is not supported".format(nio_settings["type"])) - yield from nio.create() + await nio.create() return nio - @asyncio.coroutine - def _set_ghost_ios(self, vm): + async def _set_ghost_ios(self, vm): """ Manages Ghost IOS support. @@ -418,29 +413,28 @@ class Dynamips(BaseManager): ghost_id = str(uuid4()) ghost = Router("ghost-" + ghost_file, ghost_id, vm.project, vm.manager, platform=vm.platform, hypervisor=vm.hypervisor, ghost_flag=True) try: - yield from ghost.create() - yield from ghost.set_image(vm.image) - yield from ghost.set_ghost_status(1) - yield from ghost.set_ghost_file(ghost_file_path) - yield from ghost.set_ram(vm.ram) + await ghost.create() + await ghost.set_image(vm.image) + await ghost.set_ghost_status(1) + await ghost.set_ghost_file(ghost_file_path) + await ghost.set_ram(vm.ram) try: - yield from ghost.start() - yield from ghost.stop() + await ghost.start() + await ghost.stop() self._ghost_files.add(ghost_file_path) except DynamipsError: raise finally: - yield from ghost.clean_delete() + await ghost.clean_delete() except DynamipsError as e: - log.warn("Could not create ghost instance: {}".format(e)) + log.warning("Could not create ghost instance: {}".format(e)) if vm.ghost_file != ghost_file and os.path.isfile(ghost_file_path): # set the ghost file to the router - yield from vm.set_ghost_status(2) - yield from vm.set_ghost_file(ghost_file_path) + await vm.set_ghost_status(2) + await vm.set_ghost_file(ghost_file_path) - @asyncio.coroutine - def update_vm_settings(self, vm, settings): + async def update_vm_settings(self, vm, settings): """ Updates the VM settings. @@ -452,23 +446,23 @@ class Dynamips(BaseManager): if hasattr(vm, name) and getattr(vm, name) != value: if hasattr(vm, "set_{}".format(name)): setter = getattr(vm, "set_{}".format(name)) - yield from setter(value) + await setter(value) elif name.startswith("slot") and value in ADAPTER_MATRIX: slot_id = int(name[-1]) adapter_name = value adapter = ADAPTER_MATRIX[adapter_name]() try: if vm.slots[slot_id] and not isinstance(vm.slots[slot_id], type(adapter)): - yield from vm.slot_remove_binding(slot_id) + await vm.slot_remove_binding(slot_id) if not isinstance(vm.slots[slot_id], type(adapter)): - yield from vm.slot_add_binding(slot_id, adapter) + await vm.slot_add_binding(slot_id, adapter) except IndexError: raise DynamipsError("Slot {} doesn't exist on this router".format(slot_id)) elif name.startswith("slot") and (value is None or value is ""): slot_id = int(name[-1]) try: if vm.slots[slot_id]: - yield from vm.slot_remove_binding(slot_id) + await vm.slot_remove_binding(slot_id) except IndexError: raise DynamipsError("Slot {} doesn't exist on this router".format(slot_id)) elif name.startswith("wic") and value in WIC_MATRIX: @@ -477,32 +471,35 @@ class Dynamips(BaseManager): wic = WIC_MATRIX[wic_name]() try: if vm.slots[0].wics[wic_slot_id] and not isinstance(vm.slots[0].wics[wic_slot_id], type(wic)): - yield from vm.uninstall_wic(wic_slot_id) + await vm.uninstall_wic(wic_slot_id) if not isinstance(vm.slots[0].wics[wic_slot_id], type(wic)): - yield from vm.install_wic(wic_slot_id, wic) + await vm.install_wic(wic_slot_id, wic) except IndexError: raise DynamipsError("WIC slot {} doesn't exist on this router".format(wic_slot_id)) elif name.startswith("wic") and (value is None or value is ""): wic_slot_id = int(name[-1]) try: if vm.slots[0].wics and vm.slots[0].wics[wic_slot_id]: - yield from vm.uninstall_wic(wic_slot_id) + await vm.uninstall_wic(wic_slot_id) except IndexError: raise DynamipsError("WIC slot {} doesn't exist on this router".format(wic_slot_id)) mmap_support = self.config.get_section_config("Dynamips").getboolean("mmap_support", True) if mmap_support is False: - yield from vm.set_mmap(False) + await vm.set_mmap(False) sparse_memory_support = self.config.get_section_config("Dynamips").getboolean("sparse_memory_support", True) if sparse_memory_support is False: - yield from vm.set_sparsemem(False) + await vm.set_sparsemem(False) + + usage = settings.get("usage") + if usage and usage != vm.usage: + vm.usage = usage # update the configs if needed - yield from self.set_vm_configs(vm, settings) + await self.set_vm_configs(vm, settings) - @asyncio.coroutine - def set_vm_configs(self, vm, settings): + async def set_vm_configs(self, vm, settings): """ Set VM configs from pushed content or existing config files. @@ -551,39 +548,41 @@ class Dynamips(BaseManager): return os.path.join("configs", os.path.basename(path)) - @asyncio.coroutine - def auto_idlepc(self, vm): + async def auto_idlepc(self, vm): """ Try to find the best possible idle-pc value. :param vm: VM instance """ - yield from vm.set_idlepc("0x0") + await vm.set_idlepc("0x0") was_auto_started = False + old_priority = None try: - status = yield from vm.get_status() + status = await vm.get_status() if status != "running": - yield from vm.start() + await vm.start() was_auto_started = True - yield from asyncio.sleep(20) # leave time to the router to boot + await asyncio.sleep(20) # leave time to the router to boot validated_idlepc = None - idlepcs = yield from vm.get_idle_pc_prop() + idlepcs = await vm.get_idle_pc_prop() if not idlepcs: raise DynamipsError("No Idle-PC values found") + if sys.platform.startswith("win"): + old_priority = vm.set_process_priority_windows(vm.hypervisor.process.pid) for idlepc in idlepcs: match = re.search(r"^0x[0-9a-f]{8}$", idlepc.split()[0]) if not match: continue - yield from vm.set_idlepc(idlepc.split()[0]) + await vm.set_idlepc(idlepc.split()[0]) log.debug("Auto Idle-PC: trying idle-PC value {}".format(vm.idlepc)) start_time = time.time() - initial_cpu_usage = yield from vm.get_cpu_usage() + initial_cpu_usage = await vm.get_cpu_usage() log.debug("Auto Idle-PC: initial CPU usage is {}%".format(initial_cpu_usage)) - yield from asyncio.sleep(3) # wait 3 seconds to probe the cpu again + await asyncio.sleep(3) # wait 3 seconds to probe the cpu again elapsed_time = time.time() - start_time - cpu_usage = yield from vm.get_cpu_usage() + cpu_usage = await vm.get_cpu_usage() cpu_elapsed_usage = cpu_usage - initial_cpu_usage cpu_usage = abs(cpu_elapsed_usage * 100.0 / elapsed_time) if cpu_usage > 100: @@ -600,12 +599,13 @@ class Dynamips(BaseManager): except DynamipsError: raise finally: + if old_priority is not None: + vm.set_process_priority_windows(vm.hypervisor.process.pid, old_priority) if was_auto_started: - yield from vm.stop() + await vm.stop() return validated_idlepc - @asyncio.coroutine - def duplicate_node(self, source_node_id, destination_node_id): + async def duplicate_node(self, source_node_id, destination_node_id): """ Duplicate a node @@ -618,7 +618,7 @@ class Dynamips(BaseManager): # Not a Dynamips router if not hasattr(source_node, "startup_config_path"): - return (yield from super().duplicate_node(source_node_id, destination_node_id)) + return (await super().duplicate_node(source_node_id, destination_node_id)) try: with open(source_node.startup_config_path) as f: @@ -630,13 +630,13 @@ class Dynamips(BaseManager): private_config = f.read() except OSError: private_config = None - yield from self.set_vm_configs(destination_node, { + await self.set_vm_configs(destination_node, { "startup_config_content": startup_config, "private_config_content": private_config }) # Force refresh of the name in configuration files new_name = destination_node.name - yield from destination_node.set_name(source_node.name) - yield from destination_node.set_name(new_name) + await destination_node.set_name(source_node.name) + await destination_node.set_name(new_name) return destination_node diff --git a/gns3server/compute/dynamips/dynamips_hypervisor.py b/gns3server/compute/dynamips/dynamips_hypervisor.py index 936707d6..b21e6494 100644 --- a/gns3server/compute/dynamips/dynamips_hypervisor.py +++ b/gns3server/compute/dynamips/dynamips_hypervisor.py @@ -59,8 +59,7 @@ class DynamipsHypervisor: self._writer = None self._io_lock = asyncio.Lock() - @asyncio.coroutine - def connect(self, timeout=10): + async def connect(self, timeout=10): """ Connects to the hypervisor. """ @@ -78,9 +77,9 @@ class DynamipsHypervisor: connection_success = False last_exception = None while time.time() - begin < timeout: - yield from asyncio.sleep(0.01) + await asyncio.sleep(0.01) try: - self._reader, self._writer = yield from asyncio.wait_for(asyncio.open_connection(host, self._port), timeout=1) + self._reader, self._writer = await asyncio.wait_for(asyncio.open_connection(host, self._port), timeout=1) except (asyncio.TimeoutError, OSError) as e: last_exception = e continue @@ -90,16 +89,16 @@ class DynamipsHypervisor: if not connection_success: raise DynamipsError("Couldn't connect to hypervisor on {}:{} :{}".format(host, self._port, last_exception)) else: - log.info("Connected to Dynamips hypervisor after {:.4f} seconds".format(time.time() - begin)) + log.info("Connected to Dynamips hypervisor on {}:{} after {:.4f} seconds".format(host, self._port, time.time() - begin)) try: - version = yield from self.send("hypervisor version") + version = await self.send("hypervisor version") self._version = version[0].split("-", 1)[0] except IndexError: self._version = "Unknown" # this forces to send the working dir to Dynamips - yield from self.set_working_dir(self._working_dir) + await self.set_working_dir(self._working_dir) @property def version(self): @@ -111,45 +110,41 @@ class DynamipsHypervisor: return self._version - @asyncio.coroutine - def close(self): + async def close(self): """ Closes the connection to this hypervisor (but leave it running). """ - yield from self.send("hypervisor close") + await self.send("hypervisor close") self._writer.close() self._reader, self._writer = None - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops this hypervisor (will no longer run). """ try: # try to properly stop the hypervisor - yield from self.send("hypervisor stop") + await self.send("hypervisor stop") except DynamipsError: pass try: if self._writer is not None: - yield from self._writer.drain() + await self._writer.drain() self._writer.close() except OSError as e: log.debug("Stopping hypervisor {}:{} {}".format(self._host, self._port, e)) self._reader = self._writer = None - @asyncio.coroutine - def reset(self): + async def reset(self): """ Resets this hypervisor (used to get an empty configuration). """ - yield from self.send("hypervisor reset") + await self.send("hypervisor reset") - @asyncio.coroutine - def set_working_dir(self, working_dir): + async def set_working_dir(self, working_dir): """ Sets the working directory for this hypervisor. @@ -157,7 +152,7 @@ class DynamipsHypervisor: """ # encase working_dir in quotes to protect spaces in the path - yield from self.send('hypervisor working_dir "{}"'.format(working_dir)) + await self.send('hypervisor working_dir "{}"'.format(working_dir)) self._working_dir = working_dir log.debug("Working directory set to {}".format(self._working_dir)) @@ -221,8 +216,7 @@ class DynamipsHypervisor: self._host = host - @asyncio.coroutine - def send(self, command): + async def send(self, command): """ Sends commands to this hypervisor. @@ -244,7 +238,7 @@ class DynamipsHypervisor: # but still have more data. The only thing we know for sure is the last line # will begin with '100-' or a '2xx-' and end with '\r\n' - with (yield from self._io_lock): + async with self._io_lock: if self._writer is None or self._reader is None: raise DynamipsError("Not connected") @@ -252,7 +246,7 @@ class DynamipsHypervisor: command = command.strip() + '\n' log.debug("sending {}".format(command)) self._writer.write(command.encode()) - yield from self._writer.drain() + await self._writer.drain() except OSError as e: raise DynamipsError("Could not send Dynamips command '{command}' to {host}:{port}: {error}, process running: {run}" .format(command=command.strip(), host=self._host, port=self._port, error=e, run=self.is_running())) @@ -265,8 +259,8 @@ class DynamipsHypervisor: while True: try: try: - # line = yield from self._reader.readline() # this can lead to ValueError: Line is too long - chunk = yield from self._reader.read(1024) # match to Dynamips' buffer size + # line = await self._reader.readline() # this can lead to ValueError: Line is too long + chunk = await self._reader.read(1024) # match to Dynamips' buffer size except asyncio.CancelledError: # task has been canceled but continue to read # any remaining data sent by the hypervisor @@ -283,7 +277,7 @@ class DynamipsHypervisor: .format(host=self._host, port=self._port, run=self.is_running())) else: retries += 1 - yield from asyncio.sleep(0.1) + await asyncio.sleep(0.1) continue retries = 0 buf += chunk.decode("utf-8", errors="ignore") diff --git a/gns3server/compute/dynamips/hypervisor.py b/gns3server/compute/dynamips/hypervisor.py index a94e32df..d0ef0a2d 100644 --- a/gns3server/compute/dynamips/hypervisor.py +++ b/gns3server/compute/dynamips/hypervisor.py @@ -111,8 +111,7 @@ class Hypervisor(DynamipsHypervisor): self._path = path - @asyncio.coroutine - def start(self): + async def start(self): """ Starts the Dynamips hypervisor process. """ @@ -129,7 +128,7 @@ class Hypervisor(DynamipsHypervisor): self._stdout_file = os.path.join(self.working_dir, "dynamips_i{}_stdout.txt".format(self._id)) log.info("Dynamips process logging to {}".format(self._stdout_file)) with open(self._stdout_file, "w", encoding="utf-8") as fd: - self._process = yield from asyncio.create_subprocess_exec(*self._command, + self._process = await asyncio.create_subprocess_exec(*self._command, stdout=fd, stderr=subprocess.STDOUT, cwd=self._working_dir, @@ -140,29 +139,28 @@ class Hypervisor(DynamipsHypervisor): log.error("Could not start Dynamips: {}".format(e)) raise DynamipsError("Could not start Dynamips: {}".format(e)) - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops the Dynamips hypervisor process. """ if self.is_running(): log.info("Stopping Dynamips process PID={}".format(self._process.pid)) - yield from DynamipsHypervisor.stop(self) + await DynamipsHypervisor.stop(self) # give some time for the hypervisor to properly stop. # time to delete UNIX NIOs for instance. - yield from asyncio.sleep(0.01) + await asyncio.sleep(0.01) try: - yield from wait_for_process_termination(self._process, timeout=3) + await wait_for_process_termination(self._process, timeout=3) except asyncio.TimeoutError: if self._process.returncode is None: - log.warn("Dynamips process {} is still running... killing it".format(self._process.pid)) + log.warning("Dynamips process {} is still running... killing it".format(self._process.pid)) try: self._process.kill() except OSError as e: log.error("Cannot stop the Dynamips process: {}".format(e)) if self._process.returncode is None: - log.warn('Dynamips hypervisor with PID={} is still running'.format(self._process.pid)) + log.warning('Dynamips hypervisor with PID={} is still running'.format(self._process.pid)) if self._stdout_file and os.access(self._stdout_file, os.W_OK): try: @@ -183,7 +181,7 @@ class Hypervisor(DynamipsHypervisor): with open(self._stdout_file, "rb") as file: output = file.read().decode("utf-8", errors="replace") except OSError as e: - log.warn("could not read {}: {}".format(self._stdout_file, e)) + log.warning("could not read {}: {}".format(self._stdout_file, e)) return output def is_running(self): diff --git a/gns3server/compute/dynamips/nios/nio.py b/gns3server/compute/dynamips/nios/nio.py index 2f978f19..17ed6a83 100644 --- a/gns3server/compute/dynamips/nios/nio.py +++ b/gns3server/compute/dynamips/nios/nio.py @@ -39,6 +39,11 @@ class NIO: self._hypervisor = hypervisor self._name = name + self._filters = {} + self._suspended = False + self._capturing = False + self._pcap_output_file = "" + self._pcap_data_link_type = "" self._bandwidth = None # no bandwidth constraint by default self._input_filter = None # no input filter applied by default self._output_filter = None # no output filter applied by default @@ -46,53 +51,73 @@ class NIO: self._output_filter_options = None # no output filter options by default self._dynamips_direction = {"in": 0, "out": 1, "both": 2} - @asyncio.coroutine - def list(self): + async def list(self): """ Returns all NIOs. :returns: NIO list """ - nio_list = yield from self._hypervisor.send("nio list") + nio_list = await self._hypervisor.send("nio list") return nio_list - @asyncio.coroutine - def delete(self): + async def delete(self): """ Deletes this NIO. """ if self._input_filter or self._output_filter: - yield from self.unbind_filter("both") - yield from self._hypervisor.send("nio delete {}".format(self._name)) + await self.unbind_filter("both") + self._capturing = False + await self._hypervisor.send("nio delete {}".format(self._name)) log.info("NIO {name} has been deleted".format(name=self._name)) - @asyncio.coroutine - def rename(self, new_name): + async def rename(self, new_name): """ Renames this NIO :param new_name: new NIO name """ - yield from self._hypervisor.send("nio rename {name} {new_name}".format(name=self._name, new_name=new_name)) + await self._hypervisor.send("nio rename {name} {new_name}".format(name=self._name, new_name=new_name)) log.info("NIO {name} renamed to {new_name}".format(name=self._name, new_name=new_name)) self._name = new_name - @asyncio.coroutine - def debug(self, debug): + async def debug(self, debug): """ Enables/Disables debugging for this NIO. :param debug: debug value (0 = disable, enable = 1) """ - yield from self._hypervisor.send("nio set_debug {name} {debug}".format(name=self._name, debug=debug)) + await self._hypervisor.send("nio set_debug {name} {debug}".format(name=self._name, debug=debug)) - @asyncio.coroutine - def bind_filter(self, direction, filter_name): + async def start_packet_capture(self, pcap_output_file, pcap_data_link_type="DLT_EN10MB"): + """ + Starts a packet capture. + + :param pcap_output_file: PCAP destination file for the capture + :param pcap_data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB + """ + + await self.bind_filter("both", "capture") + await self.setup_filter("both", '{} "{}"'.format(pcap_data_link_type, pcap_output_file)) + self._capturing = True + self._pcap_output_file = pcap_output_file + self._pcap_data_link_type = pcap_data_link_type + + async def stop_packet_capture(self): + """ + Stops a packet capture. + """ + + await self.unbind_filter("both") + self._capturing = False + self._pcap_output_file = "" + self._pcap_data_link_type = "" + + async def bind_filter(self, direction, filter_name): """ Adds a packet filter to this NIO. Filter "freq_drop" drops packets. @@ -106,7 +131,7 @@ class NIO: raise DynamipsError("Unknown direction {} to bind filter {}:".format(direction, filter_name)) dynamips_direction = self._dynamips_direction[direction] - yield from self._hypervisor.send("nio bind_filter {name} {direction} {filter}".format(name=self._name, + await self._hypervisor.send("nio bind_filter {name} {direction} {filter}".format(name=self._name, direction=dynamips_direction, filter=filter_name)) @@ -118,8 +143,7 @@ class NIO: self._input_filter = filter_name self._output_filter = filter_name - @asyncio.coroutine - def unbind_filter(self, direction): + async def unbind_filter(self, direction): """ Removes packet filter for this NIO. @@ -130,7 +154,7 @@ class NIO: raise DynamipsError("Unknown direction {} to unbind filter:".format(direction)) dynamips_direction = self._dynamips_direction[direction] - yield from self._hypervisor.send("nio unbind_filter {name} {direction}".format(name=self._name, + await self._hypervisor.send("nio unbind_filter {name} {direction}".format(name=self._name, direction=dynamips_direction)) if direction == "in": @@ -140,9 +164,9 @@ class NIO: elif direction == "both": self._input_filter = None self._output_filter = None + self._capturing = False - @asyncio.coroutine - def setup_filter(self, direction, options): + async def setup_filter(self, direction, options): """ Setups a packet filter bound with this NIO. @@ -164,7 +188,7 @@ class NIO: raise DynamipsError("Unknown direction {} to setup filter:".format(direction)) dynamips_direction = self._dynamips_direction[direction] - yield from self._hypervisor.send("nio setup_filter {name} {direction} {options}".format(name=self._name, + await self._hypervisor.send("nio setup_filter {name} {direction} {options}".format(name=self._name, direction=dynamips_direction, options=options)) @@ -196,24 +220,22 @@ class NIO: return self._output_filter, self._output_filter_options - @asyncio.coroutine - def get_stats(self): + async def get_stats(self): """ Gets statistics for this NIO. :returns: NIO statistics (string with packets in, packets out, bytes in, bytes out) """ - stats = yield from self._hypervisor.send("nio get_stats {}".format(self._name)) + stats = await self._hypervisor.send("nio get_stats {}".format(self._name)) return stats[0] - @asyncio.coroutine - def reset_stats(self): + async def reset_stats(self): """ Resets statistics for this NIO. """ - yield from self._hypervisor.send("nio reset_stats {}".format(self._name)) + await self._hypervisor.send("nio reset_stats {}".format(self._name)) @property def bandwidth(self): @@ -225,17 +247,86 @@ class NIO: return self._bandwidth - @asyncio.coroutine - def set_bandwidth(self, bandwidth): + async def set_bandwidth(self, bandwidth): """ Sets bandwidth constraint. :param bandwidth: bandwidth integer value (in Kb/s) """ - yield from self._hypervisor.send("nio set_bandwidth {name} {bandwidth}".format(name=self._name, bandwidth=bandwidth)) + await self._hypervisor.send("nio set_bandwidth {name} {bandwidth}".format(name=self._name, bandwidth=bandwidth)) self._bandwidth = bandwidth + @property + def suspend(self): + """ + Returns if this link is suspended or not. + + :returns: boolean + """ + + return self._suspended + + @suspend.setter + def suspend(self, suspended): + """ + Suspend this link. + + :param suspended: boolean + """ + + self._suspended = suspended + + @property + def filters(self): + """ + Returns the list of packet filters for this NIO. + + :returns: packet filters (dictionary) + """ + + return self._filters + + @filters.setter + def filters(self, new_filters): + """ + Set a list of packet filters for this NIO. + + :param new_filters: packet filters (dictionary) + """ + + assert isinstance(new_filters, dict) + self._filters = new_filters + + @property + def capturing(self): + """ + Returns either a capture is configured on this NIO. + :returns: boolean + """ + + return self._capturing + + @property + def pcap_output_file(self): + """ + Returns the path to the PCAP output file. + + :returns: path to the PCAP output file + """ + + return self._pcap_output_file + + @property + def pcap_data_link_type(self): + """ + Returns the PCAP data link type + + :returns: PCAP data link type (DLT_* value) + """ + + return self._pcap_data_link_type + def __str__(self): """ NIO string representation. diff --git a/gns3server/compute/dynamips/nios/nio_generic_ethernet.py b/gns3server/compute/dynamips/nios/nio_generic_ethernet.py index 870ecb13..533de664 100644 --- a/gns3server/compute/dynamips/nios/nio_generic_ethernet.py +++ b/gns3server/compute/dynamips/nios/nio_generic_ethernet.py @@ -43,10 +43,9 @@ class NIOGenericEthernet(NIO): self._ethernet_device = ethernet_device super().__init__(name, hypervisor) - @asyncio.coroutine - def create(self): + async def create(self): - yield from self._hypervisor.send("nio create_gen_eth {name} {eth_device}".format(name=self._name, + await self._hypervisor.send("nio create_gen_eth {name} {eth_device}".format(name=self._name, eth_device=self._ethernet_device)) log.info("NIO Generic Ethernet {name} created with device {device}".format(name=self._name, diff --git a/gns3server/compute/dynamips/nios/nio_linux_ethernet.py b/gns3server/compute/dynamips/nios/nio_linux_ethernet.py index cf96f4af..d032202b 100644 --- a/gns3server/compute/dynamips/nios/nio_linux_ethernet.py +++ b/gns3server/compute/dynamips/nios/nio_linux_ethernet.py @@ -42,10 +42,9 @@ class NIOLinuxEthernet(NIO): self._ethernet_device = ethernet_device super().__init__(name, hypervisor) - @asyncio.coroutine - def create(self): + async def create(self): - yield from self._hypervisor.send("nio create_linux_eth {name} {eth_device}".format(name=self._name, + await self._hypervisor.send("nio create_linux_eth {name} {eth_device}".format(name=self._name, eth_device=self._ethernet_device)) log.info("NIO Linux Ethernet {name} created with device {device}".format(name=self._name, diff --git a/gns3server/compute/dynamips/nios/nio_null.py b/gns3server/compute/dynamips/nios/nio_null.py index 174dd032..6524de40 100644 --- a/gns3server/compute/dynamips/nios/nio_null.py +++ b/gns3server/compute/dynamips/nios/nio_null.py @@ -41,10 +41,9 @@ class NIONull(NIO): name = 'null-{}'.format(uuid.uuid4()) super().__init__(name, hypervisor) - @asyncio.coroutine - def create(self): + async def create(self): - yield from self._hypervisor.send("nio create_null {}".format(self._name)) + await self._hypervisor.send("nio create_null {}".format(self._name)) log.info("NIO NULL {name} created.".format(name=self._name)) def __json__(self): diff --git a/gns3server/compute/dynamips/nios/nio_tap.py b/gns3server/compute/dynamips/nios/nio_tap.py index 20fdaeaa..ea5c8926 100644 --- a/gns3server/compute/dynamips/nios/nio_tap.py +++ b/gns3server/compute/dynamips/nios/nio_tap.py @@ -43,10 +43,9 @@ class NIOTAP(NIO): self._tap_device = tap_device super().__init__(name, hypervisor) - @asyncio.coroutine - def create(self): + async def create(self): - yield from self._hypervisor.send("nio create_tap {name} {tap}".format(name=self._name, tap=self._tap_device)) + await self._hypervisor.send("nio create_tap {name} {tap}".format(name=self._name, tap=self._tap_device)) log.info("NIO TAP {name} created with device {device}".format(name=self._name, device=self._tap_device)) @property diff --git a/gns3server/compute/dynamips/nios/nio_udp.py b/gns3server/compute/dynamips/nios/nio_udp.py index 60ddafa0..987840b3 100644 --- a/gns3server/compute/dynamips/nios/nio_udp.py +++ b/gns3server/compute/dynamips/nios/nio_udp.py @@ -41,34 +41,24 @@ class NIOUDP(NIO): :param rport: remote port number """ - def __init__(self, node, lport, rhost, rport, filters): + def __init__(self, node, lport, rhost, rport): # create an unique name name = 'udp-{}'.format(uuid.uuid4()) self._lport = lport self._rhost = rhost self._rport = rport - self._filters = filters self._local_tunnel_lport = None self._local_tunnel_rport = None self._node = node super().__init__(name, node.hypervisor) - @property - def filters(self): - return self._filters - - @filters.setter - def filters(self, val): - self._filters = val - - @asyncio.coroutine - def create(self): + async def create(self): if not self._hypervisor: return # Ubridge is not supported if not hasattr(self._node, "add_ubridge_udp_connection"): - yield from self._hypervisor.send("nio create_udp {name} {lport} {rhost} {rport}".format(name=self._name, + await self._hypervisor.send("nio create_udp {name} {lport} {rhost} {rport}".format(name=self._name, lport=self._lport, rhost=self._rhost, rport=self._rport)) @@ -76,7 +66,7 @@ class NIOUDP(NIO): self._local_tunnel_lport = self._node.manager.port_manager.get_free_udp_port(self._node.project) self._local_tunnel_rport = self._node.manager.port_manager.get_free_udp_port(self._node.project) self._bridge_name = 'DYNAMIPS-{}-{}'.format(self._local_tunnel_lport, self._local_tunnel_rport) - yield from self._hypervisor.send("nio create_udp {name} {lport} {rhost} {rport}".format(name=self._name, + await self._hypervisor.send("nio create_udp {name} {lport} {rhost} {rport}".format(name=self._name, lport=self._local_tunnel_lport, rhost='127.0.0.1', rport=self._local_tunnel_rport)) @@ -88,30 +78,27 @@ class NIOUDP(NIO): self._source_nio = nio_udp.NIOUDP(self._local_tunnel_rport, '127.0.0.1', - self._local_tunnel_lport, - {}) + self._local_tunnel_lport) self._destination_nio = nio_udp.NIOUDP(self._lport, self._rhost, - self._rport, - self._filters) - yield from self._node.add_ubridge_udp_connection( + self._rport) + self._destination_nio.filters = self._filters + await self._node.add_ubridge_udp_connection( self._bridge_name, self._source_nio, self._destination_nio ) - @asyncio.coroutine - def update(self): + async def update(self): self._destination_nio.filters = self._filters - yield from self._node.update_ubridge_udp_connection( + await self._node.update_ubridge_udp_connection( self._bridge_name, self._source_nio, self._destination_nio) - @asyncio.coroutine - def close(self): + async def close(self): if self._local_tunnel_lport: - yield from self._node.ubridge_delete_bridge(self._bridge_name) + await self._node.ubridge_delete_bridge(self._bridge_name) self._node.manager.port_manager.release_udp_port(self._local_tunnel_lport, self ._node.project) if self._local_tunnel_rport: self._node.manager.port_manager.release_udp_port(self._local_tunnel_rport, self._node.project) diff --git a/gns3server/compute/dynamips/nios/nio_unix.py b/gns3server/compute/dynamips/nios/nio_unix.py index 048572a4..64eeca7b 100644 --- a/gns3server/compute/dynamips/nios/nio_unix.py +++ b/gns3server/compute/dynamips/nios/nio_unix.py @@ -45,10 +45,9 @@ class NIOUNIX(NIO): self._remote_file = remote_file super().__init__(name, hypervisor) - @asyncio.coroutine - def create(self): + async def create(self): - yield from self._hypervisor.send("nio create_unix {name} {local} {remote}".format(name=self._name, + await self._hypervisor.send("nio create_unix {name} {local} {remote}".format(name=self._name, local=self._local_file, remote=self._remote_file)) diff --git a/gns3server/compute/dynamips/nios/nio_vde.py b/gns3server/compute/dynamips/nios/nio_vde.py index 099db5a3..00701f3a 100644 --- a/gns3server/compute/dynamips/nios/nio_vde.py +++ b/gns3server/compute/dynamips/nios/nio_vde.py @@ -45,10 +45,9 @@ class NIOVDE(NIO): self._local_file = local_file super().__init__(name, hypervisor) - @asyncio.coroutine - def create(self): + async def create(self): - yield from self._hypervisor.send("nio create_vde {name} {control} {local}".format(name=self._name, + await self._hypervisor.send("nio create_vde {name} {control} {local}".format(name=self._name, control=self._control_file, local=self._local_file)) diff --git a/gns3server/compute/dynamips/nodes/atm_switch.py b/gns3server/compute/dynamips/nodes/atm_switch.py index 38cac774..d8664260 100644 --- a/gns3server/compute/dynamips/nodes/atm_switch.py +++ b/gns3server/compute/dynamips/nodes/atm_switch.py @@ -64,26 +64,24 @@ class ATMSwitch(Device): "mappings": mappings, "status": "started"} - @asyncio.coroutine - def create(self): + async def create(self): if self._hypervisor is None: module_workdir = self.project.module_working_directory(self.manager.module_name.lower()) - self._hypervisor = yield from self.manager.start_new_hypervisor(working_dir=module_workdir) + self._hypervisor = await self.manager.start_new_hypervisor(working_dir=module_workdir) - yield from self._hypervisor.send('atmsw create "{}"'.format(self._name)) + await self._hypervisor.send('atmsw create "{}"'.format(self._name)) log.info('ATM switch "{name}" [{id}] has been created'.format(name=self._name, id=self._id)) self._hypervisor.devices.append(self) - @asyncio.coroutine - def set_name(self, new_name): + async def set_name(self, new_name): """ Renames this ATM switch. :param new_name: New name for this switch """ - yield from self._hypervisor.send('atm rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) + await self._hypervisor.send('atm rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) log.info('ATM switch "{name}" [{id}]: renamed to "{new_name}"'.format(name=self._name, id=self._id, new_name=new_name)) @@ -119,31 +117,29 @@ class ATMSwitch(Device): self._mappings = mappings - @asyncio.coroutine - def close(self): + async def close(self): for nio in self._nios.values(): if nio: - yield from nio.close() + await nio.close() if self._hypervisor: try: - yield from self._hypervisor.send('atmsw delete "{}"'.format(self._name)) + await self._hypervisor.send('atmsw delete "{}"'.format(self._name)) log.info('ATM switch "{name}" [{id}] has been deleted'.format(name=self._name, id=self._id)) except DynamipsError: log.debug("Could not properly delete ATM switch {}".format(self._name)) if self._hypervisor and self in self._hypervisor.devices: self._hypervisor.devices.remove(self) if self._hypervisor and not self._hypervisor.devices: - yield from self.hypervisor.stop() + await self.hypervisor.stop() self._hypervisor = None return True - @asyncio.coroutine - def delete(self): + async def delete(self): """ Deletes this ATM switch. """ - yield from self.close() + await self.close() def has_port(self, port): """ @@ -156,8 +152,7 @@ class ATMSwitch(Device): return True return False - @asyncio.coroutine - def add_nio(self, nio, port_number): + async def add_nio(self, nio, port_number): """ Adds a NIO as new port on ATM switch. @@ -174,10 +169,9 @@ class ATMSwitch(Device): port=port_number)) self._nios[port_number] = nio - yield from self.set_mappings(self._mappings) + await self.set_mappings(self._mappings) - @asyncio.coroutine - def remove_nio(self, port_number): + async def remove_nio(self, port_number): """ Removes the specified NIO as member of this ATM switch. @@ -187,6 +181,7 @@ class ATMSwitch(Device): if port_number not in self._nios: raise DynamipsError("Port {} is not allocated".format(port_number)) + await self.stop_capture(port_number) # remove VCs mapped with the port for source, destination in self._active_mappings.copy().items(): if len(source) == 3 and len(destination) == 3: @@ -202,8 +197,8 @@ class ATMSwitch(Device): destination_port=destination_port, destination_vpi=destination_vpi, destination_vci=destination_vci)) - yield from self.unmap_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci) - yield from self.unmap_pvc(destination_port, destination_vpi, destination_vci, source_port, source_vpi, source_vci) + await self.unmap_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci) + await self.unmap_pvc(destination_port, destination_vpi, destination_vci, source_port, source_vpi, source_vci) else: # remove the virtual paths mapped with this port/nio source_port, source_vpi = source @@ -215,8 +210,8 @@ class ATMSwitch(Device): source_vpi=source_vpi, destination_port=destination_port, destination_vpi=destination_vpi)) - yield from self.unmap_vp(source_port, source_vpi, destination_port, destination_vpi) - yield from self.unmap_vp(destination_port, destination_vpi, source_port, source_vpi) + await self.unmap_vp(source_port, source_vpi, destination_port, destination_vpi) + await self.unmap_vp(destination_port, destination_vpi, source_port, source_vpi) nio = self._nios[port_number] if isinstance(nio, NIOUDP): @@ -229,8 +224,26 @@ class ATMSwitch(Device): del self._nios[port_number] return nio - @asyncio.coroutine - def set_mappings(self, mappings): + def get_nio(self, port_number): + """ + Gets a port NIO binding. + + :param port_number: port number + + :returns: NIO instance + """ + + if port_number not in self._nios: + raise DynamipsError("Port {} is not allocated".format(port_number)) + + nio = self._nios[port_number] + + if not nio: + raise DynamipsError("Port {} is not connected".format(port_number)) + + return nio + + async def set_mappings(self, mappings): """ Applies VC mappings @@ -258,8 +271,8 @@ class ATMSwitch(Device): destination_port=destination_port, destination_vpi=destination_vpi, destination_vci=destination_vci)) - yield from self.map_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci) - yield from self.map_pvc(destination_port, destination_vpi, destination_vci, source_port, source_vpi, source_vci) + await self.map_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci) + await self.map_pvc(destination_port, destination_vpi, destination_vci, source_port, source_vpi, source_vci) else: # add the virtual paths source_port, source_vpi = map(int, source.split(':')) @@ -272,11 +285,10 @@ class ATMSwitch(Device): source_vpi=source_vpi, destination_port=destination_port, destination_vpi=destination_vpi)) - yield from self.map_vp(source_port, source_vpi, destination_port, destination_vpi) - yield from self.map_vp(destination_port, destination_vpi, source_port, source_vpi) + await self.map_vp(source_port, source_vpi, destination_port, destination_vpi) + await self.map_vp(destination_port, destination_vpi, source_port, source_vpi) - @asyncio.coroutine - def map_vp(self, port1, vpi1, port2, vpi2): + async def map_vp(self, port1, vpi1, port2, vpi2): """ Creates a new Virtual Path connection. @@ -295,7 +307,7 @@ class ATMSwitch(Device): nio1 = self._nios[port1] nio2 = self._nios[port2] - yield from self._hypervisor.send('atmsw create_vpc "{name}" {input_nio} {input_vpi} {output_nio} {output_vpi}'.format(name=self._name, + await self._hypervisor.send('atmsw create_vpc "{name}" {input_nio} {input_vpi} {output_nio} {output_vpi}'.format(name=self._name, input_nio=nio1, input_vpi=vpi1, output_nio=nio2, @@ -310,8 +322,7 @@ class ATMSwitch(Device): self._active_mappings[(port1, vpi1)] = (port2, vpi2) - @asyncio.coroutine - def unmap_vp(self, port1, vpi1, port2, vpi2): + async def unmap_vp(self, port1, vpi1, port2, vpi2): """ Deletes a new Virtual Path connection. @@ -330,7 +341,7 @@ class ATMSwitch(Device): nio1 = self._nios[port1] nio2 = self._nios[port2] - yield from self._hypervisor.send('atmsw delete_vpc "{name}" {input_nio} {input_vpi} {output_nio} {output_vpi}'.format(name=self._name, + await self._hypervisor.send('atmsw delete_vpc "{name}" {input_nio} {input_vpi} {output_nio} {output_vpi}'.format(name=self._name, input_nio=nio1, input_vpi=vpi1, output_nio=nio2, @@ -345,8 +356,7 @@ class ATMSwitch(Device): del self._active_mappings[(port1, vpi1)] - @asyncio.coroutine - def map_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2): + async def map_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2): """ Creates a new Virtual Channel connection (unidirectional). @@ -367,7 +377,7 @@ class ATMSwitch(Device): nio1 = self._nios[port1] nio2 = self._nios[port2] - yield from self._hypervisor.send('atmsw create_vcc "{name}" {input_nio} {input_vpi} {input_vci} {output_nio} {output_vpi} {output_vci}'.format(name=self._name, + await self._hypervisor.send('atmsw create_vcc "{name}" {input_nio} {input_vpi} {input_vci} {output_nio} {output_vpi} {output_vci}'.format(name=self._name, input_nio=nio1, input_vpi=vpi1, input_vci=vci1, @@ -386,8 +396,7 @@ class ATMSwitch(Device): self._active_mappings[(port1, vpi1, vci1)] = (port2, vpi2, vci2) - @asyncio.coroutine - def unmap_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2): + async def unmap_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2): """ Deletes a new Virtual Channel connection (unidirectional). @@ -408,7 +417,7 @@ class ATMSwitch(Device): nio1 = self._nios[port1] nio2 = self._nios[port2] - yield from self._hypervisor.send('atmsw delete_vcc "{name}" {input_nio} {input_vpi} {input_vci} {output_nio} {output_vpi} {output_vci}'.format(name=self._name, + await self._hypervisor.send('atmsw delete_vcc "{name}" {input_nio} {input_vpi} {input_vci} {output_nio} {output_vpi} {output_vci}'.format(name=self._name, input_nio=nio1, input_vpi=vpi1, input_vci=vci1, @@ -426,8 +435,7 @@ class ATMSwitch(Device): vci2=vci2)) del self._active_mappings[(port1, vpi1, vci1)] - @asyncio.coroutine - def start_capture(self, port_number, output_file, data_link_type="DLT_ATM_RFC1483"): + async def start_capture(self, port_number, output_file, data_link_type="DLT_ATM_RFC1483"): """ Starts a packet capture. @@ -436,11 +444,7 @@ class ATMSwitch(Device): :param data_link_type: PCAP data link type (DLT_*), default is DLT_ATM_RFC1483 """ - if port_number not in self._nios: - raise DynamipsError("Port {} is not allocated".format(port_number)) - - nio = self._nios[port_number] - + nio = self.get_nio(port_number) data_link_type = data_link_type.lower() if data_link_type.startswith("dlt_"): data_link_type = data_link_type[4:] @@ -448,26 +452,22 @@ class ATMSwitch(Device): if nio.input_filter[0] is not None and nio.output_filter[0] is not None: raise DynamipsError("Port {} has already a filter applied".format(port_number)) - yield from nio.bind_filter("both", "capture") - yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file)) - + await nio.start_packet_capture(output_file, data_link_type) log.info('ATM switch "{name}" [{id}]: starting packet capture on port {port}'.format(name=self._name, id=self._id, port=port_number)) - @asyncio.coroutine - def stop_capture(self, port_number): + async def stop_capture(self, port_number): """ Stops a packet capture. :param port_number: allocated port number """ - if port_number not in self._nios: - raise DynamipsError("Port {} is not allocated".format(port_number)) - - nio = self._nios[port_number] - yield from nio.unbind_filter("both") + nio = self.get_nio(port_number) + if not nio.capturing: + return + await nio.stop_packet_capture() log.info('ATM switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name, id=self._id, port=port_number)) diff --git a/gns3server/compute/dynamips/nodes/bridge.py b/gns3server/compute/dynamips/nodes/bridge.py index b37ae5d8..7146865c 100644 --- a/gns3server/compute/dynamips/nodes/bridge.py +++ b/gns3server/compute/dynamips/nodes/bridge.py @@ -41,25 +41,23 @@ class Bridge(Device): super().__init__(name, node_id, project, manager, hypervisor) self._nios = [] - @asyncio.coroutine - def create(self): + async def create(self): if self._hypervisor is None: module_workdir = self.project.module_working_directory(self.manager.module_name.lower()) - self._hypervisor = yield from self.manager.start_new_hypervisor(working_dir=module_workdir) + self._hypervisor = await self.manager.start_new_hypervisor(working_dir=module_workdir) - yield from self._hypervisor.send('nio_bridge create "{}"'.format(self._name)) + await self._hypervisor.send('nio_bridge create "{}"'.format(self._name)) self._hypervisor.devices.append(self) - @asyncio.coroutine - def set_name(self, new_name): + async def set_name(self, new_name): """ Renames this bridge. :param new_name: New name for this bridge """ - yield from self._hypervisor.send('nio_bridge rename "{name}" "{new_name}"'.format(name=self._name, + await self._hypervisor.send('nio_bridge rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) self._name = new_name @@ -74,8 +72,7 @@ class Bridge(Device): return self._nios - @asyncio.coroutine - def delete(self): + async def delete(self): """ Deletes this bridge. """ @@ -83,28 +80,26 @@ class Bridge(Device): if self._hypervisor and self in self._hypervisor.devices: self._hypervisor.devices.remove(self) if self._hypervisor and not self._hypervisor.devices: - yield from self._hypervisor.send('nio_bridge delete "{}"'.format(self._name)) + await self._hypervisor.send('nio_bridge delete "{}"'.format(self._name)) - @asyncio.coroutine - def add_nio(self, nio): + async def add_nio(self, nio): """ Adds a NIO as new port on this bridge. :param nio: NIO instance to add """ - yield from self._hypervisor.send('nio_bridge add_nio "{name}" {nio}'.format(name=self._name, nio=nio)) + await self._hypervisor.send('nio_bridge add_nio "{name}" {nio}'.format(name=self._name, nio=nio)) self._nios.append(nio) - @asyncio.coroutine - def remove_nio(self, nio): + async def remove_nio(self, nio): """ Removes the specified NIO as member of this bridge. :param nio: NIO instance to remove """ if self._hypervisor: - yield from self._hypervisor.send('nio_bridge remove_nio "{name}" {nio}'.format(name=self._name, nio=nio)) + await self._hypervisor.send('nio_bridge remove_nio "{name}" {nio}'.format(name=self._name, nio=nio)) self._nios.remove(nio) @property diff --git a/gns3server/compute/dynamips/nodes/c1700.py b/gns3server/compute/dynamips/nodes/c1700.py index c042738b..cb4b8537 100644 --- a/gns3server/compute/dynamips/nodes/c1700.py +++ b/gns3server/compute/dynamips/nodes/c1700.py @@ -46,9 +46,9 @@ class C1700(Router): 1710 is not supported. """ - def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis="1720"): + def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis="1720"): - super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c1700") + super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c1700") # Set default values for this platform (must be the same as Dynamips) self._ram = 64 @@ -70,12 +70,11 @@ class C1700(Router): router_info.update(c1700_router_info) return router_info - @asyncio.coroutine - def create(self): + async def create(self): - yield from Router.create(self) + await Router.create(self) if self._chassis != "1720": - yield from self.set_chassis(self._chassis) + await self.set_chassis(self._chassis) self._setup_chassis() def _setup_chassis(self): @@ -103,8 +102,7 @@ class C1700(Router): return self._chassis - @asyncio.coroutine - def set_chassis(self, chassis): + async def set_chassis(self, chassis): """ Sets the chassis. @@ -112,7 +110,7 @@ class C1700(Router): 1720, 1721, 1750, 1751 or 1760 """ - yield from self._hypervisor.send('c1700 set_chassis "{name}" {chassis}'.format(name=self._name, chassis=chassis)) + await self._hypervisor.send('c1700 set_chassis "{name}" {chassis}'.format(name=self._name, chassis=chassis)) log.info('Router "{name}" [{id}]: chassis set to {chassis}'.format(name=self._name, id=self._id, @@ -131,15 +129,14 @@ class C1700(Router): return self._iomem - @asyncio.coroutine - def set_iomem(self, iomem): + async def set_iomem(self, iomem): """ Sets I/O memory size for this router. :param iomem: I/O memory size """ - yield from self._hypervisor.send('c1700 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) + await self._hypervisor.send('c1700 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) log.info('Router "{name}" [{id}]: I/O memory updated from {old_iomem}% to {new_iomem}%'.format(name=self._name, id=self._id, diff --git a/gns3server/compute/dynamips/nodes/c2600.py b/gns3server/compute/dynamips/nodes/c2600.py index 79c30d18..b065607b 100644 --- a/gns3server/compute/dynamips/nodes/c2600.py +++ b/gns3server/compute/dynamips/nodes/c2600.py @@ -61,9 +61,9 @@ class C2600(Router): "2650XM": C2600_MB_1FE, "2651XM": C2600_MB_2FE} - def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis="2610"): + def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis="2610"): - super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c2600") + super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c2600") # Set default values for this platform (must be the same as Dynamips) self._ram = 64 @@ -85,12 +85,11 @@ class C2600(Router): router_info.update(c2600_router_info) return router_info - @asyncio.coroutine - def create(self): + async def create(self): - yield from Router.create(self) + await Router.create(self) if self._chassis != "2610": - yield from self.set_chassis(self._chassis) + await self.set_chassis(self._chassis) self._setup_chassis() def _setup_chassis(self): @@ -112,8 +111,7 @@ class C2600(Router): return self._chassis - @asyncio.coroutine - def set_chassis(self, chassis): + async def set_chassis(self, chassis): """ Sets the chassis. @@ -122,7 +120,7 @@ class C2600(Router): 2620XM, 2621XM, 2650XM or 2651XM """ - yield from self._hypervisor.send('c2600 set_chassis "{name}" {chassis}'.format(name=self._name, chassis=chassis)) + await self._hypervisor.send('c2600 set_chassis "{name}" {chassis}'.format(name=self._name, chassis=chassis)) log.info('Router "{name}" [{id}]: chassis set to {chassis}'.format(name=self._name, id=self._id, @@ -140,15 +138,14 @@ class C2600(Router): return self._iomem - @asyncio.coroutine - def set_iomem(self, iomem): + async def set_iomem(self, iomem): """ Sets I/O memory size for this router. :param iomem: I/O memory size """ - yield from self._hypervisor.send('c2600 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) + await self._hypervisor.send('c2600 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) log.info('Router "{name}" [{id}]: I/O memory updated from {old_iomem}% to {new_iomem}%'.format(name=self._name, id=self._id, diff --git a/gns3server/compute/dynamips/nodes/c2691.py b/gns3server/compute/dynamips/nodes/c2691.py index 46338583..8441881f 100644 --- a/gns3server/compute/dynamips/nodes/c2691.py +++ b/gns3server/compute/dynamips/nodes/c2691.py @@ -43,9 +43,9 @@ class C2691(Router): :param aux: auxiliary console port """ - def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis=None): + def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis=None): - super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c2691") + super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c2691") # Set default values for this platform (must be the same as Dynamips) self._ram = 128 @@ -79,15 +79,14 @@ class C2691(Router): return self._iomem - @asyncio.coroutine - def set_iomem(self, iomem): + async def set_iomem(self, iomem): """ Sets I/O memory size for this router. :param iomem: I/O memory size """ - yield from self._hypervisor.send('c2691 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) + await self._hypervisor.send('c2691 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) log.info('Router "{name}" [{id}]: I/O memory updated from {old_iomem}% to {new_iomem}%'.format(name=self._name, id=self._id, diff --git a/gns3server/compute/dynamips/nodes/c3600.py b/gns3server/compute/dynamips/nodes/c3600.py index 2bf99d30..984a5621 100644 --- a/gns3server/compute/dynamips/nodes/c3600.py +++ b/gns3server/compute/dynamips/nodes/c3600.py @@ -44,9 +44,9 @@ class C3600(Router): 3620, 3640 or 3660 (default = 3640). """ - def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis="3640"): + def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis="3640"): - super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c3600") + super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c3600") # Set default values for this platform (must be the same as Dynamips) self._ram = 128 @@ -66,12 +66,11 @@ class C3600(Router): router_info.update(c3600_router_info) return router_info - @asyncio.coroutine - def create(self): + async def create(self): - yield from Router.create(self) + await Router.create(self) if self._chassis != "3640": - yield from self.set_chassis(self._chassis) + await self.set_chassis(self._chassis) self._setup_chassis() def _setup_chassis(self): @@ -98,15 +97,14 @@ class C3600(Router): return self._chassis - @asyncio.coroutine - def set_chassis(self, chassis): + async def set_chassis(self, chassis): """ Sets the chassis. :param: chassis string: 3620, 3640 or 3660 """ - yield from self._hypervisor.send('c3600 set_chassis "{name}" {chassis}'.format(name=self._name, chassis=chassis)) + await self._hypervisor.send('c3600 set_chassis "{name}" {chassis}'.format(name=self._name, chassis=chassis)) log.info('Router "{name}" [{id}]: chassis set to {chassis}'.format(name=self._name, id=self._id, @@ -125,15 +123,14 @@ class C3600(Router): return self._iomem - @asyncio.coroutine - def set_iomem(self, iomem): + async def set_iomem(self, iomem): """ Set I/O memory size for this router. :param iomem: I/O memory size """ - yield from self._hypervisor.send('c3600 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) + await self._hypervisor.send('c3600 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) log.info('Router "{name}" [{id}]: I/O memory updated from {old_iomem}% to {new_iomem}%'.format(name=self._name, id=self._id, diff --git a/gns3server/compute/dynamips/nodes/c3725.py b/gns3server/compute/dynamips/nodes/c3725.py index 5d701592..be194cf5 100644 --- a/gns3server/compute/dynamips/nodes/c3725.py +++ b/gns3server/compute/dynamips/nodes/c3725.py @@ -43,9 +43,9 @@ class C3725(Router): :param aux: auxiliary console port """ - def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis=None): + def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis=None): - super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c3725") + super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c3725") # Set default values for this platform (must be the same as Dynamips) self._ram = 128 @@ -79,15 +79,14 @@ class C3725(Router): return self._iomem - @asyncio.coroutine - def set_iomem(self, iomem): + async def set_iomem(self, iomem): """ Sets I/O memory size for this router. :param iomem: I/O memory size """ - yield from self._hypervisor.send('c3725 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) + await self._hypervisor.send('c3725 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) log.info('Router "{name}" [{id}]: I/O memory updated from {old_iomem}% to {new_iomem}%'.format(name=self._name, id=self._id, diff --git a/gns3server/compute/dynamips/nodes/c3745.py b/gns3server/compute/dynamips/nodes/c3745.py index 0255e597..9087a98f 100644 --- a/gns3server/compute/dynamips/nodes/c3745.py +++ b/gns3server/compute/dynamips/nodes/c3745.py @@ -43,9 +43,9 @@ class C3745(Router): :param aux: auxiliary console port """ - def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis=None): + def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis=None): - super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c3745") + super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c3745") # Set default values for this platform (must be the same as Dynamips) self._ram = 128 @@ -79,15 +79,14 @@ class C3745(Router): return self._iomem - @asyncio.coroutine - def set_iomem(self, iomem): + async def set_iomem(self, iomem): """ Sets I/O memory size for this router. :param iomem: I/O memory size """ - yield from self._hypervisor.send('c3745 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) + await self._hypervisor.send('c3745 set_iomem "{name}" {size}'.format(name=self._name, size=iomem)) log.info('Router "{name}" [{id}]: I/O memory updated from {old_iomem}% to {new_iomem}%'.format(name=self._name, id=self._id, diff --git a/gns3server/compute/dynamips/nodes/c7200.py b/gns3server/compute/dynamips/nodes/c7200.py index fb0231cd..155bc385 100644 --- a/gns3server/compute/dynamips/nodes/c7200.py +++ b/gns3server/compute/dynamips/nodes/c7200.py @@ -46,9 +46,9 @@ class C7200(Router): :param npe: Default NPE """ - def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, npe="npe-400", chassis=None): + def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, npe="npe-400", chassis=None): - super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c7200") + super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c7200") # Set default values for this platform (must be the same as Dynamips) self._ram = 256 @@ -86,19 +86,18 @@ class C7200(Router): router_info.update(c7200_router_info) return router_info - @asyncio.coroutine - def create(self): + async def create(self): - yield from Router.create(self) + await Router.create(self) if self._npe != "npe-400": - yield from self.set_npe(self._npe) + await self.set_npe(self._npe) # first slot is a mandatory Input/Output controller (based on NPE type) if self.npe == "npe-g2": - yield from self.slot_add_binding(0, C7200_IO_GE_E()) + await self.slot_add_binding(0, C7200_IO_GE_E()) else: - yield from self.slot_add_binding(0, C7200_IO_FE()) + await self.slot_add_binding(0, C7200_IO_FE()) @property def npe(self): @@ -110,8 +109,7 @@ class C7200(Router): return self._npe - @asyncio.coroutine - def set_npe(self, npe): + async def set_npe(self, npe): """ Sets the NPE model. @@ -120,10 +118,10 @@ class C7200(Router): npe-225, npe-300, npe-400 and npe-g2 (PowerPC c7200 only) """ - if (yield from self.is_running()): + if (await self.is_running()): raise DynamipsError("Cannot change NPE on running router") - yield from self._hypervisor.send('c7200 set_npe "{name}" {npe}'.format(name=self._name, npe=npe)) + await self._hypervisor.send('c7200 set_npe "{name}" {npe}'.format(name=self._name, npe=npe)) log.info('Router "{name}" [{id}]: NPE updated from {old_npe} to {new_npe}'.format(name=self._name, id=self._id, @@ -141,15 +139,14 @@ class C7200(Router): return self._midplane - @asyncio.coroutine - def set_midplane(self, midplane): + async def set_midplane(self, midplane): """ Sets the midplane model. :returns: midplane model string (e.g. "vxr" or "std") """ - yield from self._hypervisor.send('c7200 set_midplane "{name}" {midplane}'.format(name=self._name, midplane=midplane)) + await self._hypervisor.send('c7200 set_midplane "{name}" {midplane}'.format(name=self._name, midplane=midplane)) log.info('Router "{name}" [{id}]: midplane updated from {old_midplane} to {new_midplane}'.format(name=self._name, id=self._id, @@ -167,8 +164,7 @@ class C7200(Router): return self._sensors - @asyncio.coroutine - def set_sensors(self, sensors): + async def set_sensors(self, sensors): """ Sets the 4 sensors with temperature in degree Celcius. @@ -182,7 +178,7 @@ class C7200(Router): sensor_id = 0 for sensor in sensors: - yield from self._hypervisor.send('c7200 set_temp_sensor "{name}" {sensor_id} {temp}'.format(name=self._name, + await self._hypervisor.send('c7200 set_temp_sensor "{name}" {sensor_id} {temp}'.format(name=self._name, sensor_id=sensor_id, temp=sensor)) @@ -205,8 +201,7 @@ class C7200(Router): return self._power_supplies - @asyncio.coroutine - def set_power_supplies(self, power_supplies): + async def set_power_supplies(self, power_supplies): """ Sets the 2 power supplies with 0 = off, 1 = on. @@ -216,7 +211,7 @@ class C7200(Router): power_supply_id = 0 for power_supply in power_supplies: - yield from self._hypervisor.send('c7200 set_power_supply "{name}" {power_supply_id} {powered_on}'.format(name=self._name, + await self._hypervisor.send('c7200 set_power_supply "{name}" {power_supply_id} {powered_on}'.format(name=self._name, power_supply_id=power_supply_id, powered_on=power_supply)) @@ -228,8 +223,7 @@ class C7200(Router): self._power_supplies = power_supplies - @asyncio.coroutine - def start(self): + async def start(self): """ Starts this router. At least the IOS image must be set before starting it. @@ -237,8 +231,8 @@ class C7200(Router): # trick: we must send sensors and power supplies info after starting the router # otherwise they are not taken into account (Dynamips bug?) - yield from Router.start(self) + await Router.start(self) if self._sensors != [22, 22, 22, 22]: - yield from self.set_sensors(self._sensors) + await self.set_sensors(self._sensors) if self._power_supplies != [1, 1]: - yield from self.set_power_supplies(self._power_supplies) + await self.set_power_supplies(self._power_supplies) diff --git a/gns3server/compute/dynamips/nodes/ethernet_hub.py b/gns3server/compute/dynamips/nodes/ethernet_hub.py index c481a8ab..cdfea41a 100644 --- a/gns3server/compute/dynamips/nodes/ethernet_hub.py +++ b/gns3server/compute/dynamips/nodes/ethernet_hub.py @@ -19,8 +19,6 @@ Hub object that uses the Bridge interface to create a hub with ports. """ -import asyncio - from .bridge import Bridge from ..nios.nio_udp import NIOUDP from ..dynamips_error import DynamipsError @@ -93,10 +91,9 @@ class EthernetHub(Bridge): self._ports = ports - @asyncio.coroutine - def create(self): + async def create(self): - yield from Bridge.create(self) + await Bridge.create(self) log.info('Ethernet hub "{name}" [{id}] has been created'.format(name=self._name, id=self._id)) @property @@ -109,32 +106,29 @@ class EthernetHub(Bridge): return self._mappings - @asyncio.coroutine - def delete(self): - return (yield from self.close()) + async def delete(self): + return (await self.close()) - @asyncio.coroutine - def close(self): + async def close(self): """ Deletes this hub. """ for nio in self._nios: if nio: - yield from nio.close() + await nio.close() try: - yield from Bridge.delete(self) + await Bridge.delete(self) log.info('Ethernet hub "{name}" [{id}] has been deleted'.format(name=self._name, id=self._id)) except DynamipsError: log.debug("Could not properly delete Ethernet hub {}".format(self._name)) if self._hypervisor and not self._hypervisor.devices: - yield from self.hypervisor.stop() + await self.hypervisor.stop() self._hypervisor = None return True - @asyncio.coroutine - def add_nio(self, nio, port_number): + async def add_nio(self, nio, port_number): """ Adds a NIO as new port on this hub. @@ -148,7 +142,7 @@ class EthernetHub(Bridge): if port_number in self._mappings: raise DynamipsError("Port {} isn't free".format(port_number)) - yield from Bridge.add_nio(self, nio) + await Bridge.add_nio(self, nio) log.info('Ethernet hub "{name}" [{id}]: NIO {nio} bound to port {port}'.format(name=self._name, id=self._id, @@ -156,8 +150,7 @@ class EthernetHub(Bridge): port=port_number)) self._mappings[port_number] = nio - @asyncio.coroutine - def remove_nio(self, port_number): + async def remove_nio(self, port_number): """ Removes the specified NIO as member of this hub. @@ -169,10 +162,11 @@ class EthernetHub(Bridge): if port_number not in self._mappings: raise DynamipsError("Port {} is not allocated".format(port_number)) + await self.stop_capture(port_number) nio = self._mappings[port_number] if isinstance(nio, NIOUDP): self.manager.port_manager.release_udp_port(nio.lport, self._project) - yield from Bridge.remove_nio(self, nio) + await Bridge.remove_nio(self, nio) log.info('Ethernet hub "{name}" [{id}]: NIO {nio} removed from port {port}'.format(name=self._name, id=self._id, @@ -182,8 +176,26 @@ class EthernetHub(Bridge): del self._mappings[port_number] return nio - @asyncio.coroutine - def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): + def get_nio(self, port_number): + """ + Gets a port NIO binding. + + :param port_number: port number + + :returns: NIO instance + """ + + if port_number not in self._mappings: + raise DynamipsError("Port {} is not allocated".format(port_number)) + + nio = self._mappings[port_number] + + if not nio: + raise DynamipsError("Port {} is not connected".format(port_number)) + + return nio + + async def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): """ Starts a packet capture. @@ -192,11 +204,7 @@ class EthernetHub(Bridge): :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB """ - if port_number not in self._mappings: - raise DynamipsError("Port {} is not allocated".format(port_number)) - - nio = self._mappings[port_number] - + nio = self.get_nio(port_number) data_link_type = data_link_type.lower() if data_link_type.startswith("dlt_"): data_link_type = data_link_type[4:] @@ -204,26 +212,22 @@ class EthernetHub(Bridge): if nio.input_filter[0] is not None and nio.output_filter[0] is not None: raise DynamipsError("Port {} has already a filter applied".format(port_number)) - yield from nio.bind_filter("both", "capture") - yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file)) - + await nio.start_packet_capture(output_file, data_link_type) log.info('Ethernet hub "{name}" [{id}]: starting packet capture on port {port}'.format(name=self._name, id=self._id, port=port_number)) - @asyncio.coroutine - def stop_capture(self, port_number): + async def stop_capture(self, port_number): """ Stops a packet capture. :param port_number: allocated port number """ - if port_number not in self._mappings: - raise DynamipsError("Port {} is not allocated".format(port_number)) - - nio = self._mappings[port_number] - yield from nio.unbind_filter("both") + nio = self.get_nio(port_number) + if not nio.capturing: + return + await nio.stop_packet_capture() log.info('Ethernet hub "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name, id=self._id, port=port_number)) diff --git a/gns3server/compute/dynamips/nodes/ethernet_switch.py b/gns3server/compute/dynamips/nodes/ethernet_switch.py index 841a47c9..fa296a95 100644 --- a/gns3server/compute/dynamips/nodes/ethernet_switch.py +++ b/gns3server/compute/dynamips/nodes/ethernet_switch.py @@ -22,7 +22,7 @@ http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L558 import asyncio from gns3server.utils import parse_version -from gns3server.utils.asyncio.embed_shell import EmbedShell, create_telnet_shell +#from gns3server.utils.asyncio.embed_shell import EmbedShell, create_telnet_shell from .device import Device @@ -34,37 +34,36 @@ import logging log = logging.getLogger(__name__) -class EthernetSwitchConsole(EmbedShell): - """ - Console for the ethernet switch - """ - - def __init__(self, node): - super().__init__(welcome_message="Welcome to GNS3 builtin Ethernet switch.\n\nType help for available commands\n") - self._node = node - - @asyncio.coroutine - def mac(self): - """ - Show MAC address table - """ - res = 'Port Mac VLAN\n' - result = (yield from self._node._hypervisor.send('ethsw show_mac_addr_table {}'.format(self._node.name))) - for line in result: - mac, vlan, nio = line.replace(' ', ' ').split(' ') - mac = mac.replace('.', '') - mac = "{}:{}:{}:{}:{}:{}".format( - mac[0:2], - mac[2:4], - mac[4:6], - mac[6:8], - mac[8:10], - mac[10:12]) - for port_number, switch_nio in self._node.nios.items(): - if switch_nio.name == nio: - res += 'Ethernet' + str(port_number) + ' ' + mac + ' ' + vlan + '\n' - break - return res +# class EthernetSwitchConsole(EmbedShell): +# """ +# Console for the ethernet switch +# """ +# +# def __init__(self, node): +# super().__init__(welcome_message="Welcome to GNS3 builtin Ethernet switch.\n\nType help for available commands\n") +# self._node = node +# +# async def mac(self): +# """ +# Show MAC address table +# """ +# res = 'Port Mac VLAN\n' +# result = (await self._node._hypervisor.send('ethsw show_mac_addr_table {}'.format(self._node.name))) +# for line in result: +# mac, vlan, nio = line.replace(' ', ' ').split(' ') +# mac = mac.replace('.', '') +# mac = "{}:{}:{}:{}:{}:{}".format( +# mac[0:2], +# mac[2:4], +# mac[4:6], +# mac[6:8], +# mac[8:10], +# mac[10:12]) +# for port_number, switch_nio in self._node.nios.items(): +# if switch_nio.name == nio: +# res += 'Ethernet' + str(port_number) + ' ' + mac + ' ' + vlan + '\n' +# break +# return res class EthernetSwitch(Device): @@ -80,14 +79,22 @@ class EthernetSwitch(Device): :param hypervisor: Dynamips hypervisor instance """ - def __init__(self, name, node_id, project, manager, ports=None, hypervisor=None): + def __init__(self, name, node_id, project, manager, console=None, console_type="none", ports=None, hypervisor=None): super().__init__(name, node_id, project, manager, hypervisor) self._nios = {} self._mappings = {} self._telnet_console = None - self._telnet_shell = None - self._console = self._manager.port_manager.get_free_tcp_port(self._project) + #self._telnet_shell = None + #self._telnet_server = None + self._console = console + self._console_type = console_type + + if self._console is not None: + self._console = self._manager.port_manager.reserve_tcp_port(self._console, self._project) + else: + self._console = self._manager.port_manager.get_free_tcp_port(self._project) + if ports is None: # create 8 ports by default self._ports = [] @@ -103,7 +110,7 @@ class EthernetSwitch(Device): ethernet_switch_info = {"name": self.name, "console": self.console, - "console_type": "telnet", + "console_type": self.console_type, "node_id": self.id, "project_id": self.project.id, "ports_mapping": self._ports, @@ -115,8 +122,21 @@ class EthernetSwitch(Device): return self._console @console.setter - def console(self, val): - self._console = val + def console(self, console): + self._console = console + + @property + def console_type(self): + return self._console_type + + @console_type.setter + def console_type(self, console_type): + + if self._console_type != console_type: + if console_type == "telnet": + self.project.emit("log.warning", { + "message": '"{name}": Telnet access for switches is not available in this version of GNS3'.format(name=self._name)}) + self._console_type = console_type @property def ports_mapping(self): @@ -147,39 +167,40 @@ class EthernetSwitch(Device): self._ports = ports - @asyncio.coroutine - def update_port_settings(self): + async def update_port_settings(self): for port_settings in self._ports: port_number = port_settings["port_number"] if port_number in self._nios and self._nios[port_number] is not None: - yield from self.set_port_settings(port_number, port_settings) + await self.set_port_settings(port_number, port_settings) - @asyncio.coroutine - def create(self): + async def create(self): if self._hypervisor is None: module_workdir = self.project.module_working_directory(self.manager.module_name.lower()) - self._hypervisor = yield from self.manager.start_new_hypervisor(working_dir=module_workdir) + self._hypervisor = await self.manager.start_new_hypervisor(working_dir=module_workdir) - yield from self._hypervisor.send('ethsw create "{}"'.format(self._name)) + await self._hypervisor.send('ethsw create "{}"'.format(self._name)) log.info('Ethernet switch "{name}" [{id}] has been created'.format(name=self._name, id=self._id)) - self._telnet_shell = EthernetSwitchConsole(self) - self._telnet_shell.prompt = self._name + '> ' - self._telnet = create_telnet_shell(self._telnet_shell) - self._telnet_server = (yield from asyncio.start_server(self._telnet.run, self._manager.port_manager.console_host, self.console)) - + #self._telnet_shell = EthernetSwitchConsole(self) + #self._telnet_shell.prompt = self._name + '> ' + #self._telnet = create_telnet_shell(self._telnet_shell) + #try: + # self._telnet_server = (await asyncio.start_server(self._telnet.run, self._manager.port_manager.console_host, self.console)) + #except OSError as e: + # self.project.emit("log.warning", {"message": "Could not start Telnet server on socket {}:{}: {}".format(self._manager.port_manager.console_host, self.console, e)}) + if self._console_type == "telnet": + self.project.emit("log.warning", {"message": '"{name}": Telnet access for switches is not available in this version of GNS3'.format(name=self._name)}) self._hypervisor.devices.append(self) - @asyncio.coroutine - def set_name(self, new_name): + async def set_name(self, new_name): """ Renames this Ethernet switch. :param new_name: New name for this switch """ - yield from self._hypervisor.send('ethsw rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) + await self._hypervisor.send('ethsw rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) log.info('Ethernet switch "{name}" [{id}]: renamed to "{new_name}"'.format(name=self._name, id=self._id, new_name=new_name)) @@ -205,37 +226,36 @@ class EthernetSwitch(Device): return self._mappings - @asyncio.coroutine - def delete(self): - return (yield from self.close()) + async def delete(self): + return (await self.close()) - @asyncio.coroutine - def close(self): + async def close(self): """ Deletes this Ethernet switch. """ - yield from self._telnet.close() - self._telnet_server.close() - + + #await self._telnet.close() + #if self._telnet_server: + # self._telnet_server.close() + for nio in self._nios.values(): if nio: - yield from nio.close() + await nio.close() self.manager.port_manager.release_tcp_port(self._console, self._project) if self._hypervisor: try: - yield from self._hypervisor.send('ethsw delete "{}"'.format(self._name)) + await self._hypervisor.send('ethsw delete "{}"'.format(self._name)) log.info('Ethernet switch "{name}" [{id}] has been deleted'.format(name=self._name, id=self._id)) except DynamipsError: log.debug("Could not properly delete Ethernet switch {}".format(self._name)) if self._hypervisor and self in self._hypervisor.devices: self._hypervisor.devices.remove(self) if self._hypervisor and not self._hypervisor.devices: - yield from self.hypervisor.stop() + await self.hypervisor.stop() self._hypervisor = None return True - @asyncio.coroutine - def add_nio(self, nio, port_number): + async def add_nio(self, nio, port_number): """ Adds a NIO as new port on Ethernet switch. @@ -246,7 +266,7 @@ class EthernetSwitch(Device): if port_number in self._nios: raise DynamipsError("Port {} isn't free".format(port_number)) - yield from self._hypervisor.send('ethsw add_nio "{name}" {nio}'.format(name=self._name, nio=nio)) + await self._hypervisor.send('ethsw add_nio "{name}" {nio}'.format(name=self._name, nio=nio)) log.info('Ethernet switch "{name}" [{id}]: NIO {nio} bound to port {port}'.format(name=self._name, id=self._id, @@ -255,11 +275,10 @@ class EthernetSwitch(Device): self._nios[port_number] = nio for port_settings in self._ports: if port_settings["port_number"] == port_number: - yield from self.set_port_settings(port_number, port_settings) + await self.set_port_settings(port_number, port_settings) break - @asyncio.coroutine - def remove_nio(self, port_number): + async def remove_nio(self, port_number): """ Removes the specified NIO as member of this Ethernet switch. @@ -271,11 +290,12 @@ class EthernetSwitch(Device): if port_number not in self._nios: raise DynamipsError("Port {} is not allocated".format(port_number)) + await self.stop_capture(port_number) nio = self._nios[port_number] if isinstance(nio, NIOUDP): self.manager.port_manager.release_udp_port(nio.lport, self._project) if self._hypervisor: - yield from self._hypervisor.send('ethsw remove_nio "{name}" {nio}'.format(name=self._name, nio=nio)) + await self._hypervisor.send('ethsw remove_nio "{name}" {nio}'.format(name=self._name, nio=nio)) log.info('Ethernet switch "{name}" [{id}]: NIO {nio} removed from port {port}'.format(name=self._name, id=self._id, @@ -288,8 +308,26 @@ class EthernetSwitch(Device): return nio - @asyncio.coroutine - def set_port_settings(self, port_number, settings): + def get_nio(self, port_number): + """ + Gets a port NIO binding. + + :param port_number: port number + + :returns: NIO instance + """ + + if port_number not in self._nios: + raise DynamipsError("Port {} is not allocated".format(port_number)) + + nio = self._nios[port_number] + + if not nio: + raise DynamipsError("Port {} is not connected".format(port_number)) + + return nio + + async def set_port_settings(self, port_number, settings): """ Applies port settings to a specific port. @@ -298,14 +336,13 @@ class EthernetSwitch(Device): """ if settings["type"] == "access": - yield from self.set_access_port(port_number, settings["vlan"]) + await self.set_access_port(port_number, settings["vlan"]) elif settings["type"] == "dot1q": - yield from self.set_dot1q_port(port_number, settings["vlan"]) + await self.set_dot1q_port(port_number, settings["vlan"]) elif settings["type"] == "qinq": - yield from self.set_qinq_port(port_number, settings["vlan"], settings.get("ethertype")) + await self.set_qinq_port(port_number, settings["vlan"], settings.get("ethertype")) - @asyncio.coroutine - def set_access_port(self, port_number, vlan_id): + async def set_access_port(self, port_number, vlan_id): """ Sets the specified port as an ACCESS port. @@ -317,7 +354,7 @@ class EthernetSwitch(Device): raise DynamipsError("Port {} is not allocated".format(port_number)) nio = self._nios[port_number] - yield from self._hypervisor.send('ethsw set_access_port "{name}" {nio} {vlan_id}'.format(name=self._name, + await self._hypervisor.send('ethsw set_access_port "{name}" {nio} {vlan_id}'.format(name=self._name, nio=nio, vlan_id=vlan_id)) @@ -327,8 +364,7 @@ class EthernetSwitch(Device): vlan_id=vlan_id)) self._mappings[port_number] = ("access", vlan_id) - @asyncio.coroutine - def set_dot1q_port(self, port_number, native_vlan): + async def set_dot1q_port(self, port_number, native_vlan): """ Sets the specified port as a 802.1Q trunk port. @@ -340,7 +376,7 @@ class EthernetSwitch(Device): raise DynamipsError("Port {} is not allocated".format(port_number)) nio = self._nios[port_number] - yield from self._hypervisor.send('ethsw set_dot1q_port "{name}" {nio} {native_vlan}'.format(name=self._name, + await self._hypervisor.send('ethsw set_dot1q_port "{name}" {nio} {native_vlan}'.format(name=self._name, nio=nio, native_vlan=native_vlan)) @@ -351,8 +387,7 @@ class EthernetSwitch(Device): self._mappings[port_number] = ("dot1q", native_vlan) - @asyncio.coroutine - def set_qinq_port(self, port_number, outer_vlan, ethertype): + async def set_qinq_port(self, port_number, outer_vlan, ethertype): """ Sets the specified port as a trunk (QinQ) port. @@ -367,7 +402,7 @@ class EthernetSwitch(Device): if ethertype != "0x8100" and parse_version(self.hypervisor.version) < parse_version('0.2.16'): raise DynamipsError("Dynamips version required is >= 0.2.16 to change the default QinQ Ethernet type, detected version is {}".format(self.hypervisor.version)) - yield from self._hypervisor.send('ethsw set_qinq_port "{name}" {nio} {outer_vlan} {ethertype}'.format(name=self._name, + await self._hypervisor.send('ethsw set_qinq_port "{name}" {nio} {outer_vlan} {ethertype}'.format(name=self._name, nio=nio, outer_vlan=outer_vlan, ethertype=ethertype if ethertype != "0x8100" else "")) @@ -379,27 +414,24 @@ class EthernetSwitch(Device): ethertype=ethertype)) self._mappings[port_number] = ("qinq", outer_vlan, ethertype) - @asyncio.coroutine - def get_mac_addr_table(self): + async def get_mac_addr_table(self): """ Returns the MAC address table for this Ethernet switch. :returns: list of entries (Ethernet address, VLAN, NIO) """ - mac_addr_table = yield from self._hypervisor.send('ethsw show_mac_addr_table "{}"'.format(self._name)) + mac_addr_table = await self._hypervisor.send('ethsw show_mac_addr_table "{}"'.format(self._name)) return mac_addr_table - @asyncio.coroutine - def clear_mac_addr_table(self): + async def clear_mac_addr_table(self): """ Clears the MAC address table for this Ethernet switch. """ - yield from self._hypervisor.send('ethsw clear_mac_addr_table "{}"'.format(self._name)) + await self._hypervisor.send('ethsw clear_mac_addr_table "{}"'.format(self._name)) - @asyncio.coroutine - def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): + async def start_capture(self, port_number, output_file, data_link_type="DLT_EN10MB"): """ Starts a packet capture. @@ -408,14 +440,7 @@ class EthernetSwitch(Device): :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB """ - if port_number not in self._nios: - raise DynamipsError("Port {} is not allocated".format(port_number)) - - nio = self._nios[port_number] - - if not nio: - raise DynamipsError("Port {} is not connected".format(port_number)) - + nio = self.get_nio(port_number) data_link_type = data_link_type.lower() if data_link_type.startswith("dlt_"): data_link_type = data_link_type[4:] @@ -423,30 +448,22 @@ class EthernetSwitch(Device): if nio.input_filter[0] is not None and nio.output_filter[0] is not None: raise DynamipsError("Port {} has already a filter applied".format(port_number)) - yield from nio.bind_filter("both", "capture") - yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file)) - + await nio.start_packet_capture(output_file, data_link_type) log.info('Ethernet switch "{name}" [{id}]: starting packet capture on port {port}'.format(name=self._name, id=self._id, port=port_number)) - @asyncio.coroutine - def stop_capture(self, port_number): + async def stop_capture(self, port_number): """ Stops a packet capture. :param port_number: allocated port number """ - if port_number not in self._nios: - raise DynamipsError("Port {} is not allocated".format(port_number)) - - nio = self._nios[port_number] - - if not nio: - raise DynamipsError("Port {} is not connected".format(port_number)) - - yield from nio.unbind_filter("both") + nio = self.get_nio(port_number) + if not nio.capturing: + return + await nio.stop_packet_capture() log.info('Ethernet switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name, id=self._id, port=port_number)) diff --git a/gns3server/compute/dynamips/nodes/frame_relay_switch.py b/gns3server/compute/dynamips/nodes/frame_relay_switch.py index c6dac00e..535187c7 100644 --- a/gns3server/compute/dynamips/nodes/frame_relay_switch.py +++ b/gns3server/compute/dynamips/nodes/frame_relay_switch.py @@ -63,26 +63,24 @@ class FrameRelaySwitch(Device): "mappings": mappings, "status": "started"} - @asyncio.coroutine - def create(self): + async def create(self): if self._hypervisor is None: module_workdir = self.project.module_working_directory(self.manager.module_name.lower()) - self._hypervisor = yield from self.manager.start_new_hypervisor(working_dir=module_workdir) + self._hypervisor = await self.manager.start_new_hypervisor(working_dir=module_workdir) - yield from self._hypervisor.send('frsw create "{}"'.format(self._name)) + await self._hypervisor.send('frsw create "{}"'.format(self._name)) log.info('Frame Relay switch "{name}" [{id}] has been created'.format(name=self._name, id=self._id)) self._hypervisor.devices.append(self) - @asyncio.coroutine - def set_name(self, new_name): + async def set_name(self, new_name): """ Renames this Frame Relay switch. :param new_name: New name for this switch """ - yield from self._hypervisor.send('frsw rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) + await self._hypervisor.send('frsw rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) log.info('Frame Relay switch "{name}" [{id}]: renamed to "{new_name}"'.format(name=self._name, id=self._id, new_name=new_name)) @@ -118,15 +116,14 @@ class FrameRelaySwitch(Device): self._mappings = mappings - @asyncio.coroutine - def close(self): + async def close(self): for nio in self._nios.values(): if nio: - yield from nio.close() + await nio.close() if self._hypervisor: try: - yield from self._hypervisor.send('frsw delete "{}"'.format(self._name)) + await self._hypervisor.send('frsw delete "{}"'.format(self._name)) log.info('Frame Relay switch "{name}" [{id}] has been deleted'.format(name=self._name, id=self._id)) except DynamipsError: log.debug("Could not properly delete Frame relay switch {}".format(self._name)) @@ -134,15 +131,14 @@ class FrameRelaySwitch(Device): if self._hypervisor and self in self._hypervisor.devices: self._hypervisor.devices.remove(self) if self._hypervisor and not self._hypervisor.devices: - yield from self.hypervisor.stop() + await self.hypervisor.stop() self._hypervisor = None - @asyncio.coroutine - def delete(self): + async def delete(self): """ Deletes this Frame Relay switch. """ - yield from self.close() + await self.close() return True def has_port(self, port): @@ -156,8 +152,7 @@ class FrameRelaySwitch(Device): return True return False - @asyncio.coroutine - def add_nio(self, nio, port_number): + async def add_nio(self, nio, port_number): """ Adds a NIO as new port on Frame Relay switch. @@ -174,10 +169,9 @@ class FrameRelaySwitch(Device): port=port_number)) self._nios[port_number] = nio - yield from self.set_mappings(self._mappings) + await self.set_mappings(self._mappings) - @asyncio.coroutine - def remove_nio(self, port_number): + async def remove_nio(self, port_number): """ Removes the specified NIO as member of this Frame Relay switch. @@ -189,6 +183,7 @@ class FrameRelaySwitch(Device): if port_number not in self._nios: raise DynamipsError("Port {} is not allocated".format(port_number)) + await self.stop_capture(port_number) # remove VCs mapped with the port for source, destination in self._active_mappings.copy().items(): source_port, source_dlci = source @@ -200,8 +195,8 @@ class FrameRelaySwitch(Device): source_dlci=source_dlci, destination_port=destination_port, destination_dlci=destination_dlci)) - yield from self.unmap_vc(source_port, source_dlci, destination_port, destination_dlci) - yield from self.unmap_vc(destination_port, destination_dlci, source_port, source_dlci) + await self.unmap_vc(source_port, source_dlci, destination_port, destination_dlci) + await self.unmap_vc(destination_port, destination_dlci, source_port, source_dlci) nio = self._nios[port_number] if isinstance(nio, NIOUDP): @@ -215,8 +210,26 @@ class FrameRelaySwitch(Device): del self._nios[port_number] return nio - @asyncio.coroutine - def set_mappings(self, mappings): + def get_nio(self, port_number): + """ + Gets a port NIO binding. + + :param port_number: port number + + :returns: NIO instance + """ + + if port_number not in self._nios: + raise DynamipsError("Port {} is not allocated".format(port_number)) + + nio = self._nios[port_number] + + if not nio: + raise DynamipsError("Port {} is not connected".format(port_number)) + + return nio + + async def set_mappings(self, mappings): """ Applies VC mappings @@ -237,11 +250,10 @@ class FrameRelaySwitch(Device): destination_port=destination_port, destination_dlci=destination_dlci)) - yield from self.map_vc(source_port, source_dlci, destination_port, destination_dlci) - yield from self.map_vc(destination_port, destination_dlci, source_port, source_dlci) + await self.map_vc(source_port, source_dlci, destination_port, destination_dlci) + await self.map_vc(destination_port, destination_dlci, source_port, source_dlci) - @asyncio.coroutine - def map_vc(self, port1, dlci1, port2, dlci2): + async def map_vc(self, port1, dlci1, port2, dlci2): """ Creates a new Virtual Circuit connection (unidirectional). @@ -260,7 +272,7 @@ class FrameRelaySwitch(Device): nio1 = self._nios[port1] nio2 = self._nios[port2] - yield from self._hypervisor.send('frsw create_vc "{name}" {input_nio} {input_dlci} {output_nio} {output_dlci}'.format(name=self._name, + await self._hypervisor.send('frsw create_vc "{name}" {input_nio} {input_dlci} {output_nio} {output_dlci}'.format(name=self._name, input_nio=nio1, input_dlci=dlci1, output_nio=nio2, @@ -275,8 +287,7 @@ class FrameRelaySwitch(Device): self._active_mappings[(port1, dlci1)] = (port2, dlci2) - @asyncio.coroutine - def unmap_vc(self, port1, dlci1, port2, dlci2): + async def unmap_vc(self, port1, dlci1, port2, dlci2): """ Deletes a Virtual Circuit connection (unidirectional). @@ -295,7 +306,7 @@ class FrameRelaySwitch(Device): nio1 = self._nios[port1] nio2 = self._nios[port2] - yield from self._hypervisor.send('frsw delete_vc "{name}" {input_nio} {input_dlci} {output_nio} {output_dlci}'.format(name=self._name, + await self._hypervisor.send('frsw delete_vc "{name}" {input_nio} {input_dlci} {output_nio} {output_dlci}'.format(name=self._name, input_nio=nio1, input_dlci=dlci1, output_nio=nio2, @@ -309,8 +320,7 @@ class FrameRelaySwitch(Device): dlci2=dlci2)) del self._active_mappings[(port1, dlci1)] - @asyncio.coroutine - def start_capture(self, port_number, output_file, data_link_type="DLT_FRELAY"): + async def start_capture(self, port_number, output_file, data_link_type="DLT_FRELAY"): """ Starts a packet capture. @@ -319,10 +329,7 @@ class FrameRelaySwitch(Device): :param data_link_type: PCAP data link type (DLT_*), default is DLT_FRELAY """ - if port_number not in self._nios: - raise DynamipsError("Port {} is not allocated".format(port_number)) - - nio = self._nios[port_number] + nio = self.get_nio(port_number) data_link_type = data_link_type.lower() if data_link_type.startswith("dlt_"): @@ -331,26 +338,22 @@ class FrameRelaySwitch(Device): if nio.input_filter[0] is not None and nio.output_filter[0] is not None: raise DynamipsError("Port {} has already a filter applied".format(port_number)) - yield from nio.bind_filter("both", "capture") - yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file)) - + await nio.start_packet_capture(output_file, data_link_type) log.info('Frame relay switch "{name}" [{id}]: starting packet capture on port {port}'.format(name=self._name, id=self._id, port=port_number)) - @asyncio.coroutine - def stop_capture(self, port_number): + async def stop_capture(self, port_number): """ Stops a packet capture. :param port_number: allocated port number """ - if port_number not in self._nios: - raise DynamipsError("Port {} is not allocated".format(port_number)) - - nio = self._nios[port_number] - yield from nio.unbind_filter("both") + nio = self.get_nio(port_number) + if not nio.capturing: + return + await nio.stop_packet_capture() log.info('Frame relay switch "{name}" [{id}]: stopping packet capture on port {port}'.format(name=self._name, id=self._id, port=port_number)) diff --git a/gns3server/compute/dynamips/nodes/router.py b/gns3server/compute/dynamips/nodes/router.py index a05e61aa..d7472a46 100644 --- a/gns3server/compute/dynamips/nodes/router.py +++ b/gns3server/compute/dynamips/nodes/router.py @@ -36,8 +36,6 @@ log = logging.getLogger(__name__) from ...base_node import BaseNode from ..dynamips_error import DynamipsError -from ..nios.nio_udp import NIOUDP - from gns3server.utils.file_watcher import FileWatcher from gns3server.utils.asyncio import wait_run_in_executor, monitor_process @@ -64,9 +62,9 @@ class Router(BaseNode): 2: "running", 3: "suspended"} - def __init__(self, name, node_id, project, manager, dynamips_id=None, console=None, aux=None, platform="c7200", hypervisor=None, ghost_flag=False): + def __init__(self, name, node_id, project, manager, dynamips_id=None, console=None, console_type="telnet", aux=None, platform="c7200", hypervisor=None, ghost_flag=False): - super().__init__(name, node_id, project, manager, console=console, aux=aux, allocate_aux=aux) + super().__init__(name, node_id, project, manager, console=console, console_type=console_type, aux=aux, allocate_aux=aux) self._working_directory = os.path.join(self.project.module_working_directory(self.manager.module_name.lower()), self.id) try: @@ -131,18 +129,21 @@ class Router(BaseNode): try: shutil.move(path, dst) except OSError as e: - raise DynamipsError("Can't move {}: {}".format(path, str(e))) + log.error("Can't move {}: {}".format(path, str(e))) + continue for path in glob.glob(os.path.join(glob.escape(dynamips_dir), "*_i{}_*".format(dynamips_id))): dst = os.path.join(self._working_directory, os.path.basename(path)) if not os.path.exists(dst): try: shutil.move(path, dst) except OSError as e: - raise DynamipsError("Can't move {}: {}".format(path, str(e))) + log.error("Can't move {}: {}".format(path, str(e))) + continue def __json__(self): router_info = {"name": self.name, + "usage": self.usage, "node_id": self.id, "node_directory": os.path.join(self._working_directory), "project_id": self.project.id, @@ -164,13 +165,12 @@ class Router(BaseNode): "auto_delete_disks": self._auto_delete_disks, "status": self.status, "console": self.console, - "console_type": "telnet", + "console_type": self.console_type, "aux": self.aux, "mac_addr": self._mac_addr, "system_id": self._system_id} - # return the relative path if the IOS image is in the images_path directory - router_info["image"] = self.manager.get_relative_image_path(self._image) + router_info["image"] = self.manager.get_relative_image_path(self._image, self.project.path) # add the slots slot_number = 0 @@ -194,7 +194,7 @@ class Router(BaseNode): """ Called when the NVRAM file has changed """ - asyncio.async(self.save_configs()) + asyncio.ensure_future(self.save_configs()) @property def dynamips_id(self): @@ -206,16 +206,15 @@ class Router(BaseNode): return self._dynamips_id - @asyncio.coroutine - def create(self): + async def create(self): if not self._hypervisor: # We start the hypervisor is the dynamips folder and next we change to node dir # this allow the creation of common files in the dynamips folder - self._hypervisor = yield from self.manager.start_new_hypervisor(working_dir=self.project.module_working_directory(self.manager.module_name.lower())) - yield from self._hypervisor.set_working_dir(self._working_directory) + self._hypervisor = await self.manager.start_new_hypervisor(working_dir=self.project.module_working_directory(self.manager.module_name.lower())) + await self._hypervisor.set_working_dir(self._working_directory) - yield from self._hypervisor.send('vm create "{name}" {id} {platform}'.format(name=self._name, + await self._hypervisor.send('vm create "{name}" {id} {platform}'.format(name=self._name, id=self._dynamips_id, platform=self._platform)) @@ -225,41 +224,40 @@ class Router(BaseNode): platform=self._platform, id=self._id)) - yield from self._hypervisor.send('vm set_con_tcp_port "{name}" {console}'.format(name=self._name, console=self._console)) + if self._console: + await self._hypervisor.send('vm set_con_tcp_port "{name}" {console}'.format(name=self._name, console=self._console)) if self.aux is not None: - yield from self._hypervisor.send('vm set_aux_tcp_port "{name}" {aux}'.format(name=self._name, aux=self.aux)) + await self._hypervisor.send('vm set_aux_tcp_port "{name}" {aux}'.format(name=self._name, aux=self.aux)) # get the default base MAC address - mac_addr = yield from self._hypervisor.send('{platform} get_mac_addr "{name}"'.format(platform=self._platform, + mac_addr = await self._hypervisor.send('{platform} get_mac_addr "{name}"'.format(platform=self._platform, name=self._name)) self._mac_addr = mac_addr[0] self._hypervisor.devices.append(self) - @asyncio.coroutine - def get_status(self): + async def get_status(self): """ Returns the status of this router :returns: inactive, shutting down, running or suspended. """ - status = yield from self._hypervisor.send('vm get_status "{name}"'.format(name=self._name)) + status = await self._hypervisor.send('vm get_status "{name}"'.format(name=self._name)) if len(status) == 0: raise DynamipsError("Can't get vm {name} status".format(name=self._name)) return self._status[int(status[0])] - @asyncio.coroutine - def start(self): + async def start(self): """ Starts this router. At least the IOS image must be set before it can start. """ - status = yield from self.get_status() + status = await self.get_status() if status == "suspended": - yield from self.resume() + await self.resume() elif status == "inactive": if not os.path.isfile(self._image) or not os.path.exists(self._image): @@ -292,19 +290,18 @@ class Router(BaseNode): # an empty private-config can prevent a router to boot. private_config_path = '' - yield from self._hypervisor.send('vm set_config "{name}" "{startup}" "{private}"'.format( + await self._hypervisor.send('vm set_config "{name}" "{startup}" "{private}"'.format( name=self._name, startup=startup_config_path, private=private_config_path)) - yield from self._hypervisor.send('vm start "{name}"'.format(name=self._name)) + await self._hypervisor.send('vm start "{name}"'.format(name=self._name)) self.status = "started" log.info('router "{name}" [{id}] has been started'.format(name=self._name, id=self._id)) self._memory_watcher = FileWatcher(self._memory_files(), self._memory_changed, strategy='hash', delay=30) monitor_process(self._hypervisor.process, self._termination_callback) - @asyncio.coroutine - def _termination_callback(self, returncode): + async def _termination_callback(self, returncode): """ Called when the process has stopped. @@ -317,94 +314,88 @@ class Router(BaseNode): if returncode != 0: self.project.emit("log.error", {"message": "Dynamips hypervisor process has stopped, return code: {}\n{}".format(returncode, self._hypervisor.read_stdout())}) - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops this router. """ - status = yield from self.get_status() + status = await self.get_status() if status != "inactive": try: - yield from self._hypervisor.send('vm stop "{name}"'.format(name=self._name)) + await self._hypervisor.send('vm stop "{name}"'.format(name=self._name)) except DynamipsError as e: - log.warn("Could not stop {}: {}".format(self._name, e)) + log.warning("Could not stop {}: {}".format(self._name, e)) self.status = "stopped" log.info('Router "{name}" [{id}] has been stopped'.format(name=self._name, id=self._id)) if self._memory_watcher: self._memory_watcher.close() self._memory_watcher = None - yield from self.save_configs() + await self.save_configs() - @asyncio.coroutine - def reload(self): + async def reload(self): """ Reload this router. """ - yield from self.stop() - yield from self.start() + await self.stop() + await self.start() - @asyncio.coroutine - def suspend(self): + async def suspend(self): """ Suspends this router. """ - status = yield from self.get_status() + status = await self.get_status() if status == "running": - yield from self._hypervisor.send('vm suspend "{name}"'.format(name=self._name)) + await self._hypervisor.send('vm suspend "{name}"'.format(name=self._name)) self.status = "suspended" log.info('Router "{name}" [{id}] has been suspended'.format(name=self._name, id=self._id)) - @asyncio.coroutine - def resume(self): + async def resume(self): """ Resumes this suspended router """ - status = yield from self.get_status() + status = await self.get_status() if status == "suspended": - yield from self._hypervisor.send('vm resume "{name}"'.format(name=self._name)) + await self._hypervisor.send('vm resume "{name}"'.format(name=self._name)) self.status = "started" log.info('Router "{name}" [{id}] has been resumed'.format(name=self._name, id=self._id)) - @asyncio.coroutine - def is_running(self): + async def is_running(self): """ Checks if this router is running. :returns: True if running, False otherwise """ - status = yield from self.get_status() + status = await self.get_status() if status == "running": return True return False - @asyncio.coroutine - def close(self): + async def close(self): - if not (yield from super().close()): + if not (await super().close()): return False for adapter in self._slots: if adapter is not None: for nio in adapter.ports.values(): if nio: - yield from nio.close() + await nio.close() - yield from self._stop_ubridge() + await self._stop_ubridge() if self in self._hypervisor.devices: self._hypervisor.devices.remove(self) if self._hypervisor and not self._hypervisor.devices: try: - yield from self.stop() - yield from self._hypervisor.send('vm delete "{}"'.format(self._name)) + await self.stop() + await self._hypervisor.send('vm delete "{}"'.format(self._name)) except DynamipsError as e: - log.warn("Could not stop and delete {}: {}".format(self._name, e)) - yield from self.hypervisor.stop() + log.warning("Could not stop and delete {}: {}".format(self._name, e)) + await self.hypervisor.stop() if self._auto_delete_disks: # delete nvram and disk files @@ -418,9 +409,9 @@ class Router(BaseNode): for file in files: try: log.debug("Deleting file {}".format(file)) - yield from wait_run_in_executor(os.remove, file) + await wait_run_in_executor(os.remove, file) except OSError as e: - log.warn("Could not delete file {}: {}".format(file, e)) + log.warning("Could not delete file {}: {}".format(file, e)) continue self.manager.release_dynamips_id(self.project.id, self.dynamips_id) @@ -445,37 +436,34 @@ class Router(BaseNode): return self._hypervisor - @asyncio.coroutine - def list(self): + async def list(self): """ Returns all VM instances :returns: list of all VM instances """ - vm_list = yield from self._hypervisor.send("vm list") + vm_list = await self._hypervisor.send("vm list") return vm_list - @asyncio.coroutine - def list_con_ports(self): + async def list_con_ports(self): """ Returns all VM console TCP ports :returns: list of port numbers """ - port_list = yield from self._hypervisor.send("vm list_con_ports") + port_list = await self._hypervisor.send("vm list_con_ports") return port_list - @asyncio.coroutine - def set_debug_level(self, level): + async def set_debug_level(self, level): """ Sets the debug level for this router (default is 0). :param level: level number """ - yield from self._hypervisor.send('vm set_debug_level "{name}" {level}'.format(name=self._name, level=level)) + await self._hypervisor.send('vm set_debug_level "{name}" {level}'.format(name=self._name, level=level)) @property def image(self): @@ -487,8 +475,7 @@ class Router(BaseNode): return self._image - @asyncio.coroutine - def set_image(self, image): + async def set_image(self, image): """ Sets the IOS image for this router. There is no default. @@ -496,9 +483,9 @@ class Router(BaseNode): :param image: path to IOS image file """ - image = self.manager.get_abs_image_path(image) + image = self.manager.get_abs_image_path(image, self.project.path) - yield from self._hypervisor.send('vm set_ios "{name}" "{image}"'.format(name=self._name, image=image)) + await self._hypervisor.send('vm set_ios "{name}" "{image}"'.format(name=self._name, image=image)) log.info('Router "{name}" [{id}]: has a new IOS image set: "{image}"'.format(name=self._name, id=self._id, @@ -516,8 +503,7 @@ class Router(BaseNode): return self._ram - @asyncio.coroutine - def set_ram(self, ram): + async def set_ram(self, ram): """ Sets amount of RAM allocated to this router @@ -527,7 +513,7 @@ class Router(BaseNode): if self._ram == ram: return - yield from self._hypervisor.send('vm set_ram "{name}" {ram}'.format(name=self._name, ram=ram)) + await self._hypervisor.send('vm set_ram "{name}" {ram}'.format(name=self._name, ram=ram)) log.info('Router "{name}" [{id}]: RAM updated from {old_ram}MB to {new_ram}MB'.format(name=self._name, id=self._id, old_ram=self._ram, @@ -544,8 +530,7 @@ class Router(BaseNode): return self._nvram - @asyncio.coroutine - def set_nvram(self, nvram): + async def set_nvram(self, nvram): """ Sets amount of NVRAM allocated to this router @@ -555,7 +540,7 @@ class Router(BaseNode): if self._nvram == nvram: return - yield from self._hypervisor.send('vm set_nvram "{name}" {nvram}'.format(name=self._name, nvram=nvram)) + await self._hypervisor.send('vm set_nvram "{name}" {nvram}'.format(name=self._name, nvram=nvram)) log.info('Router "{name}" [{id}]: NVRAM updated from {old_nvram}KB to {new_nvram}KB'.format(name=self._name, id=self._id, old_nvram=self._nvram, @@ -572,8 +557,7 @@ class Router(BaseNode): return self._mmap - @asyncio.coroutine - def set_mmap(self, mmap): + async def set_mmap(self, mmap): """ Enable/Disable use of a mapped file to simulate router memory. By default, a mapped file is used. This is a bit slower, but requires less memory. @@ -586,7 +570,7 @@ class Router(BaseNode): else: flag = 0 - yield from self._hypervisor.send('vm set_ram_mmap "{name}" {mmap}'.format(name=self._name, mmap=flag)) + await self._hypervisor.send('vm set_ram_mmap "{name}" {mmap}'.format(name=self._name, mmap=flag)) if mmap: log.info('Router "{name}" [{id}]: mmap enabled'.format(name=self._name, id=self._id)) @@ -604,8 +588,7 @@ class Router(BaseNode): return self._sparsemem - @asyncio.coroutine - def set_sparsemem(self, sparsemem): + async def set_sparsemem(self, sparsemem): """ Enable/disable use of sparse memory @@ -616,7 +599,7 @@ class Router(BaseNode): flag = 1 else: flag = 0 - yield from self._hypervisor.send('vm set_sparse_mem "{name}" {sparsemem}'.format(name=self._name, sparsemem=flag)) + await self._hypervisor.send('vm set_sparse_mem "{name}" {sparsemem}'.format(name=self._name, sparsemem=flag)) if sparsemem: log.info('Router "{name}" [{id}]: sparse memory enabled'.format(name=self._name, id=self._id)) @@ -634,8 +617,7 @@ class Router(BaseNode): return self._clock_divisor - @asyncio.coroutine - def set_clock_divisor(self, clock_divisor): + async def set_clock_divisor(self, clock_divisor): """ Sets the clock divisor value. The higher is the value, the faster is the clock in the virtual machine. The default is 4, but it is often required to adjust it. @@ -643,7 +625,7 @@ class Router(BaseNode): :param clock_divisor: clock divisor value (integer) """ - yield from self._hypervisor.send('vm set_clock_divisor "{name}" {clock}'.format(name=self._name, clock=clock_divisor)) + await self._hypervisor.send('vm set_clock_divisor "{name}" {clock}'.format(name=self._name, clock=clock_divisor)) log.info('Router "{name}" [{id}]: clock divisor updated from {old_clock} to {new_clock}'.format(name=self._name, id=self._id, old_clock=self._clock_divisor, @@ -660,8 +642,7 @@ class Router(BaseNode): return self._idlepc - @asyncio.coroutine - def set_idlepc(self, idlepc): + async def set_idlepc(self, idlepc): """ Sets the idle Pointer Counter (PC) @@ -671,18 +652,40 @@ class Router(BaseNode): if not idlepc: idlepc = "0x0" - is_running = yield from self.is_running() + is_running = await self.is_running() if not is_running: # router is not running - yield from self._hypervisor.send('vm set_idle_pc "{name}" {idlepc}'.format(name=self._name, idlepc=idlepc)) + await self._hypervisor.send('vm set_idle_pc "{name}" {idlepc}'.format(name=self._name, idlepc=idlepc)) else: - yield from self._hypervisor.send('vm set_idle_pc_online "{name}" 0 {idlepc}'.format(name=self._name, idlepc=idlepc)) + await self._hypervisor.send('vm set_idle_pc_online "{name}" 0 {idlepc}'.format(name=self._name, idlepc=idlepc)) log.info('Router "{name}" [{id}]: idle-PC set to {idlepc}'.format(name=self._name, id=self._id, idlepc=idlepc)) self._idlepc = idlepc - @asyncio.coroutine - def get_idle_pc_prop(self): + def set_process_priority_windows(self, pid, priority=None): + """ + Sets process priority on Windows + + :param pid: process PID + """ + + import win32api + import win32process + import win32con + import pywintypes + + old_priority = None + try: + handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid) + old_priority = win32process.GetPriorityClass(handle) + if priority is None: + priority = win32process.BELOW_NORMAL_PRIORITY_CLASS + win32process.SetPriorityClass(handle, priority) + except pywintypes.error as e: + log.error("Cannot set priority for Dynamips process (PID={}) ".format(pid, e.strerror)) + return old_priority + + async def get_idle_pc_prop(self): """ Gets the idle PC proposals. Takes 1000 measurements and records up to 10 idle PC proposals. @@ -691,37 +694,41 @@ class Router(BaseNode): :returns: list of idle PC proposal """ - is_running = yield from self.is_running() + is_running = await self.is_running() was_auto_started = False if not is_running: - yield from self.start() + await self.start() was_auto_started = True - yield from asyncio.sleep(20) # leave time to the router to boot + await asyncio.sleep(20) # leave time to the router to boot log.info('Router "{name}" [{id}] has started calculating Idle-PC values'.format(name=self._name, id=self._id)) + old_priority = None + if sys.platform.startswith("win"): + old_priority = self.set_process_priority_windows(self._hypervisor.process.pid) begin = time.time() - idlepcs = yield from self._hypervisor.send('vm get_idle_pc_prop "{}" 0'.format(self._name)) + idlepcs = await self._hypervisor.send('vm get_idle_pc_prop "{}" 0'.format(self._name)) + if old_priority is not None: + self.set_process_priority_windows(self._hypervisor.process.pid, old_priority) log.info('Router "{name}" [{id}] has finished calculating Idle-PC values after {time:.4f} seconds'.format(name=self._name, id=self._id, time=time.time() - begin)) if was_auto_started: - yield from self.stop() + await self.stop() return idlepcs - @asyncio.coroutine - def show_idle_pc_prop(self): + async def show_idle_pc_prop(self): """ Dumps the idle PC proposals (previously generated). :returns: list of idle PC proposal """ - is_running = yield from self.is_running() + is_running = await self.is_running() if not is_running: # router is not running raise DynamipsError('Router "{name}" is not running'.format(name=self._name)) - proposals = yield from self._hypervisor.send('vm show_idle_pc_prop "{}" 0'.format(self._name)) + proposals = await self._hypervisor.send('vm show_idle_pc_prop "{}" 0'.format(self._name)) return proposals @property @@ -734,17 +741,16 @@ class Router(BaseNode): return self._idlemax - @asyncio.coroutine - def set_idlemax(self, idlemax): + async def set_idlemax(self, idlemax): """ Sets CPU idle max value :param idlemax: idle max value (integer) """ - is_running = yield from self.is_running() + is_running = await self.is_running() if is_running: # router is running - yield from self._hypervisor.send('vm set_idle_max "{name}" 0 {idlemax}'.format(name=self._name, idlemax=idlemax)) + await self._hypervisor.send('vm set_idle_max "{name}" 0 {idlemax}'.format(name=self._name, idlemax=idlemax)) log.info('Router "{name}" [{id}]: idlemax updated from {old_idlemax} to {new_idlemax}'.format(name=self._name, id=self._id, @@ -763,17 +769,16 @@ class Router(BaseNode): return self._idlesleep - @asyncio.coroutine - def set_idlesleep(self, idlesleep): + async def set_idlesleep(self, idlesleep): """ Sets CPU idle sleep time value. :param idlesleep: idle sleep value (integer) """ - is_running = yield from self.is_running() + is_running = await self.is_running() if is_running: # router is running - yield from self._hypervisor.send('vm set_idle_sleep_time "{name}" 0 {idlesleep}'.format(name=self._name, + await self._hypervisor.send('vm set_idle_sleep_time "{name}" 0 {idlesleep}'.format(name=self._name, idlesleep=idlesleep)) log.info('Router "{name}" [{id}]: idlesleep updated from {old_idlesleep} to {new_idlesleep}'.format(name=self._name, @@ -793,15 +798,14 @@ class Router(BaseNode): return self._ghost_file - @asyncio.coroutine - def set_ghost_file(self, ghost_file): + async def set_ghost_file(self, ghost_file): """ Sets ghost RAM file :ghost_file: path to ghost file """ - yield from self._hypervisor.send('vm set_ghost_file "{name}" {ghost_file}'.format(name=self._name, + await self._hypervisor.send('vm set_ghost_file "{name}" {ghost_file}'.format(name=self._name, ghost_file=shlex.quote(ghost_file))) log.info('Router "{name}" [{id}]: ghost file set to {ghost_file}'.format(name=self._name, @@ -831,8 +835,7 @@ class Router(BaseNode): return self._ghost_status - @asyncio.coroutine - def set_ghost_status(self, ghost_status): + async def set_ghost_status(self, ghost_status): """ Sets ghost RAM status @@ -842,7 +845,7 @@ class Router(BaseNode): 2 => Use an existing ghost instance """ - yield from self._hypervisor.send('vm set_ghost_status "{name}" {ghost_status}'.format(name=self._name, + await self._hypervisor.send('vm set_ghost_status "{name}" {ghost_status}'.format(name=self._name, ghost_status=ghost_status)) log.info('Router "{name}" [{id}]: ghost status set to {ghost_status}'.format(name=self._name, @@ -860,8 +863,7 @@ class Router(BaseNode): return self._exec_area - @asyncio.coroutine - def set_exec_area(self, exec_area): + async def set_exec_area(self, exec_area): """ Sets the exec area value. The exec area is a pool of host memory used to store pages @@ -871,7 +873,7 @@ class Router(BaseNode): :param exec_area: exec area value (integer) """ - yield from self._hypervisor.send('vm set_exec_area "{name}" {exec_area}'.format(name=self._name, + await self._hypervisor.send('vm set_exec_area "{name}" {exec_area}'.format(name=self._name, exec_area=exec_area)) log.info('Router "{name}" [{id}]: exec area updated from {old_exec}MB to {new_exec}MB'.format(name=self._name, @@ -890,15 +892,14 @@ class Router(BaseNode): return self._disk0 - @asyncio.coroutine - def set_disk0(self, disk0): + async def set_disk0(self, disk0): """ Sets the size (MB) for PCMCIA disk0. :param disk0: disk0 size (integer) """ - yield from self._hypervisor.send('vm set_disk0 "{name}" {disk0}'.format(name=self._name, disk0=disk0)) + await self._hypervisor.send('vm set_disk0 "{name}" {disk0}'.format(name=self._name, disk0=disk0)) log.info('Router "{name}" [{id}]: disk0 updated from {old_disk0}MB to {new_disk0}MB'.format(name=self._name, id=self._id, @@ -916,15 +917,14 @@ class Router(BaseNode): return self._disk1 - @asyncio.coroutine - def set_disk1(self, disk1): + async def set_disk1(self, disk1): """ Sets the size (MB) for PCMCIA disk1. :param disk1: disk1 size (integer) """ - yield from self._hypervisor.send('vm set_disk1 "{name}" {disk1}'.format(name=self._name, disk1=disk1)) + await self._hypervisor.send('vm set_disk1 "{name}" {disk1}'.format(name=self._name, disk1=disk1)) log.info('Router "{name}" [{id}]: disk1 updated from {old_disk1}MB to {new_disk1}MB'.format(name=self._name, id=self._id, @@ -942,8 +942,7 @@ class Router(BaseNode): return self._auto_delete_disks - @asyncio.coroutine - def set_auto_delete_disks(self, auto_delete_disks): + async def set_auto_delete_disks(self, auto_delete_disks): """ Enable/disable use of auto delete disks @@ -956,8 +955,7 @@ class Router(BaseNode): log.info('Router "{name}" [{id}]: auto delete disks disabled'.format(name=self._name, id=self._id)) self._auto_delete_disks = auto_delete_disks - @asyncio.coroutine - def set_console(self, console): + async def set_console(self, console): """ Sets the TCP console port. @@ -965,10 +963,28 @@ class Router(BaseNode): """ self.console = console - yield from self._hypervisor.send('vm set_con_tcp_port "{name}" {console}'.format(name=self._name, console=self.console)) + await self._hypervisor.send('vm set_con_tcp_port "{name}" {console}'.format(name=self._name, console=self.console)) - @asyncio.coroutine - def set_aux(self, aux): + async def set_console_type(self, console_type): + """ + Sets the console type. + + :param console_type: console type + """ + + if self.console_type != console_type: + status = await self.get_status() + if status == "running": + raise DynamipsError('"{name}" must be stopped to change the console type to {console_type}'.format(name=self._name, + console_type=console_type)) + + + self.console_type = console_type + + if self._console and console_type == "telnet": + await self._hypervisor.send('vm set_con_tcp_port "{name}" {console}'.format(name=self._name, console=self._console)) + + async def set_aux(self, aux): """ Sets the TCP auxiliary port. @@ -976,17 +992,16 @@ class Router(BaseNode): """ self.aux = aux - yield from self._hypervisor.send('vm set_aux_tcp_port "{name}" {aux}'.format(name=self._name, aux=aux)) + await self._hypervisor.send('vm set_aux_tcp_port "{name}" {aux}'.format(name=self._name, aux=aux)) - @asyncio.coroutine - def get_cpu_usage(self, cpu_id=0): + async def get_cpu_usage(self, cpu_id=0): """ Shows cpu usage in seconds, "cpu_id" is ignored. :returns: cpu usage in seconds """ - cpu_usage = yield from self._hypervisor.send('vm cpu_usage "{name}" {cpu_id}'.format(name=self._name, cpu_id=cpu_id)) + cpu_usage = await self._hypervisor.send('vm cpu_usage "{name}" {cpu_id}'.format(name=self._name, cpu_id=cpu_id)) return int(cpu_usage[0]) @property @@ -999,15 +1014,14 @@ class Router(BaseNode): return self._mac_addr - @asyncio.coroutine - def set_mac_addr(self, mac_addr): + async def set_mac_addr(self, mac_addr): """ Sets the MAC address. :param mac_addr: a MAC address (hexadecimal format: hh:hh:hh:hh:hh:hh) """ - yield from self._hypervisor.send('{platform} set_mac_addr "{name}" {mac_addr}'.format(platform=self._platform, + await self._hypervisor.send('{platform} set_mac_addr "{name}" {mac_addr}'.format(platform=self._platform, name=self._name, mac_addr=mac_addr)) @@ -1027,15 +1041,14 @@ class Router(BaseNode): return self._system_id - @asyncio.coroutine - def set_system_id(self, system_id): + async def set_system_id(self, system_id): """ Sets the system ID. :param system_id: a system ID (also called board processor ID) """ - yield from self._hypervisor.send('{platform} set_system_id "{name}" {system_id}'.format(platform=self._platform, + await self._hypervisor.send('{platform} set_system_id "{name}" {system_id}'.format(platform=self._platform, name=self._name, system_id=system_id)) @@ -1045,19 +1058,17 @@ class Router(BaseNode): new_id=system_id)) self._system_id = system_id - @asyncio.coroutine - def get_slot_bindings(self): + async def get_slot_bindings(self): """ Returns slot bindings. :returns: slot bindings (adapter names) list """ - slot_bindings = yield from self._hypervisor.send('vm slot_bindings "{}"'.format(self._name)) + slot_bindings = await self._hypervisor.send('vm slot_bindings "{}"'.format(self._name)) return slot_bindings - @asyncio.coroutine - def slot_add_binding(self, slot_number, adapter): + async def slot_add_binding(self, slot_number, adapter): """ Adds a slot binding (a module into a slot). @@ -1076,7 +1087,7 @@ class Router(BaseNode): slot_number=slot_number, adapter=current_adapter)) - is_running = yield from self.is_running() + is_running = await self.is_running() # Only c7200, c3600 and c3745 (NM-4T only) support new adapter while running if is_running and not ((self._platform == 'c7200' and not str(adapter).startswith('C7200')) @@ -1085,7 +1096,7 @@ class Router(BaseNode): raise DynamipsError('Adapter {adapter} cannot be added while router "{name}" is running'.format(adapter=adapter, name=self._name)) - yield from self._hypervisor.send('vm slot_add_binding "{name}" {slot_number} 0 {adapter}'.format(name=self._name, + await self._hypervisor.send('vm slot_add_binding "{name}" {slot_number} 0 {adapter}'.format(name=self._name, slot_number=slot_number, adapter=adapter)) @@ -1099,15 +1110,14 @@ class Router(BaseNode): # Generate an OIR event if the router is running if is_running: - yield from self._hypervisor.send('vm slot_oir_start "{name}" {slot_number} 0'.format(name=self._name, + await self._hypervisor.send('vm slot_oir_start "{name}" {slot_number} 0'.format(name=self._name, slot_number=slot_number)) log.info('Router "{name}" [{id}]: OIR start event sent to slot {slot_number}'.format(name=self._name, id=self._id, slot_number=slot_number)) - @asyncio.coroutine - def slot_remove_binding(self, slot_number): + async def slot_remove_binding(self, slot_number): """ Removes a slot binding (a module from a slot). @@ -1124,7 +1134,7 @@ class Router(BaseNode): raise DynamipsError('No adapter in slot {slot_number} on router "{name}"'.format(name=self._name, slot_number=slot_number)) - is_running = yield from self.is_running() + is_running = await self.is_running() # Only c7200, c3600 and c3745 (NM-4T only) support to remove adapter while running if is_running and not ((self._platform == 'c7200' and not str(adapter).startswith('C7200')) @@ -1136,14 +1146,14 @@ class Router(BaseNode): # Generate an OIR event if the router is running if is_running: - yield from self._hypervisor.send('vm slot_oir_stop "{name}" {slot_number} 0'.format(name=self._name, + await self._hypervisor.send('vm slot_oir_stop "{name}" {slot_number} 0'.format(name=self._name, slot_number=slot_number)) log.info('Router "{name}" [{id}]: OIR stop event sent to slot {slot_number}'.format(name=self._name, id=self._id, slot_number=slot_number)) - yield from self._hypervisor.send('vm slot_remove_binding "{name}" {slot_number} 0'.format(name=self._name, + await self._hypervisor.send('vm slot_remove_binding "{name}" {slot_number} 0'.format(name=self._name, slot_number=slot_number)) log.info('Router "{name}" [{id}]: adapter {adapter} removed from slot {slot_number}'.format(name=self._name, @@ -1152,8 +1162,7 @@ class Router(BaseNode): slot_number=slot_number)) self._slots[slot_number] = None - @asyncio.coroutine - def install_wic(self, wic_slot_number, wic): + async def install_wic(self, wic_slot_number, wic): """ Installs a WIC adapter into this router. @@ -1177,7 +1186,7 @@ class Router(BaseNode): # Dynamips WICs slot IDs start on a multiple of 16 # WIC1 = 16, WIC2 = 32 and WIC3 = 48 internal_wic_slot_number = 16 * (wic_slot_number + 1) - yield from self._hypervisor.send('vm slot_add_binding "{name}" {slot_number} {wic_slot_number} {wic}'.format(name=self._name, + await self._hypervisor.send('vm slot_add_binding "{name}" {slot_number} {wic_slot_number} {wic}'.format(name=self._name, slot_number=slot_number, wic_slot_number=internal_wic_slot_number, wic=wic)) @@ -1189,8 +1198,7 @@ class Router(BaseNode): adapter.install_wic(wic_slot_number, wic) - @asyncio.coroutine - def uninstall_wic(self, wic_slot_number): + async def uninstall_wic(self, wic_slot_number): """ Uninstalls a WIC adapter from this router. @@ -1213,7 +1221,7 @@ class Router(BaseNode): # Dynamips WICs slot IDs start on a multiple of 16 # WIC1 = 16, WIC2 = 32 and WIC3 = 48 internal_wic_slot_number = 16 * (wic_slot_number + 1) - yield from self._hypervisor.send('vm slot_remove_binding "{name}" {slot_number} {wic_slot_number}'.format(name=self._name, + await self._hypervisor.send('vm slot_remove_binding "{name}" {slot_number} {wic_slot_number}'.format(name=self._name, slot_number=slot_number, wic_slot_number=internal_wic_slot_number)) @@ -1223,8 +1231,7 @@ class Router(BaseNode): wic_slot_number=wic_slot_number)) adapter.uninstall_wic(wic_slot_number) - @asyncio.coroutine - def get_slot_nio_bindings(self, slot_number): + async def get_slot_nio_bindings(self, slot_number): """ Returns slot NIO bindings. @@ -1233,12 +1240,11 @@ class Router(BaseNode): :returns: list of NIO bindings """ - nio_bindings = yield from self._hypervisor.send('vm slot_nio_bindings "{name}" {slot_number}'.format(name=self._name, + nio_bindings = await self._hypervisor.send('vm slot_nio_bindings "{name}" {slot_number}'.format(name=self._name, slot_number=slot_number)) return nio_bindings - @asyncio.coroutine - def slot_add_nio_binding(self, slot_number, port_number, nio): + async def slot_add_nio_binding(self, slot_number, port_number, nio): """ Adds a slot NIO binding. @@ -1257,20 +1263,20 @@ class Router(BaseNode): raise DynamipsError("Adapter is missing in slot {slot_number}".format(slot_number=slot_number)) if not adapter.port_exists(port_number): - raise DynamipsError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + raise DynamipsError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter, port_number=port_number)) try: - yield from self._hypervisor.send('vm slot_add_nio_binding "{name}" {slot_number} {port_number} {nio}'.format(name=self._name, + await self._hypervisor.send('vm slot_add_nio_binding "{name}" {slot_number} {port_number} {nio}'.format(name=self._name, slot_number=slot_number, port_number=port_number, nio=nio)) except DynamipsError: # in case of error try to remove and add the nio binding - yield from self._hypervisor.send('vm slot_remove_nio_binding "{name}" {slot_number} {port_number}'.format(name=self._name, + await self._hypervisor.send('vm slot_remove_nio_binding "{name}" {slot_number} {port_number}'.format(name=self._name, slot_number=slot_number, port_number=port_number)) - yield from self._hypervisor.send('vm slot_add_nio_binding "{name}" {slot_number} {port_number} {nio}'.format(name=self._name, + await self._hypervisor.send('vm slot_add_nio_binding "{name}" {slot_number} {port_number} {nio}'.format(name=self._name, slot_number=slot_number, port_number=port_number, nio=nio)) @@ -1281,11 +1287,10 @@ class Router(BaseNode): slot_number=slot_number, port_number=port_number)) - yield from self.slot_enable_nio(slot_number, port_number) + await self.slot_enable_nio(slot_number, port_number) adapter.add_nio(port_number, nio) - @asyncio.coroutine - def slot_update_nio_binding(self, slot_number, port_number, nio): + async def slot_update_nio_binding(self, slot_number, port_number, nio): """ Update a slot NIO binding. @@ -1293,10 +1298,10 @@ class Router(BaseNode): :param port_number: port number :param nio: NIO instance to add to the slot/port """ - yield from nio.update() - @asyncio.coroutine - def slot_remove_nio_binding(self, slot_number, port_number): + await nio.update() + + async def slot_remove_nio_binding(self, slot_number, port_number): """ Removes a slot NIO binding. @@ -1316,18 +1321,19 @@ class Router(BaseNode): raise DynamipsError("Adapter is missing in slot {slot_number}".format(slot_number=slot_number)) if not adapter.port_exists(port_number): - raise DynamipsError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + raise DynamipsError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter, port_number=port_number)) - yield from self.slot_disable_nio(slot_number, port_number) - yield from self._hypervisor.send('vm slot_remove_nio_binding "{name}" {slot_number} {port_number}'.format(name=self._name, + await self.stop_capture(slot_number, port_number) + await self.slot_disable_nio(slot_number, port_number) + await self._hypervisor.send('vm slot_remove_nio_binding "{name}" {slot_number} {port_number}'.format(name=self._name, slot_number=slot_number, port_number=port_number)) nio = adapter.get_nio(port_number) if nio is None: return - yield from nio.close() + await nio.close() adapter.remove_nio(port_number) log.info('Router "{name}" [{id}]: NIO {nio_name} removed from port {slot_number}/{port_number}'.format(name=self._name, @@ -1338,8 +1344,7 @@ class Router(BaseNode): return nio - @asyncio.coroutine - def slot_enable_nio(self, slot_number, port_number): + async def slot_enable_nio(self, slot_number, port_number): """ Enables a slot NIO binding. @@ -1347,9 +1352,9 @@ class Router(BaseNode): :param port_number: port number """ - is_running = yield from self.is_running() + is_running = await self.is_running() if is_running: # running router - yield from self._hypervisor.send('vm slot_enable_nio "{name}" {slot_number} {port_number}'.format(name=self._name, + await self._hypervisor.send('vm slot_enable_nio "{name}" {slot_number} {port_number}'.format(name=self._name, slot_number=slot_number, port_number=port_number)) @@ -1358,8 +1363,33 @@ class Router(BaseNode): slot_number=slot_number, port_number=port_number)) - @asyncio.coroutine - def slot_disable_nio(self, slot_number, port_number): + def get_nio(self, slot_number, port_number): + """ + Gets an slot NIO binding. + + :param slot_number: slot number + :param port_number: port number + + :returns: NIO instance + """ + + try: + adapter = self._slots[slot_number] + except IndexError: + raise DynamipsError('Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, + slot_number=slot_number)) + if not adapter.port_exists(port_number): + raise DynamipsError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter, + port_number=port_number)) + + nio = adapter.get_nio(port_number) + + if not nio: + raise DynamipsError("Port {slot_number}/{port_number} is not connected".format(slot_number=slot_number, + port_number=port_number)) + return nio + + async def slot_disable_nio(self, slot_number, port_number): """ Disables a slot NIO binding. @@ -1367,9 +1397,9 @@ class Router(BaseNode): :param port_number: port number """ - is_running = yield from self.is_running() + is_running = await self.is_running() if is_running: # running router - yield from self._hypervisor.send('vm slot_disable_nio "{name}" {slot_number} {port_number}'.format(name=self._name, + await self._hypervisor.send('vm slot_disable_nio "{name}" {slot_number} {port_number}'.format(name=self._name, slot_number=slot_number, port_number=port_number)) @@ -1378,8 +1408,7 @@ class Router(BaseNode): slot_number=slot_number, port_number=port_number)) - @asyncio.coroutine - def start_capture(self, slot_number, port_number, output_file, data_link_type="DLT_EN10MB"): + async def start_capture(self, slot_number, port_number, output_file, data_link_type="DLT_EN10MB"): """ Starts a packet capture. @@ -1400,7 +1429,7 @@ class Router(BaseNode): raise DynamipsError('Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, slot_number=slot_number)) if not adapter.port_exists(port_number): - raise DynamipsError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + raise DynamipsError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter, port_number=port_number)) data_link_type = data_link_type.lower() @@ -1416,18 +1445,14 @@ class Router(BaseNode): if nio.input_filter[0] is not None and nio.output_filter[0] is not None: raise DynamipsError("Port {port_number} has already a filter applied on {adapter}".format(adapter=adapter, port_number=port_number)) - - yield from nio.bind_filter("both", "capture") - yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file)) - + await nio.start_packet_capture(output_file, data_link_type) log.info('Router "{name}" [{id}]: starting packet capture on port {slot_number}/{port_number}'.format(name=self._name, id=self._id, nio_name=nio.name, slot_number=slot_number, port_number=port_number)) - @asyncio.coroutine - def stop_capture(self, slot_number, port_number): + async def stop_capture(self, slot_number, port_number): """ Stops a packet capture. @@ -1441,7 +1466,7 @@ class Router(BaseNode): raise DynamipsError('Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, slot_number=slot_number)) if not adapter.port_exists(port_number): - raise DynamipsError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + raise DynamipsError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter, port_number=port_number)) nio = adapter.get_nio(port_number) @@ -1450,7 +1475,9 @@ class Router(BaseNode): raise DynamipsError("Port {slot_number}/{port_number} is not connected".format(slot_number=slot_number, port_number=port_number)) - yield from nio.unbind_filter("both") + if not nio.capturing: + return + await nio.stop_packet_capture() log.info('Router "{name}" [{id}]: stopping packet capture on port {slot_number}/{port_number}'.format(name=self._name, id=self._id, @@ -1491,8 +1518,7 @@ class Router(BaseNode): """ return os.path.join(self._working_directory, "configs", "i{}_private-config.cfg".format(self._dynamips_id)) - @asyncio.coroutine - def set_name(self, new_name): + async def set_name(self, new_name): """ Renames this router. @@ -1521,12 +1547,11 @@ class Router(BaseNode): except OSError as e: raise DynamipsError("Could not amend the configuration {}: {}".format(self.private_config_path, e)) - yield from self._hypervisor.send('vm rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) + await self._hypervisor.send('vm rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) log.info('Router "{name}" [{id}]: renamed to "{new_name}"'.format(name=self._name, id=self._id, new_name=new_name)) self._name = new_name - @asyncio.coroutine - def extract_config(self): + async def extract_config(self): """ Gets the contents of the config files startup-config and private-config from NVRAM. @@ -1535,7 +1560,7 @@ class Router(BaseNode): """ try: - reply = yield from self._hypervisor.send('vm extract_config "{}"'.format(self._name)) + reply = await self._hypervisor.send('vm extract_config "{}"'.format(self._name)) except DynamipsError: # for some reason Dynamips gets frozen when it does not find the magic number in the NVRAM file. return None, None @@ -1544,8 +1569,7 @@ class Router(BaseNode): private_config = reply[1][1:-1] # get private-config and remove single quotes return startup_config, private_config - @asyncio.coroutine - def save_configs(self): + async def save_configs(self): """ Saves the startup-config and private-config to files. """ @@ -1556,7 +1580,7 @@ class Router(BaseNode): except OSError as e: raise DynamipsError("Could could not create configuration directory {}: {}".format(config_path, e)) - startup_config_base64, private_config_base64 = yield from self.extract_config() + startup_config_base64, private_config_base64 = await self.extract_config() if startup_config_base64: startup_config = self.startup_config_path try: @@ -1580,32 +1604,33 @@ class Router(BaseNode): except (binascii.Error, OSError) as e: raise DynamipsError("Could not save the private configuration {}: {}".format(config_path, e)) - def delete(self): + async def delete(self): """ - Delete this VM (including all its files). + Deletes this VM (including all its files). """ + try: - yield from wait_run_in_executor(shutil.rmtree, self._working_directory) + await wait_run_in_executor(shutil.rmtree, self._working_directory) except OSError as e: - log.warn("Could not delete file {}".format(e)) + log.warning("Could not delete file {}".format(e)) self.manager.release_dynamips_id(self._project.id, self._dynamips_id) - @asyncio.coroutine - def clean_delete(self): + async def clean_delete(self): """ Deletes this router & associated files (nvram, disks etc.) """ - yield from self._hypervisor.send('vm clean_delete "{}"'.format(self._name)) + await self._hypervisor.send('vm clean_delete "{}"'.format(self._name)) self._hypervisor.devices.remove(self) try: - yield from wait_run_in_executor(shutil.rmtree, self._working_directory) + await wait_run_in_executor(shutil.rmtree, self._working_directory) except OSError as e: - log.warn("Could not delete file {}".format(e)) + log.warning("Could not delete file {}".format(e)) log.info('Router "{name}" [{id}] has been deleted (including associated files)'.format(name=self._name, id=self._id)) def _memory_files(self): + return [ os.path.join(self._working_directory, "{}_i{}_rom".format(self.platform, self.dynamips_id)), os.path.join(self._working_directory, "{}_i{}_nvram".format(self.platform, self.dynamips_id)) diff --git a/gns3server/compute/iou/__init__.py b/gns3server/compute/iou/__init__.py index 4cba97d7..028736b7 100644 --- a/gns3server/compute/iou/__init__.py +++ b/gns3server/compute/iou/__init__.py @@ -41,20 +41,19 @@ class IOU(BaseManager): super().__init__() self._iou_id_lock = asyncio.Lock() - @asyncio.coroutine - def create_node(self, *args, **kwargs): + async def create_node(self, *args, **kwargs): """ Creates a new IOU VM. :returns: IOUVM instance """ - with (yield from self._iou_id_lock): + async with self._iou_id_lock: # wait for a node to be completely created before adding a new one # this is important otherwise we allocate the same application ID # when creating multiple IOU node at the same time application_id = get_next_application_id(self.nodes) - node = yield from super().create_node(*args, application_id=application_id, **kwargs) + node = await super().create_node(*args, application_id=application_id, **kwargs) return node @staticmethod diff --git a/gns3server/compute/iou/iou_vm.py b/gns3server/compute/iou/iou_vm.py index c863d22e..6db57636 100644 --- a/gns3server/compute/iou/iou_vm.py +++ b/gns3server/compute/iou/iou_vm.py @@ -43,7 +43,7 @@ from .utils.iou_export import nvram_export from gns3server.ubridge.ubridge_error import UbridgeError from gns3server.utils.file_watcher import FileWatcher from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer -from gns3server.utils.asyncio import locked_coroutine +from gns3server.utils.asyncio import locking import gns3server.utils.asyncio import gns3server.utils.images @@ -63,18 +63,20 @@ class IOUVM(BaseNode): :param project: Project instance :param manager: Manager instance :param console: TCP console port + :param console_type: console type """ - def __init__(self, name, node_id, project, manager, application_id=None, path=None, console=None): + def __init__(self, name, node_id, project, manager, application_id=None, path=None, console=None, console_type="telnet"): - super().__init__(name, node_id, project, manager, console=console) + super().__init__(name, node_id, project, manager, console=console, console_type=console_type) self._iou_process = None self._telnet_server = None self._iou_stdout_file = "" self._started = False self._nvram_watcher = None - self._path = self.manager.get_abs_image_path(path) + self._path = self.manager.get_abs_image_path(path, project.path) + self._license_check = True # IOU settings self._ethernet_adapters = [] @@ -100,13 +102,12 @@ class IOUVM(BaseNode): self.save_configs() self.updated() - @asyncio.coroutine - def close(self): + async def close(self): """ Closes this IOU VM. """ - if not (yield from super().close()): + if not (await super().close()): return False adapters = self._ethernet_adapters + self._serial_adapters @@ -116,7 +117,7 @@ class IOUVM(BaseNode): if nio and isinstance(nio, NIOUDP): self.manager.port_manager.release_udp_port(nio.lport, self._project) - yield from self.stop() + await self.stop() @property def path(self): @@ -136,7 +137,7 @@ class IOUVM(BaseNode): :param path: path to the IOU image executable """ - self._path = self.manager.get_abs_image_path(path) + self._path = self.manager.get_abs_image_path(path, self.project.path) log.info('IOU "{name}" [{id}]: IOU image updated to "{path}"'.format(name=self._name, id=self._id, path=self._path)) @property @@ -163,27 +164,25 @@ class IOUVM(BaseNode): else: log.info('IOU "{name}" [{id}]: does not use the default IOU image values'.format(name=self._name, id=self._id)) - @asyncio.coroutine - def update_default_iou_values(self): + async def update_default_iou_values(self): """ Finds the default RAM and NVRAM values for the IOU image. """ try: - output = yield from gns3server.utils.asyncio.subprocess_check_output(self._path, "-h", cwd=self.working_dir, stderr=True) - match = re.search("-n \s+Size of nvram in Kb \(default ([0-9]+)KB\)", output) + output = await gns3server.utils.asyncio.subprocess_check_output(self._path, "-h", cwd=self.working_dir, stderr=True) + match = re.search(r"-n \s+Size of nvram in Kb \(default ([0-9]+)KB\)", output) if match: self.nvram = int(match.group(1)) - match = re.search("-m \s+Megabytes of router memory \(default ([0-9]+)MB\)", output) + match = re.search(r"-m \s+Megabytes of router memory \(default ([0-9]+)MB\)", output) if match: self.ram = int(match.group(1)) except (ValueError, OSError, subprocess.SubprocessError) as e: log.warning("could not find default RAM and NVRAM values for {}: {}".format(os.path.basename(self._path), e)) - @asyncio.coroutine - def create(self): + async def create(self): - yield from self.update_default_iou_values() + await self.update_default_iou_values() def _check_requirements(self): """ @@ -216,10 +215,11 @@ class IOUVM(BaseNode): def __json__(self): iou_vm_info = {"name": self.name, + "usage": self.usage, "node_id": self.id, "node_directory": self.working_path, "console": self._console, - "console_type": "telnet", + "console_type": self._console_type, "status": self.status, "project_id": self.project.id, "path": self.path, @@ -233,8 +233,7 @@ class IOUVM(BaseNode): "command_line": self.command_line, "application_id": self.application_id} - # return the relative path if the IOU image is in the images_path directory - iou_vm_info["path"] = self.manager.get_relative_image_path(self.path) + iou_vm_info["path"] = self.manager.get_relative_image_path(self.path, self.project.path) return iou_vm_info @property @@ -343,7 +342,7 @@ class IOUVM(BaseNode): @iourc_content.setter def iourc_content(self, value): - if value is not None: + if value: # If we don't save the value in the ~/ the licence is lost at project # reload path = os.path.join(os.path.expanduser("~/"), ".iourc") @@ -360,38 +359,55 @@ class IOUVM(BaseNode): except OSError as e: raise IOUError("Could not write the iourc file {}: {}".format(path, e)) - @asyncio.coroutine - def _library_check(self): + @property + def license_check(self): + + return self._license_check + + @license_check.setter + def license_check(self, value): + + self._license_check = value + + async def _library_check(self): """ Checks for missing shared library dependencies in the IOU image. """ try: - output = yield from gns3server.utils.asyncio.subprocess_check_output("ldd", self._path) - except (FileNotFoundError, subprocess.SubprocessError) as e: - log.warn("Could not determine the shared library dependencies for {}: {}".format(self._path, e)) + output = await gns3server.utils.asyncio.subprocess_check_output("ldd", self._path) + except (OSError, subprocess.SubprocessError) as e: + log.warning("Could not determine the shared library dependencies for {}: {}".format(self._path, e)) return - p = re.compile("([\.\w]+)\s=>\s+not found") + p = re.compile(r"([\.\w]+)\s=>\s+not found") missing_libs = p.findall(output) if missing_libs: raise IOUError("The following shared library dependencies cannot be found for IOU image {}: {}".format(self._path, ", ".join(missing_libs))) - @asyncio.coroutine - def _check_iou_licence(self): + async def _check_iou_licence(self): """ Checks for a valid IOU key in the iourc file (paranoid mode). """ + + # license check is sent by the controller + if self.license_check is False: + return + try: - license_check = self._config().getboolean("license_check", True) + # we allow license check to be disabled server wide + server_wide_license_check = self._config().getboolean("license_check", True) except ValueError: raise IOUError("Invalid licence check setting") - if license_check is False: + + if server_wide_license_check is False: + log.warning("License check is explicitly disabled on this server") return config = configparser.ConfigParser() try: + log.info("Checking IOU license in '{}'".format(self.iourc_path)) with open(self.iourc_path, encoding="utf-8") as f: config.read_file(f) except OSError as e: @@ -418,10 +434,10 @@ class IOUVM(BaseNode): # in tests or generating one if not hasattr(sys, "_called_from_test"): try: - hostid = (yield from gns3server.utils.asyncio.subprocess_check_output("hostid")).strip() + hostid = (await gns3server.utils.asyncio.subprocess_check_output("hostid")).strip() except FileNotFoundError as e: raise IOUError("Could not find hostid: {}".format(e)) - except subprocess.SubprocessError as e: + except (OSError, subprocess.SubprocessError) as e: raise IOUError("Could not execute hostid: {}".format(e)) try: @@ -476,8 +492,7 @@ class IOUVM(BaseNode): except OSError as e: raise IOUError("Cannot write nvram file {}: {}".format(nvram_file, e)) - @asyncio.coroutine - def start(self): + async def start(self): """ Starts the IOU process. """ @@ -485,7 +500,7 @@ class IOUVM(BaseNode): self._check_requirements() if not self.is_running(): - yield from self._library_check() + await self._library_check() try: self._rename_nvram_file() @@ -494,17 +509,17 @@ class IOUVM(BaseNode): iourc_path = self.iourc_path if not iourc_path: - raise IOUError("Could not find an iourc file (IOU license)") + raise IOUError("Could not find an iourc file (IOU license), please configure an IOU license") if not os.path.isfile(iourc_path): raise IOUError("The iourc path '{}' is not a regular file".format(iourc_path)) - yield from self._check_iou_licence() - yield from self._start_ubridge() + await self._check_iou_licence() + await self._start_ubridge() self._create_netmap_config() if self.use_default_iou_values: # make sure we have the default nvram amount to correctly push the configs - yield from self.update_default_iou_values() + await self.update_default_iou_values() self._push_configs_to_nvram() # check if there is enough RAM to run @@ -514,14 +529,24 @@ class IOUVM(BaseNode): # created a environment variable pointing to the iourc file. env = os.environ.copy() - - if "IOURC" not in os.environ: + if "IOURC" not in os.environ and iourc_path: env["IOURC"] = iourc_path - command = yield from self._build_command() + + # create a symbolic link to the image to avoid IOU error "failed code signing checks" + # on newer images, see https://github.com/GNS3/gns3-server/issues/1484 + try: + symlink = os.path.join(self.working_dir, os.path.basename(self.path)) + if os.path.islink(symlink): + os.unlink(symlink) + os.symlink(self.path, symlink) + except OSError as e: + raise IOUError("Could not create symbolic link: {}".format(e)) + + command = await self._build_command() try: log.info("Starting IOU: {}".format(command)) self.command_line = ' '.join(command) - self._iou_process = yield from asyncio.create_subprocess_exec( + self._iou_process = await asyncio.create_subprocess_exec( *command, stdout=asyncio.subprocess.PIPE, stdin=asyncio.subprocess.PIPE, @@ -540,14 +565,19 @@ class IOUVM(BaseNode): log.error("Could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout)) raise IOUError("Could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout)) - server = AsyncioTelnetServer(reader=self._iou_process.stdout, writer=self._iou_process.stdin, binary=True, echo=True) - self._telnet_server = yield from asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console) + if self.console and self.console_type == "telnet": + server = AsyncioTelnetServer(reader=self._iou_process.stdout, writer=self._iou_process.stdin, binary=True, echo=True) + try: + self._telnet_server = await asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console) + except OSError as e: + await self.stop() + raise IOUError("Could not start Telnet server on socket {}:{}: {}".format(self._manager.port_manager.console_host, self.console, e)) # configure networking support - yield from self._networking() + await self._networking() - @locked_coroutine - def _networking(self): + @locking + async def _networking(self): """ Configures the IOL bridge in uBridge. """ @@ -555,10 +585,10 @@ class IOUVM(BaseNode): bridge_name = "IOL-BRIDGE-{}".format(self.application_id + 512) try: # delete any previous bridge if it exists - yield from self._ubridge_send("iol_bridge delete {name}".format(name=bridge_name)) + await self._ubridge_send("iol_bridge delete {name}".format(name=bridge_name)) except UbridgeError: pass - yield from self._ubridge_send("iol_bridge create {name} {bridge_id}".format(name=bridge_name, bridge_id=self.application_id + 512)) + await self._ubridge_send("iol_bridge create {name} {bridge_id}".format(name=bridge_name, bridge_id=self.application_id + 512)) bay_id = 0 for adapter in self._adapters: @@ -566,7 +596,7 @@ class IOUVM(BaseNode): for unit in adapter.ports.keys(): nio = adapter.get_nio(unit) if nio and isinstance(nio, NIOUDP): - yield from self._ubridge_send("iol_bridge add_nio_udp {name} {iol_id} {bay} {unit} {lport} {rhost} {rport}".format(name=bridge_name, + await self._ubridge_send("iol_bridge add_nio_udp {name} {iol_id} {bay} {unit} {lport} {rhost} {rport}".format(name=bridge_name, iol_id=self.application_id, bay=bay_id, unit=unit_id, @@ -574,15 +604,15 @@ class IOUVM(BaseNode): rhost=nio.rhost, rport=nio.rport)) if nio.capturing: - yield from self._ubridge_send('iol_bridge start_capture {name} "{output_file}" {data_link_type}'.format(name=bridge_name, + await self._ubridge_send('iol_bridge start_capture {name} "{output_file}" {data_link_type}'.format(name=bridge_name, output_file=nio.pcap_output_file, - data_link_type=re.sub("^DLT_", "", nio.pcap_data_link_type))) + data_link_type=re.sub(r"^DLT_", "", nio.pcap_data_link_type))) - yield from self._ubridge_apply_filters(bay_id, unit_id, nio.filters) + await self._ubridge_apply_filters(bay_id, unit_id, nio.filters) unit_id += 1 bay_id += 1 - yield from self._ubridge_send("iol_bridge start {name}".format(name=bridge_name)) + await self._ubridge_send("iol_bridge start {name}".format(name=bridge_name)) def _termination_callback(self, process_name, returncode): """ @@ -617,13 +647,12 @@ class IOUVM(BaseNode): for file_path in glob.glob(os.path.join(glob.escape(self.working_dir), "vlan.dat-*")): shutil.move(file_path, destination) - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops the IOU process. """ - yield from self._stop_ubridge() + await self._stop_ubridge() if self._nvram_watcher: self._nvram_watcher.close() self._nvram_watcher = None @@ -636,7 +665,7 @@ class IOUVM(BaseNode): self._terminate_process_iou() if self._iou_process.returncode is None: try: - yield from gns3server.utils.asyncio.wait_for_process_termination(self._iou_process, timeout=3) + await gns3server.utils.asyncio.wait_for_process_termination(self._iou_process, timeout=3) except asyncio.TimeoutError: if self._iou_process.returncode is None: log.warning("IOU process {} is still running... killing it".format(self._iou_process.pid)) @@ -646,6 +675,13 @@ class IOUVM(BaseNode): pass self._iou_process = None + try: + symlink = os.path.join(self.working_dir, os.path.basename(self.path)) + if os.path.islink(symlink): + os.unlink(symlink) + except OSError as e: + log.warning("Could not delete symbolic link: {}".format(e)) + self._started = False self.save_configs() @@ -664,14 +700,13 @@ class IOUVM(BaseNode): self._started = False self.status = "stopped" - @asyncio.coroutine - def reload(self): + async def reload(self): """ Reloads the IOU process (stop & start). """ - yield from self.stop() - yield from self.start() + await self.stop() + await self.start() def is_running(self): """ @@ -684,6 +719,19 @@ class IOUVM(BaseNode): return True return False + @BaseNode.console_type.setter + def console_type(self, new_console_type): + """ + Sets the console type for this IOU VM. + + :param new_console_type: console type (string) + """ + + if self.is_running() and self.console_type != new_console_type: + raise IOUError('"{name}" must be stopped to change the console type to {new_console_type}'.format(name=self._name, new_console_type=new_console_type)) + + super(IOUVM, IOUVM).console_type.__set__(self, new_console_type) + def _create_netmap_config(self): """ Creates the NETMAP file. @@ -703,8 +751,7 @@ class IOUVM(BaseNode): except OSError as e: raise IOUError("Could not create {}: {}".format(netmap_path, e)) - @asyncio.coroutine - def _build_command(self): + async def _build_command(self): """ Command to start the IOU process. (to be passed to subprocess.Popen()) @@ -749,7 +796,7 @@ class IOUVM(BaseNode): # command.extend(["-c", os.path.basename(startup_config_file)]) if self._l1_keepalives: - yield from self._enable_l1_keepalives(command) + await self._enable_l1_keepalives(command) command.extend([str(self.application_id)]) return command @@ -765,7 +812,7 @@ class IOUVM(BaseNode): with open(self._iou_stdout_file, "rb") as file: output = file.read().decode("utf-8", errors="replace") except OSError as e: - log.warn("could not read {}: {}".format(self._iou_stdout_file, e)) + log.warning("could not read {}: {}".format(self._iou_stdout_file, e)) return output @property @@ -828,10 +875,9 @@ class IOUVM(BaseNode): self._adapters = self._ethernet_adapters + self._serial_adapters - @asyncio.coroutine - def adapter_add_nio_binding(self, adapter_number, port_number, nio): + async def adapter_add_nio_binding(self, adapter_number, port_number, nio): """ - Adds a adapter NIO binding. + Adds an adapter NIO binding. :param adapter_number: adapter number :param port_number: port number @@ -845,7 +891,7 @@ class IOUVM(BaseNode): adapter_number=adapter_number)) if not adapter.port_exists(port_number): - raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + raise IOUError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter, port_number=port_number)) adapter.add_nio(port_number, nio) @@ -857,19 +903,18 @@ class IOUVM(BaseNode): if self.ubridge: bridge_name = "IOL-BRIDGE-{}".format(self.application_id + 512) - yield from self._ubridge_send("iol_bridge add_nio_udp {name} {iol_id} {bay} {unit} {lport} {rhost} {rport}".format(name=bridge_name, + await self._ubridge_send("iol_bridge add_nio_udp {name} {iol_id} {bay} {unit} {lport} {rhost} {rport}".format(name=bridge_name, iol_id=self.application_id, bay=adapter_number, unit=port_number, lport=nio.lport, rhost=nio.rhost, rport=nio.rport)) - yield from self._ubridge_apply_filters(adapter_number, port_number, nio.filters) + await self._ubridge_apply_filters(adapter_number, port_number, nio.filters) - @asyncio.coroutine - def adapter_update_nio_binding(self, adapter_number, port_number, nio): + async def adapter_update_nio_binding(self, adapter_number, port_number, nio): """ - Update a port NIO binding. + Updates an adapter NIO binding. :param adapter_number: adapter number :param port_number: port number @@ -877,10 +922,9 @@ class IOUVM(BaseNode): """ if self.ubridge: - yield from self._ubridge_apply_filters(adapter_number, port_number, nio.filters) + await self._ubridge_apply_filters(adapter_number, port_number, nio.filters) - @asyncio.coroutine - def _ubridge_apply_filters(self, adapter_number, port_number, filters): + async def _ubridge_apply_filters(self, adapter_number, port_number, filters): """ Apply filter like rate limiting @@ -893,20 +937,20 @@ class IOUVM(BaseNode): bridge_name=bridge_name, bay=adapter_number, unit=port_number) - yield from self._ubridge_send('iol_bridge reset_packet_filters ' + location) + await self._ubridge_send('iol_bridge reset_packet_filters ' + location) for filter in self._build_filter_list(filters): cmd = 'iol_bridge add_packet_filter {} {}'.format( location, filter) - yield from self._ubridge_send(cmd) + await self._ubridge_send(cmd) - @asyncio.coroutine - def adapter_remove_nio_binding(self, adapter_number, port_number): + async def adapter_remove_nio_binding(self, adapter_number, port_number): """ Removes an adapter NIO binding. :param adapter_number: adapter number :param port_number: port number + :returns: NIO instance """ @@ -917,7 +961,7 @@ class IOUVM(BaseNode): adapter_number=adapter_number)) if not adapter.port_exists(port_number): - raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + raise IOUError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter, port_number=port_number)) nio = adapter.get_nio(port_number) @@ -932,12 +976,39 @@ class IOUVM(BaseNode): if self.ubridge: bridge_name = "IOL-BRIDGE-{}".format(self.application_id + 512) - yield from self._ubridge_send("iol_bridge delete_nio_udp {name} {bay} {unit}".format(name=bridge_name, + await self._ubridge_send("iol_bridge delete_nio_udp {name} {bay} {unit}".format(name=bridge_name, bay=adapter_number, unit=port_number)) return nio + def get_nio(self, adapter_number, port_number): + """ + Gets an adapter NIO binding. + + :param adapter_number: adapter number + :param port_number: port number + + :returns: NIO instance + """ + + try: + adapter = self._adapters[adapter_number] + except IndexError: + raise IOUError('Adapter {adapter_number} does not exist on IOU "{name}"'.format(name=self._name, + adapter_number=adapter_number)) + + if not adapter.port_exists(port_number): + raise IOUError("Port {port_number} does not exist on adapter {adapter}".format(adapter=adapter, + port_number=port_number)) + + nio = adapter.get_nio(port_number) + + if not nio: + raise IOUError("NIO {port_number} does not exist on adapter {adapter}".format(adapter=adapter, + port_number=port_number)) + return nio + @property def l1_keepalives(self): """ @@ -962,8 +1033,7 @@ class IOUVM(BaseNode): else: log.info('IOU "{name}" [{id}]: has deactivated layer 1 keepalive messages'.format(name=self._name, id=self._id)) - @asyncio.coroutine - def _enable_l1_keepalives(self, command): + async def _enable_l1_keepalives(self, command): """ Enables L1 keepalive messages if supported. @@ -974,8 +1044,8 @@ class IOUVM(BaseNode): if "IOURC" not in os.environ: env["IOURC"] = self.iourc_path try: - output = yield from gns3server.utils.asyncio.subprocess_check_output(self._path, "-h", cwd=self.working_dir, env=env, stderr=True) - if re.search("-l\s+Enable Layer 1 keepalive messages", output): + output = await gns3server.utils.asyncio.subprocess_check_output(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"]) else: raise IOUError("layer 1 keepalive messages are not supported by {}".format(os.path.basename(self._path))) @@ -1206,8 +1276,7 @@ class IOUVM(BaseNode): except (binascii.Error, OSError) as e: raise IOUError("Could not save the private configuration {}: {}".format(config_path, e)) - @asyncio.coroutine - def start_capture(self, adapter_number, port_number, output_file, data_link_type="DLT_EN10MB"): + async def start_capture(self, adapter_number, port_number, output_file, data_link_type="DLT_EN10MB"): """ Starts a packet capture. @@ -1217,26 +1286,12 @@ class IOUVM(BaseNode): :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB """ - try: - adapter = self._adapters[adapter_number] - except IndexError: - raise IOUError('Adapter {adapter_number} does not exist on IOU "{name}"'.format(name=self._name, - adapter_number=adapter_number)) - - if not adapter.port_exists(port_number): - raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, - port_number=port_number)) - - nio = adapter.get_nio(port_number) - if not nio: - raise IOUError("NIO {port_number} does not exist in adapter {adapter}".format(adapter=adapter, - port_number=port_number)) - + nio = self.get_nio(adapter_number, port_number) if nio.capturing: raise IOUError("Packet capture is already activated on {adapter_number}/{port_number}".format(adapter_number=adapter_number, port_number=port_number)) - nio.startPacketCapture(output_file, data_link_type) + nio.start_packet_capture(output_file, data_link_type) log.info('IOU "{name}" [{id}]: starting packet capture on {adapter_number}/{port_number} to {output_file}'.format(name=self._name, id=self._id, adapter_number=adapter_number, @@ -1245,14 +1300,13 @@ class IOUVM(BaseNode): if self.ubridge: bridge_name = "IOL-BRIDGE-{}".format(self.application_id + 512) - yield from self._ubridge_send('iol_bridge start_capture {name} {bay} {unit} "{output_file}" {data_link_type}'.format(name=bridge_name, + await self._ubridge_send('iol_bridge start_capture {name} {bay} {unit} "{output_file}" {data_link_type}'.format(name=bridge_name, bay=adapter_number, unit=port_number, output_file=output_file, - data_link_type=re.sub("^DLT_", "", data_link_type))) + data_link_type=re.sub(r"^DLT_", "", data_link_type))) - @asyncio.coroutine - def stop_capture(self, adapter_number, port_number): + async def stop_capture(self, adapter_number, port_number): """ Stops a packet capture. @@ -1260,28 +1314,16 @@ class IOUVM(BaseNode): :param port_number: port number """ - try: - adapter = self._adapters[adapter_number] - except IndexError: - raise IOUError('Adapter {adapter_number} does not exist on IOU "{name}"'.format(name=self._name, - adapter_number=adapter_number)) - - if not adapter.port_exists(port_number): - raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, - port_number=port_number)) - - nio = adapter.get_nio(port_number) - if not nio: - raise IOUError("NIO {port_number} does not exist in adapter {adapter}".format(adapter=adapter, - port_number=port_number)) - - nio.stopPacketCapture() + nio = self.get_nio(adapter_number, port_number) + if not nio.capturing: + return + nio.stop_packet_capture() log.info('IOU "{name}" [{id}]: stopping packet capture on {adapter_number}/{port_number}'.format(name=self._name, id=self._id, adapter_number=adapter_number, port_number=port_number)) if self.ubridge: bridge_name = "IOL-BRIDGE-{}".format(self.application_id + 512) - yield from self._ubridge_send('iol_bridge stop_capture {name} {bay} {unit}'.format(name=bridge_name, + await self._ubridge_send('iol_bridge stop_capture {name} {bay} {unit}'.format(name=bridge_name, bay=adapter_number, unit=port_number)) diff --git a/gns3server/compute/iou/utils/application_id.py b/gns3server/compute/iou/utils/application_id.py index 5bd2c125..1caf9b3b 100644 --- a/gns3server/compute/iou/utils/application_id.py +++ b/gns3server/compute/iou/utils/application_id.py @@ -29,6 +29,7 @@ def get_next_application_id(nodes): :raises IOUError when exceeds number :return: integer first free id """ + used = set([n.application_id for n in nodes]) pool = set(range(1, 512)) try: diff --git a/gns3server/compute/nios/nio.py b/gns3server/compute/nios/nio.py index b1ab24ae..324c2639 100644 --- a/gns3server/compute/nios/nio.py +++ b/gns3server/compute/nios/nio.py @@ -29,10 +29,12 @@ class NIO(object): def __init__(self): self._capturing = False + self._suspended = False + self._filters = {} self._pcap_output_file = "" self._pcap_data_link_type = "" - def startPacketCapture(self, pcap_output_file, pcap_data_link_type="DLT_EN10MB"): + def start_packet_capture(self, pcap_output_file, pcap_data_link_type="DLT_EN10MB"): """ :param pcap_output_file: PCAP destination file for the capture :param pcap_data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB @@ -42,7 +44,7 @@ class NIO(object): self._pcap_output_file = pcap_output_file self._pcap_data_link_type = pcap_data_link_type - def stopPacketCapture(self): + def stop_packet_capture(self): self._capturing = False self._pcap_output_file = "" @@ -61,6 +63,7 @@ class NIO(object): def pcap_output_file(self): """ Returns the path to the PCAP output file. + :returns: path to the PCAP output file """ @@ -70,7 +73,49 @@ class NIO(object): def pcap_data_link_type(self): """ Returns the PCAP data link type + :returns: PCAP data link type (DLT_* value) """ return self._pcap_data_link_type + + @property + def suspend(self): + """ + Returns if this link is suspended or not. + + :returns: boolean + """ + + return self._suspended + + @suspend.setter + def suspend(self, suspended): + """ + Suspend this link. + + :param suspended: boolean + """ + + self._suspended = suspended + + @property + def filters(self): + """ + Returns the list of packet filters for this NIO. + + :returns: packet filters (dictionary) + """ + + return self._filters + + @filters.setter + def filters(self, new_filters): + """ + Set a list of packet filters for this NIO. + + :param new_filters: packet filters (dictionary) + """ + + assert isinstance(new_filters, dict) + self._filters = new_filters diff --git a/gns3server/compute/nios/nio_udp.py b/gns3server/compute/nios/nio_udp.py index 36305312..a87875fe 100644 --- a/gns3server/compute/nios/nio_udp.py +++ b/gns3server/compute/nios/nio_udp.py @@ -32,25 +32,12 @@ class NIOUDP(NIO): :param rport: remote port number """ - def __init__(self, lport, rhost, rport, filters): + def __init__(self, lport, rhost, rport): super().__init__() self._lport = lport self._rhost = rhost self._rport = rport - assert isinstance(filters, dict) - self._filters = filters - - @property - def filters(self): - """ - Return the list of filter on this NIO - """ - return self._filters - - @filters.setter - def filters(self, val): - self._filters = val @property def lport(self): diff --git a/gns3server/compute/notification_manager.py b/gns3server/compute/notification_manager.py index 381e2a87..b6b67f7e 100644 --- a/gns3server/compute/notification_manager.py +++ b/gns3server/compute/notification_manager.py @@ -23,7 +23,7 @@ from ..notification_queue import NotificationQueue class NotificationManager: """ Manage the notification queue where the controller - will connect to get notifications from compute servers + will connect to get notifications from computes """ def __init__(self): @@ -60,6 +60,7 @@ class NotificationManager: def instance(): """ Singleton to return only on instance of NotificationManager. + :returns: instance of NotificationManager """ diff --git a/gns3server/compute/port_manager.py b/gns3server/compute/port_manager.py index c78dbc9b..9db76a4d 100644 --- a/gns3server/compute/port_manager.py +++ b/gns3server/compute/port_manager.py @@ -23,7 +23,7 @@ import logging log = logging.getLogger(__name__) -# This ports are disallowed by Chrome and Firefox to avoid issues, we skip them as well +# These ports are disallowed by Chrome and Firefox to avoid issues, we skip them as well BANNED_PORTS = set((1, 7, 9, 11, 13, 15, 17, 19, 20, 21, 22, 23, 25, 37, 42, 43, 53, 77, 79, 87, 95, 101, 102, 103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 139, 143, 179, 389, 465, 512, 513, 514, 515, 526, 530, 531, 532, 540, 556, 563, 587, 601, 636, 993, 995, 2049, 3659, 4045, 6000, 6665, 6666, 6667, @@ -67,16 +67,25 @@ class PortManager: cls._instance = cls() return cls._instance + def __json__(self): + + return {"console_port_range": self._console_port_range, + "console_ports": list(self._used_tcp_ports), + "udp_port_range": self._udp_port_range, + "udp_ports": list(self._used_udp_ports)} + @property def console_host(self): + assert self._console_host is not None return self._console_host @console_host.setter def console_host(self, new_host): """ - If allow remote connection we need to bind console host to 0.0.0.0 + Bind console host to 0.0.0.0 if remote connections are allowed. """ + server_config = Config.instance().get_section_config("Server") remote_console_connections = server_config.getboolean("allow_remote_console") if remote_console_connections: @@ -228,14 +237,12 @@ class PortManager: port = self.get_free_tcp_port(project, port_range_start=port_range_start, port_range_end=port_range_end) msg = "TCP port {} already in use on host {}. Port has been replaced by {}".format(old_port, self._console_host, port) log.debug(msg) - #project.emit("log.warning", {"message": msg}) return port if port < port_range_start or port > port_range_end: old_port = port port = self.get_free_tcp_port(project, port_range_start=port_range_start, port_range_end=port_range_end) msg = "TCP port {} is outside the range {}-{} on host {}. Port has been replaced by {}".format(old_port, port_range_start, port_range_end, self._console_host, port) log.debug(msg) - #project.emit("log.warning", {"message": msg}) return port try: PortManager._check_port(self._console_host, port, "TCP") @@ -244,7 +251,6 @@ class PortManager: port = self.get_free_tcp_port(project, port_range_start=port_range_start, port_range_end=port_range_end) msg = "TCP port {} already in use on host {}. Port has been replaced by {}".format(old_port, self._console_host, port) log.debug(msg) - #project.emit("log.warning", {"message": msg}) return port self._used_tcp_ports.add(port) diff --git a/gns3server/compute/project.py b/gns3server/compute/project.py index 8be8fb1e..38b96522 100644 --- a/gns3server/compute/project.py +++ b/gns3server/compute/project.py @@ -20,18 +20,15 @@ import aiohttp import shutil import asyncio import hashlib -import zipstream -import zipfile -import json from uuid import UUID, uuid4 + from .port_manager import PortManager from .notification_manager import NotificationManager from ..config import Config from ..utils.asyncio import wait_run_in_executor from ..utils.path import check_path_allowed, get_default_project_directory - import logging log = logging.getLogger(__name__) @@ -46,7 +43,7 @@ class Project: :param path: path of the project. (None use the standard directory) """ - def __init__(self, name=None, project_id=None, path=None): + def __init__(self, name=None, project_id=None, path=None, variables=None): self._name = name if project_id: @@ -61,6 +58,7 @@ class Project: self._nodes = set() self._used_tcp_ports = set() self._used_udp_ports = set() + self._variables = variables if path is None: location = get_default_project_directory() @@ -83,7 +81,8 @@ class Project: return { "name": self._name, - "project_id": self._id + "project_id": self._id, + "variables": self._variables } def _config(self): @@ -110,7 +109,7 @@ class Project: if hasattr(self, "_path"): if path != self._path and self.is_local() is False: - raise aiohttp.web.HTTPForbidden(text="You are not allowed to modify the project directory path") + raise aiohttp.web.HTTPForbidden(text="Changing the project directory path is not allowed") self._path = path @@ -123,7 +122,7 @@ class Project: def name(self, name): if "/" in name or "\\" in name: - raise aiohttp.web.HTTPForbidden(text="Name can not contain path separator") + raise aiohttp.web.HTTPForbidden(text="Project names cannot contain path separators") self._name = name @property @@ -131,6 +130,14 @@ class Project: return self._nodes + @property + def variables(self): + return self._variables + + @variables.setter + def variables(self, variables): + self._variables = variables + def record_tcp_port(self, port): """ Associate a reserved TCP port number with this project. @@ -232,12 +239,12 @@ class Project: def capture_working_directory(self): """ - Returns a working directory where to temporary store packet capture files. + Returns a working directory where to store packet capture files. :returns: path to the directory """ - workdir = os.path.join(self._path, "tmp", "captures") + workdir = os.path.join(self._path, "project-files", "captures") if not self._deleted: try: os.makedirs(workdir, exist_ok=True) @@ -275,7 +282,7 @@ class Project: raise aiohttp.web.HTTPNotFound(text="Node ID {} doesn't exist".format(node_id)) - def remove_node(self, node): + async def remove_node(self, node): """ Removes a node from the project. In theory this should be called by the node manager. @@ -284,13 +291,22 @@ class Project: """ if node in self._nodes: - yield from node.delete() + await node.delete() self._nodes.remove(node) - @asyncio.coroutine - def close(self): + async def update(self, variables=None, **kwargs): + original_variables = self.variables + self.variables = variables + + # we need to update docker nodes when variables changes + if original_variables != variables: + for node in self.nodes: + if hasattr(node, 'update'): + await node.update() + + async def close(self): """ - Closes the project, but keep information on disk + Closes the project, but keep project data on disk """ project_nodes_id = set([n.id for n in self.nodes]) @@ -299,15 +315,15 @@ class Project: module_nodes_id = set([n.id for n in module.instance().nodes]) # We close the project only for the modules using it if len(module_nodes_id & project_nodes_id): - yield from module.instance().project_closing(self) + await module.instance().project_closing(self) - yield from self._close_and_clean(False) + await self._close_and_clean(False) for module in self.compute(): module_nodes_id = set([n.id for n in module.instance().nodes]) # We close the project only for the modules using it if len(module_nodes_id & project_nodes_id): - yield from module.instance().project_closed(self) + await module.instance().project_closed(self) try: if os.path.exists(self.tmp_working_directory()): @@ -315,8 +331,7 @@ class Project: except OSError: pass - @asyncio.coroutine - def _close_and_clean(self, cleanup): + async def _close_and_clean(self, cleanup): """ Closes the project, and cleanup the disk if cleanup is True @@ -325,10 +340,10 @@ class Project: tasks = [] for node in self._nodes: - tasks.append(asyncio.async(node.manager.close_node(node.id))) + tasks.append(asyncio.ensure_future(node.manager.close_node(node.id))) if tasks: - done, _ = yield from asyncio.wait(tasks) + done, _ = await asyncio.wait(tasks) for future in done: try: future.result() @@ -338,7 +353,7 @@ class Project: if cleanup and os.path.exists(self.path): self._deleted = True try: - yield from wait_run_in_executor(shutil.rmtree, self.path) + await wait_run_in_executor(shutil.rmtree, self.path) log.info("Project {id} with path '{path}' deleted".format(path=self._path, id=self._id)) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not delete the project directory: {}".format(e)) @@ -357,17 +372,16 @@ class Project: for port in self._used_udp_ports.copy(): port_manager.release_udp_port(port, self) - @asyncio.coroutine - def delete(self): + async def delete(self): """ Removes project from disk """ for module in self.compute(): - yield from module.instance().project_closing(self) - yield from self._close_and_clean(True) + await module.instance().project_closing(self) + await self._close_and_clean(True) for module in self.compute(): - yield from module.instance().project_closed(self) + await module.instance().project_closed(self) def compute(self): """ @@ -387,14 +401,13 @@ class Project: """ NotificationManager.instance().emit(action, event, project_id=self.id) - @asyncio.coroutine - def list_files(self): + async def list_files(self): """ :returns: Array of files in project without temporary files. The files are dictionary {"path": "test.bin", "md5sum": "aaaaa"} """ files = [] - for dirpath, dirnames, filenames in os.walk(self.path): + for dirpath, dirnames, filenames in os.walk(self.path, followlinks=False): for filename in filenames: if not filename.endswith(".ghost"): path = os.path.relpath(dirpath, self.path) @@ -403,7 +416,7 @@ class Project: file_info = {"path": path} try: - file_info["md5sum"] = yield from wait_run_in_executor(self._hash_file, os.path.join(dirpath, filename)) + file_info["md5sum"] = await wait_run_in_executor(self._hash_file, os.path.join(dirpath, filename)) except OSError: continue files.append(file_info) diff --git a/gns3server/compute/project_manager.py b/gns3server/compute/project_manager.py index 28c517d1..5ed61542 100644 --- a/gns3server/compute/project_manager.py +++ b/gns3server/compute/project_manager.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import aiohttp +import asyncio import psutil import platform from .project import Project @@ -89,22 +90,22 @@ class ProjectManager: return # send a warning if used disk space is >= 90% if used_disk_space >= 90: - message = 'Only {}% or less of disk space detected in "{}" on "{}"'.format(used_disk_space, - project.path, - platform.node()) + message = 'Only {:.2f}% or less of free disk space detected in "{}" on "{}"'.format(100 - used_disk_space, + project.path, + platform.node()) log.warning(message) project.emit("log.warning", {"message": message}) - def create_project(self, name=None, project_id=None, path=None): + def create_project(self, name=None, project_id=None, path=None, variables=None): """ Create a project and keep a references to it in project manager. See documentation of Project for arguments """ - if project_id is not None and project_id in self._projects: return self._projects[project_id] - project = Project(name=name, project_id=project_id, path=path) + project = Project(name=name, project_id=project_id, + path=path, variables=variables) self._check_available_disk_space(project) self._projects[project.id] = project return project diff --git a/gns3server/compute/qemu/__init__.py b/gns3server/compute/qemu/__init__.py index fd06605c..922064e8 100644 --- a/gns3server/compute/qemu/__init__.py +++ b/gns3server/compute/qemu/__init__.py @@ -41,13 +41,13 @@ class Qemu(BaseManager): _NODE_TYPE = "qemu" @staticmethod - @asyncio.coroutine - def get_kvm_archs(): + async def get_kvm_archs(): """ Gets a list of architectures for which KVM is available on this server. :returns: List of architectures for which KVM is available on this server. """ + kvm = [] if not os.path.exists("/dev/kvm"): @@ -100,14 +100,14 @@ class Qemu(BaseManager): paths.update(["/usr/bin", "/usr/local/bin", "/opt/local/bin"]) try: exec_dir = os.path.dirname(os.path.abspath(sys.executable)) - paths.add(os.path.abspath(os.path.join(exec_dir, "../Resources/qemu/bin/"))) + paths.add(os.path.abspath(os.path.join(exec_dir, "qemu/bin"))) # If the user run the server by hand from outside except FileNotFoundError: - paths.add("/Applications/GNS3.app/Contents/Resources/qemu/bin") + paths.add("/Applications/GNS3.app/Contents/MacOS/qemu/bin") return paths @staticmethod - def binary_list(archs=None): + async def binary_list(archs=None): """ Gets QEMU binaries list available on the host. @@ -127,11 +127,11 @@ class Qemu(BaseManager): for arch in archs: if f.endswith(arch) or f.endswith("{}.exe".format(arch)) or f.endswith("{}w.exe".format(arch)): qemu_path = os.path.join(path, f) - version = yield from Qemu.get_qemu_version(qemu_path) + version = await Qemu.get_qemu_version(qemu_path) qemus.append({"path": qemu_path, "version": version}) else: qemu_path = os.path.join(path, f) - version = yield from Qemu.get_qemu_version(qemu_path) + version = await Qemu.get_qemu_version(qemu_path) qemus.append({"path": qemu_path, "version": version}) except OSError: @@ -140,7 +140,7 @@ class Qemu(BaseManager): return qemus @staticmethod - def img_binary_list(): + async def img_binary_list(): """ Gets QEMU-img binaries list available on the host. @@ -154,7 +154,7 @@ class Qemu(BaseManager): os.access(os.path.join(path, f), os.X_OK) and \ os.path.isfile(os.path.join(path, f)): qemu_path = os.path.join(path, f) - version = yield from Qemu._get_qemu_img_version(qemu_path) + version = await Qemu._get_qemu_img_version(qemu_path) qemu_imgs.append({"path": qemu_path, "version": version}) except OSError: continue @@ -162,8 +162,7 @@ class Qemu(BaseManager): return qemu_imgs @staticmethod - @asyncio.coroutine - def get_qemu_version(qemu_path): + async def get_qemu_version(qemu_path): """ Gets the Qemu version. @@ -178,27 +177,26 @@ class Qemu(BaseManager): try: with open(version_file, "rb") as file: version = file.read().decode("utf-8").strip() - match = re.search("[0-9\.]+", version) + match = re.search(r"[0-9\.]+", version) if match: return version except (UnicodeDecodeError, OSError) as e: - log.warn("could not read {}: {}".format(version_file, e)) + log.warning("could not read {}: {}".format(version_file, e)) return "" else: try: - output = yield from subprocess_check_output(qemu_path, "-version") + output = await subprocess_check_output(qemu_path, "-version", "-nographic") match = re.search("version\s+([0-9a-z\-\.]+)", output) if match: version = match.group(1) return version else: raise QemuError("Could not determine the Qemu version for {}".format(qemu_path)) - except subprocess.SubprocessError as e: + except (OSError, subprocess.SubprocessError) as e: raise QemuError("Error while looking for the Qemu version: {}".format(e)) @staticmethod - @asyncio.coroutine - def _get_qemu_img_version(qemu_img_path): + async def _get_qemu_img_version(qemu_img_path): """ Gets the Qemu-img version. @@ -206,16 +204,44 @@ class Qemu(BaseManager): """ try: - output = yield from subprocess_check_output(qemu_img_path, "--version") - match = re.search("version\s+([0-9a-z\-\.]+)", output) + output = await subprocess_check_output(qemu_img_path, "--version") + match = re.search(r"version\s+([0-9a-z\-\.]+)", output) if match: version = match.group(1) return version else: raise QemuError("Could not determine the Qemu-img version for {}".format(qemu_img_path)) - except subprocess.SubprocessError as e: + except (OSError, subprocess.SubprocessError) as e: raise QemuError("Error while looking for the Qemu-img version: {}".format(e)) + @staticmethod + def get_haxm_windows_version(): + """ + Gets the HAXM version number (Windows). + + :returns: HAXM version number. Returns None if HAXM is not installed. + """ + + assert(sys.platform.startswith("win")) + import winreg + + hkey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products") + version = None + for index in range(winreg.QueryInfoKey(hkey)[0]): + product_id = winreg.EnumKey(hkey, index) + try: + product_key = winreg.OpenKey(hkey, r"{}\InstallProperties".format(product_id)) + try: + if winreg.QueryValueEx(product_key, "DisplayName")[0].endswith("Hardware Accelerated Execution Manager"): + version = winreg.QueryValueEx(product_key, "DisplayVersion")[0] + break + finally: + winreg.CloseKey(product_key) + except OSError: + continue + winreg.CloseKey(hkey) + return version + @staticmethod def get_legacy_vm_workdir(legacy_vm_id, name): """ @@ -229,10 +255,9 @@ class Qemu(BaseManager): return os.path.join("qemu", "vm-{}".format(legacy_vm_id)) - @asyncio.coroutine - def create_disk(self, qemu_img, path, options): + async def create_disk(self, qemu_img, path, options): """ - Create a qemu disk with qemu-img + Create a Qemu disk with qemu-img :param qemu_img: qemu-img binary path :param path: Image path @@ -250,9 +275,9 @@ class Qemu(BaseManager): try: if os.path.exists(path): - raise QemuError("Could not create disk image {} already exist".format(path)) + raise QemuError("Could not create disk image '{}', file already exists".format(path)) except UnicodeEncodeError: - raise QemuError("Could not create disk image {}, " + raise QemuError("Could not create disk image '{}', " "path contains characters not supported by filesystem".format(path)) command = [qemu_img, "create", "-f", img_format] @@ -261,7 +286,31 @@ class Qemu(BaseManager): command.append(path) command.append("{}M".format(img_size)) - process = yield from asyncio.create_subprocess_exec(*command) - yield from process.wait() + process = await asyncio.create_subprocess_exec(*command) + await process.wait() except (OSError, subprocess.SubprocessError) as e: raise QemuError("Could not create disk image {}:{}".format(path, e)) + + async def resize_disk(self, qemu_img, path, extend): + """ + Resize a Qemu disk with qemu-img + + :param qemu_img: qemu-img binary path + :param path: Image path + :param size: size + """ + + if not os.path.isabs(path): + directory = self.get_images_directory() + os.makedirs(directory, exist_ok=True) + path = os.path.join(directory, os.path.basename(path)) + + try: + if not os.path.exists(path): + raise QemuError("Qemu disk '{}' does not exist".format(path)) + command = [qemu_img, "resize", path, "+{}M".format(extend)] + process = await asyncio.create_subprocess_exec(*command) + await process.wait() + log.info("Qemu disk '{}' extended by {} MB".format(path, extend)) + except (OSError, subprocess.SubprocessError) as e: + raise QemuError("Could not update disk image {}:{}".format(path, e)) diff --git a/gns3server/compute/qemu/qcow2.py b/gns3server/compute/qemu/qcow2.py index c88389e2..efbb54fe 100644 --- a/gns3server/compute/qemu/qcow2.py +++ b/gns3server/compute/qemu/qcow2.py @@ -87,8 +87,7 @@ class Qcow2: return None return path - @asyncio.coroutine - def rebase(self, qemu_img, base_image): + async def rebase(self, qemu_img, base_image): """ Rebase a linked clone in order to use the correct disk @@ -99,8 +98,8 @@ class Qcow2: if not os.path.exists(base_image): raise FileNotFoundError(base_image) command = [qemu_img, "rebase", "-u", "-b", base_image, self._path] - process = yield from asyncio.create_subprocess_exec(*command) - retcode = yield from process.wait() + process = await asyncio.create_subprocess_exec(*command) + retcode = await process.wait() if retcode != 0: raise Qcow2Error("Could not rebase the image") self._reload() diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py index 92a43020..332e5813 100644 --- a/gns3server/compute/qemu/qemu_vm.py +++ b/gns3server/compute/qemu/qemu_vm.py @@ -30,9 +30,11 @@ import asyncio import socket import gns3server import subprocess +import time +import json from gns3server.utils import parse_version -from gns3server.utils.asyncio import subprocess_check_output +from gns3server.utils.asyncio import subprocess_check_output, cancellable_wait_run_in_executor from .qemu_error import QemuError from ..adapters.ethernet_adapter import EthernetAdapter from ..nios.nio_udp import NIOUDP @@ -60,14 +62,14 @@ class QemuVM(BaseNode): :param project: Project instance :param manager: Manager instance :param console: TCP console port + :param console_type: Console type :param qemu_path: path to the QEMU binary :param platform: Platform to emulate - :param console: TCP console port """ def __init__(self, name, node_id, project, manager, linked_clone=True, qemu_path=None, console=None, console_type="telnet", platform=None): - super().__init__(name, node_id, project, manager, console=console, console_type=console_type, wrap_console=True) + super().__init__(name, node_id, project, manager, console=console, console_type=console_type, linked_clone=linked_clone, wrap_console=True) server_config = manager.config.get_section_config("Server") self._host = server_config.get("host", "127.0.0.1") self._monitor_host = server_config.get("monitor_host", "127.0.0.1") @@ -114,7 +116,7 @@ class QemuVM(BaseNode): self._kernel_image = "" self._kernel_command_line = "" self._legacy_networking = False - self._acpi_shutdown = False + self._on_close = "power_off" self._cpu_throttling = 0 # means no CPU throttling self._process_priority = "low" @@ -178,6 +180,7 @@ class QemuVM(BaseNode): qemu_path=qemu_path)) def _check_qemu_path(self, qemu_path): + if qemu_path is None: raise QemuError("QEMU binary path is not set") if not os.path.exists(qemu_path): @@ -194,6 +197,7 @@ class QemuVM(BaseNode): @platform.setter def platform(self, platform): + self._platform = platform if sys.platform.startswith("win"): self.qemu_path = "qemu-system-{}w.exe".format(platform) @@ -207,7 +211,8 @@ class QemuVM(BaseNode): :param variable: Variable name in the class :param value: New disk value """ - value = self.manager.get_abs_image_path(value) + + value = self.manager.get_abs_image_path(value, self.project.path) if not self.linked_clone: for node in self.manager.nodes: if node != self and getattr(node, variable) == value: @@ -235,6 +240,7 @@ class QemuVM(BaseNode): :param hda_disk_image: QEMU hda disk image path """ + self._disk_setter("hda_disk_image", hda_disk_image) @property @@ -406,7 +412,8 @@ class QemuVM(BaseNode): :param cdrom_image: QEMU cdrom image path """ - self._cdrom_image = self.manager.get_abs_image_path(cdrom_image) + + self._cdrom_image = self.manager.get_abs_image_path(cdrom_image, self.project.path) log.info('QEMU VM "{name}" [{id}] has set the QEMU cdrom image path to {cdrom_image}'.format(name=self._name, id=self._id, cdrom_image=self._cdrom_image)) @@ -428,7 +435,8 @@ class QemuVM(BaseNode): :param bios_image: QEMU bios image path """ - self._bios_image = self.manager.get_abs_image_path(bios_image) + + self._bios_image = self.manager.get_abs_image_path(bios_image, self.project.path) log.info('QEMU VM "{name}" [{id}] has set the QEMU bios image path to {bios_image}'.format(name=self._name, id=self._id, bios_image=self._bios_image)) @@ -533,7 +541,7 @@ class QemuVM(BaseNode): if not mac_address: # use the node UUID to generate a random MAC address - self._mac_address = "52:%s:%s:%s:%s:00" % (self.project.id[-4:-2], self.project.id[-2:], self.id[-4:-2], self.id[-2:]) + self._mac_address = "0c:%s:%s:%s:%s:00" % (self.project.id[-4:-2], self.project.id[-2:], self.id[-4:-2], self.id[-2:]) else: self._mac_address = mac_address @@ -566,28 +574,25 @@ class QemuVM(BaseNode): self._legacy_networking = legacy_networking @property - def acpi_shutdown(self): + def on_close(self): """ - Returns either this QEMU VM can be ACPI shutdown. + Returns the action to execute when the VM is stopped/closed - :returns: boolean + :returns: string """ - return self._acpi_shutdown + return self._on_close - @acpi_shutdown.setter - def acpi_shutdown(self, acpi_shutdown): + @on_close.setter + def on_close(self, on_close): """ - Sets either this QEMU VM can be ACPI shutdown. + Sets the action to execute when the VM is stopped/closed - :param acpi_shutdown: boolean + :param on_close: string """ - if acpi_shutdown: - log.info('QEMU VM "{name}" [{id}] has enabled ACPI shutdown'.format(name=self._name, id=self._id)) - else: - log.info('QEMU VM "{name}" [{id}] has disabled ACPI shutdown'.format(name=self._name, id=self._id)) - self._acpi_shutdown = acpi_shutdown + log.info('QEMU VM "{name}" [{id}] set the close action to "{action}"'.format(name=self._name, id=self._id, action=on_close)) + self._on_close = on_close @property def cpu_throttling(self): @@ -707,10 +712,15 @@ class QemuVM(BaseNode): options = options.replace("-no-kvm", "") if "-enable-kvm" in options: options = options.replace("-enable-kvm", "") - elif "-icount" in options and ("-no-kvm" not in options): - # automatically add the -no-kvm option if -icount is detected - # to help with the migration of ASA VMs created before version 1.4 - options = "-no-kvm " + options + else: + if "-no-hax" in options: + options = options.replace("-no-hax", "") + if "-enable-hax" in options: + options = options.replace("-enable-hax", "") + if "-icount" in options and ("-no-kvm" not in options): + # automatically add the -no-kvm option if -icount is detected + # to help with the migration of ASA VMs created before version 1.4 + options = "-no-kvm " + options self._options = options.strip() @property @@ -731,13 +741,13 @@ class QemuVM(BaseNode): :param initrd: QEMU initrd path """ - initrd = self.manager.get_abs_image_path(initrd) + initrd = self.manager.get_abs_image_path(initrd, self.project.path) log.info('QEMU VM "{name}" [{id}] has set the QEMU initrd path to {initrd}'.format(name=self._name, id=self._id, initrd=initrd)) - if "asa" in initrd: - self.project.emit("log.warning", {"message": "Warning ASA 8 is not supported by GNS3 and Cisco, you need to use ASAv. Depending of your hardware and OS this could not work or you could be limited to one instance. If ASA 8 is not booting their is no GNS3 solution, you need to upgrade to ASAv."}) + if "asa" in initrd and self._initrd != initrd: + self.project.emit("log.warning", {"message": "Warning ASA 8 is not supported by GNS3 and Cisco, please use ASAv instead. Depending of your hardware and OS this could not work or you could be limited to one instance. If ASA 8 is not booting their is no GNS3 solution, you must to upgrade to ASAv."}) self._initrd = initrd @property @@ -758,7 +768,7 @@ class QemuVM(BaseNode): :param kernel_image: QEMU kernel image path """ - kernel_image = self.manager.get_abs_image_path(kernel_image) + kernel_image = self.manager.get_abs_image_path(kernel_image, self.project.path) log.info('QEMU VM "{name}" [{id}] has set the QEMU kernel image path to {kernel_image}'.format(name=self._name, id=self._id, kernel_image=kernel_image)) @@ -787,8 +797,7 @@ class QemuVM(BaseNode): kernel_command_line=kernel_command_line)) self._kernel_command_line = kernel_command_line - @asyncio.coroutine - def _set_process_priority(self): + async def _set_process_priority(self): """ Changes the process priority """ @@ -836,8 +845,8 @@ class QemuVM(BaseNode): else: priority = 0 try: - process = yield from asyncio.create_subprocess_exec('renice', '-n', str(priority), '-p', str(self._process.pid)) - yield from process.wait() + process = await asyncio.create_subprocess_exec('renice', '-n', str(priority), '-p', str(self._process.pid)) + await process.wait() except (OSError, subprocess.SubprocessError) as e: log.error('Could not change process priority for QEMU VM "{}": {}'.format(self._name, e)) @@ -873,16 +882,30 @@ class QemuVM(BaseNode): except (OSError, subprocess.SubprocessError) as e: raise QemuError("Could not throttle CPU: {}".format(e)) - @asyncio.coroutine - def start(self): + async def create(self): + """ + Creates QEMU VM and sets proper MD5 hashes + """ + + # In case user upload image manually we don't have md5 sums. + # We need generate hashes at this point, otherwise they will be generated + # at __json__ but not on separate thread. + await cancellable_wait_run_in_executor(md5sum, self._hda_disk_image) + await cancellable_wait_run_in_executor(md5sum, self._hdb_disk_image) + await cancellable_wait_run_in_executor(md5sum, self._hdc_disk_image) + await cancellable_wait_run_in_executor(md5sum, self._hdd_disk_image) + + super(QemuVM, self).create() + + async def start(self): """ Starts this QEMU VM. """ - with (yield from self._execute_lock): + async with self._execute_lock: if self.is_running(): # resume the VM if it is paused - yield from self.resume() + await self.resume() return if self._manager.config.get_section_config("Qemu").getboolean("monitor", True): @@ -894,6 +917,7 @@ class QemuVM(BaseNode): af, socktype, proto, _, sa = res # let the OS find an unused port for the Qemu monitor with socket.socket(af, socktype, proto) as sock: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(sa) self._monitor = sock.getsockname()[1] except OSError as e: @@ -902,7 +926,7 @@ class QemuVM(BaseNode): # check if there is enough RAM to run self.check_available_ram(self.ram) - command = yield from self._build_command() + command = await self._build_command() command_string = " ".join(shlex.quote(s) for s in command) try: log.info("Starting QEMU with: {}".format(command_string)) @@ -911,19 +935,10 @@ class QemuVM(BaseNode): with open(self._stdout_file, "w", encoding="utf-8") as fd: fd.write("Start QEMU with {}\n\nExecution log:\n".format(command_string)) self.command_line = ' '.join(command) - self._process = yield from asyncio.create_subprocess_exec(*command, + self._process = await asyncio.create_subprocess_exec(*command, stdout=fd, stderr=subprocess.STDOUT, cwd=self.working_dir) - - yield from self._start_ubridge() - for adapter_number, adapter in enumerate(self._ethernet_adapters): - nio = adapter.get_nio(0) - if nio: - yield from self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number), - self._local_udp_tunnels[adapter_number][1], - nio) - log.info('QEMU VM "{}" started PID={}'.format(self._name, self._process.pid)) self.status = "started" monitor_process(self._process, self._termination_callback) @@ -932,19 +947,36 @@ class QemuVM(BaseNode): log.error("Could not start QEMU {}: {}\n{}".format(self.qemu_path, e, stdout)) raise QemuError("Could not start QEMU {}: {}\n{}".format(self.qemu_path, e, stdout)) - yield from self._set_process_priority() + await self._set_process_priority() if self._cpu_throttling: self._set_cpu_throttling() - if "-enable-kvm" in command_string: + if "-enable-kvm" in command_string or "-enable-hax" in command_string: self._hw_virtualization = True - try: - yield from self.start_wrap_console() - except OSError as e: - raise QemuError("Could not start QEMU console {}\n".format(e)) - @asyncio.coroutine - def _termination_callback(self, returncode): + await self._start_ubridge() + set_link_commands = [] + for adapter_number, adapter in enumerate(self._ethernet_adapters): + nio = adapter.get_nio(0) + if nio: + await self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number), + self._local_udp_tunnels[adapter_number][1], + nio) + if nio.suspend: + set_link_commands.append("set_link gns3-{} off".format(adapter_number)) + else: + set_link_commands.append("set_link gns3-{} off".format(adapter_number)) + + if "-loadvm" not in command_string: + # only set the link statuses if not restoring a previous VM state + await self._control_vm_commands(set_link_commands) + + try: + await self.start_wrap_console() + except OSError as e: + raise QemuError("Could not start Telnet QEMU console {}\n".format(e)) + + async def _termination_callback(self, returncode): """ Called when the process has stopped. @@ -953,30 +985,41 @@ class QemuVM(BaseNode): if self.started: log.info("QEMU process has stopped, return code: %d", returncode) - yield from self.stop() + await self.stop() # A return code of 1 seem fine on Windows - if returncode != 0 and (returncode != 1 or not sys.platform.startswith("win")): + if returncode != 0 and (not sys.platform.startswith("win") or returncode != 1): self.project.emit("log.error", {"message": "QEMU process has stopped, return code: {}\n{}".format(returncode, self.read_stdout())}) - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops this QEMU VM. """ - yield from self._stop_ubridge() - with (yield from self._execute_lock): + await self._stop_ubridge() + async with self._execute_lock: # stop the QEMU process self._hw_virtualization = False if self.is_running(): log.info('Stopping QEMU VM "{}" PID={}'.format(self._name, self._process.pid)) try: - if self.acpi_shutdown: - yield from self._control_vm("system_powerdown") - yield from gns3server.utils.asyncio.wait_for_process_termination(self._process, timeout=30) + + if self.on_close == "save_vm_state": + await self._control_vm("stop") + await self._control_vm("savevm GNS3_SAVED_STATE") + wait_for_savevm = 120 + while wait_for_savevm: + await asyncio.sleep(1) + status = await self._saved_state_option() + wait_for_savevm -= 1 + if status != []: + break + + if self.on_close == "shutdown_signal": + await self._control_vm("system_powerdown") + await gns3server.utils.asyncio.wait_for_process_termination(self._process, timeout=120) else: self._process.terminate() - yield from gns3server.utils.asyncio.wait_for_process_termination(self._process, timeout=3) + await gns3server.utils.asyncio.wait_for_process_termination(self._process, timeout=3) except ProcessLookupError: pass except asyncio.TimeoutError: @@ -986,13 +1029,44 @@ class QemuVM(BaseNode): except ProcessLookupError: pass if self._process.returncode is None: - log.warn('QEMU VM "{}" PID={} is still running'.format(self._name, self._process.pid)) + log.warning('QEMU VM "{}" PID={} is still running'.format(self._name, self._process.pid)) self._process = None self._stop_cpulimit() - yield from super().stop() + if self.on_close != "save_vm_state": + await self._clear_save_vm_stated() + await super().stop() - @asyncio.coroutine - def _control_vm(self, command, expected=None): + async def _open_qemu_monitor_connection_vm(self, timeout=10): + """ + Opens a connection to the QEMU monitor. + + :param timeout: timeout to connect to the monitor TCP server + :returns: The reader returned is a StreamReader instance; the writer is a StreamWriter instance + """ + + begin = time.time() + connection_success = False + last_exception = None + reader = writer = None + while time.time() - begin < timeout: + await asyncio.sleep(0.01) + try: + log.debug("Connecting to Qemu monitor on {}:{}".format(self._monitor_host, self._monitor)) + reader, writer = await asyncio.open_connection(self._monitor_host, self._monitor) + except (asyncio.TimeoutError, OSError) as e: + last_exception = e + continue + connection_success = True + break + + if not connection_success: + log.warning("Could not connect to QEMU monitor on {}:{}: {}".format(self._monitor_host, self._monitor, + last_exception)) + else: + log.info("Connected to QEMU monitor on {}:{} after {:.4f} seconds".format(self._monitor_host, self._monitor, time.time() - begin)) + return reader, writer + + async def _control_vm(self, command, expected=None): """ Executes a command with QEMU monitor when this VM is running. @@ -1004,45 +1078,78 @@ class QemuVM(BaseNode): result = None if self.is_running() and self._monitor: - log.debug("Execute QEMU monitor command: {}".format(command)) - try: - log.info("Connecting to Qemu monitor on {}:{}".format(self._monitor_host, self._monitor)) - reader, writer = yield from asyncio.open_connection(self._monitor_host, self._monitor) - except OSError as e: - log.warn("Could not connect to QEMU monitor: {}".format(e)) + log.info("Execute QEMU monitor command: {}".format(command)) + reader, writer = await self._open_qemu_monitor_connection_vm() + if reader is None and writer is None: return result + try: - writer.write(command.encode('ascii') + b"\n") + cmd_byte = command.encode('ascii') + writer.write(cmd_byte + b"\n") + if not expected: + while True: + line = await asyncio.wait_for(reader.readline(), timeout=3) # echo of the command + if not line or cmd_byte in line: + break + except asyncio.TimeoutError: + log.warning("Missing echo of command '{}'".format(command)) except OSError as e: - log.warn("Could not write to QEMU monitor: {}".format(e)) + log.warning("Could not write to QEMU monitor: {}".format(e)) writer.close() return result if expected: try: while result is None: - line = yield from reader.readline() + line = await asyncio.wait_for(reader.readline(), timeout=3) if not line: break for expect in expected: if expect in line: result = line.decode("utf-8").strip() break - except EOFError as e: - log.warn("Could not read from QEMU monitor: {}".format(e)) + except asyncio.TimeoutError: + log.warning("Timeout while waiting for result of command '{}'".format(command)) + except (ConnectionError, EOFError) as e: + log.warning("Could not read from QEMU monitor: {}".format(e)) writer.close() return result - @asyncio.coroutine - def close(self): + async def _control_vm_commands(self, commands): + """ + Executes commands with QEMU monitor when this VM is running. + + :param commands: a list of QEMU monitor commands (e.g. info status, stop etc.) + """ + + if self.is_running() and self._monitor: + + reader, writer = await self._open_qemu_monitor_connection_vm() + if reader is None and writer is None: + return + + for command in commands: + log.info("Execute QEMU monitor command: {}".format(command)) + try: + writer.write(command.encode('ascii') + b"\n") + await asyncio.wait_for(reader.readline(), timeout=3) # echo of the command + except asyncio.TimeoutError: + log.warning("Missing echo of command '{}'".format(command)) + except OSError as e: + log.warning("Could not write to QEMU monitor: {}".format(e)) + writer.close() + + async def close(self): """ Closes this QEMU VM. """ - if not (yield from super().close()): + if not (await super().close()): return False - self.acpi_shutdown = False - yield from self.stop() + #FIXME: Don't wait for ACPI shutdown when closing the project, should we? + if self.on_close == "shutdown_signal": + self.on_close = "power_off" + await self.stop() for adapter in self._ethernet_adapters: if adapter is not None: @@ -1055,8 +1162,7 @@ class QemuVM(BaseNode): self.manager.port_manager.release_udp_port(udp_tunnel[1].lport, self._project) self._local_udp_tunnels = {} - @asyncio.coroutine - def _get_vm_status(self): + async def _get_vm_status(self): """ Returns this VM suspend status. @@ -1066,7 +1172,7 @@ class QemuVM(BaseNode): :returns: status (string) """ - result = yield from self._control_vm("info status", [ + result = await self._control_vm("info status", [ b"debug", b"inmigrate", b"internal-error", b"io-error", b"paused", b"postmigrate", b"prelaunch", b"finish-migrate", b"restore-vm", b"running", b"save-vm", b"shutdown", b"suspended", @@ -1083,51 +1189,47 @@ class QemuVM(BaseNode): self.status = "stopped" return status - @asyncio.coroutine - def suspend(self): + async def suspend(self): """ Suspends this QEMU VM. """ if self.is_running(): - vm_status = yield from self._get_vm_status() + vm_status = await self._get_vm_status() if vm_status is None: raise QemuError("Suspending a QEMU VM is not supported") elif vm_status == "running" or vm_status == "prelaunch": - yield from self._control_vm("stop") + await self._control_vm("stop") self.status = "suspended" log.debug("QEMU VM has been suspended") else: log.info("QEMU VM is not running to be suspended, current status is {}".format(vm_status)) - @asyncio.coroutine - def reload(self): + async def reload(self): """ Reloads this QEMU VM. """ - yield from self._control_vm("system_reset") + await self._control_vm("system_reset") log.debug("QEMU VM has been reset") - @asyncio.coroutine - def resume(self): + async def resume(self): """ Resumes this QEMU VM. """ - vm_status = yield from self._get_vm_status() + vm_status = await self._get_vm_status() if vm_status is None: raise QemuError("Resuming a QEMU VM is not supported") elif vm_status == "paused": - yield from self._control_vm("cont") + await self._control_vm("cont") log.debug("QEMU VM has been resumed") else: log.info("QEMU VM is not paused to be resumed, current status is {}".format(vm_status)) - @asyncio.coroutine - def adapter_add_nio_binding(self, adapter_number, nio): + async def adapter_add_nio_binding(self, adapter_number, nio): """ - Adds a port NIO binding. + Adds an adapter NIO binding. :param adapter_number: adapter number :param nio: NIO instance to add to the adapter @@ -1141,9 +1243,10 @@ class QemuVM(BaseNode): if self.is_running(): try: - yield from self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number), + await self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number), self._local_udp_tunnels[adapter_number][1], nio) + await self._control_vm("set_link gns3-{} on".format(adapter_number)) except (IndexError, KeyError): raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name, adapter_number=adapter_number)) @@ -1154,29 +1257,30 @@ class QemuVM(BaseNode): nio=nio, adapter_number=adapter_number)) - @asyncio.coroutine - def adapter_update_nio_binding(self, adapter_number, nio): + async def adapter_update_nio_binding(self, adapter_number, nio): """ - Update a port NIO binding. + Update an adapter NIO binding. :param adapter_number: adapter number - :param nio: NIO instance to add to the adapter + :param nio: NIO instance to update the adapter """ if self.is_running(): try: - yield from self.update_ubridge_udp_connection( - "QEMU-{}-{}".format(self._id, adapter_number), - self._local_udp_tunnels[adapter_number][1], - nio) + await self.update_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number), + self._local_udp_tunnels[adapter_number][1], + nio) + if nio.suspend: + await self._control_vm("set_link gns3-{} off".format(adapter_number)) + else: + await self._control_vm("set_link gns3-{} on".format(adapter_number)) except IndexError: raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name, adapter_number=adapter_number)) - @asyncio.coroutine - def adapter_remove_nio_binding(self, adapter_number): + async def adapter_remove_nio_binding(self, adapter_number): """ - Removes a port NIO binding. + Removes an adapter NIO binding. :param adapter_number: adapter number @@ -1189,8 +1293,10 @@ class QemuVM(BaseNode): raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name, adapter_number=adapter_number)) + await self.stop_capture(adapter_number) if self.is_running(): - yield from self._ubridge_send("bridge delete {name}".format(name="QEMU-{}-{}".format(self._id, adapter_number))) + await self._control_vm("set_link gns3-{} off".format(adapter_number)) + await self._ubridge_send("bridge delete {name}".format(name="QEMU-{}-{}".format(self._id, adapter_number))) nio = adapter.get_nio(0) if isinstance(nio, NIOUDP): @@ -1203,8 +1309,29 @@ class QemuVM(BaseNode): adapter_number=adapter_number)) return nio - @asyncio.coroutine - def start_capture(self, adapter_number, output_file): + def get_nio(self, adapter_number): + """ + Gets an adapter NIO binding. + + :param adapter_number: adapter number + + :returns: NIO instance + """ + + try: + adapter = self._ethernet_adapters[adapter_number] + except IndexError: + raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name, + adapter_number=adapter_number)) + + nio = adapter.get_nio(0) + + if not nio: + raise QemuError("Adapter {} is not connected".format(adapter_number)) + + return nio + + async def start_capture(self, adapter_number, output_file): """ Starts a packet capture. @@ -1212,51 +1339,33 @@ class QemuVM(BaseNode): :param output_file: PCAP destination file for the capture """ - try: - adapter = self._ethernet_adapters[adapter_number] - except IndexError: - raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name, - adapter_number=adapter_number)) - - nio = adapter.get_nio(0) - - if not nio: - raise QemuError("Adapter {} is not connected".format(adapter_number)) - + nio = self.get_nio(adapter_number) if nio.capturing: raise QemuError("Packet capture is already activated on adapter {adapter_number}".format(adapter_number=adapter_number)) - nio.startPacketCapture(output_file) - + nio.start_packet_capture(output_file) if self.ubridge: - yield from self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name="QEMU-{}-{}".format(self._id, adapter_number), + await self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name="QEMU-{}-{}".format(self._id, adapter_number), output_file=output_file)) log.info("QEMU VM '{name}' [{id}]: starting packet capture on adapter {adapter_number}".format(name=self.name, id=self.id, adapter_number=adapter_number)) - def stop_capture(self, adapter_number): + async def stop_capture(self, adapter_number): """ Stops a packet capture. :param adapter_number: adapter number """ - try: - adapter = self._ethernet_adapters[adapter_number] - except IndexError: - raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name, - adapter_number=adapter_number)) - nio = adapter.get_nio(0) - - if not nio: - raise QemuError("Adapter {} is not connected".format(adapter_number)) - - nio.stopPacketCapture() + nio = self.get_nio(adapter_number) + if not nio.capturing: + return + nio.stop_packet_capture() if self.ubridge: - yield from self._ubridge_send('bridge stop_capture {name}'.format(name="QEMU-{}-{}".format(self._id, adapter_number))) + await self._ubridge_send('bridge stop_capture {name}'.format(name="QEMU-{}-{}".format(self._id, adapter_number))) log.info("QEMU VM '{name}' [{id}]: stopping packet capture on adapter {adapter_number}".format(name=self.name, id=self.id, @@ -1324,6 +1433,19 @@ class QemuVM(BaseNode): return " ".join(self._build_command()) + @BaseNode.console_type.setter + def console_type(self, new_console_type): + """ + Sets the console type for this QEMU VM. + + :param new_console_type: console type (string) + """ + + if self.is_running() and self.console_type != new_console_type: + raise QemuError('"{name}" must be stopped to change the console type to {new_console_type}'.format(name=self._name, new_console_type=new_console_type)) + + super(QemuVM, QemuVM).console_type.__set__(self, new_console_type) + def _serial_options(self): if self._console: @@ -1354,6 +1476,21 @@ class QemuVM(BaseNode): else: return [] + def _spice_with_agent_options(self): + + spice_options = self._spice_options() + if self._console: + # agent options (mouse/screen) + agent_options = ["-device", "virtio-serial", + "-chardev", "spicevmc,id=vdagent,debug=0,name=vdagent", + "-device", "virtserialport,chardev=vdagent,name=com.redhat.spice.0"] + spice_options.extend(agent_options) + # folder sharing options + folder_sharing_options = ["-chardev", "spiceport,name=org.spice-space.webdav.0,id=charchannel0", + "-device", "virtserialport,chardev=charchannel0,id=channel0,name=org.spice-space.webdav.0"] + spice_options.extend(folder_sharing_options) + return spice_options + def _monitor_options(self): if self._monitor: @@ -1364,7 +1501,7 @@ class QemuVM(BaseNode): def _get_qemu_img(self): """ Search the qemu-img binary in the same binary of the qemu binary - for avoiding version incompatibily. + for avoiding version incompatibility. :returns: qemu-img path or raise an error """ @@ -1382,21 +1519,19 @@ class QemuVM(BaseNode): return qemu_img_path - @asyncio.coroutine - def _qemu_img_exec(self, command): + async def _qemu_img_exec(self, command): self._qemu_img_stdout_file = os.path.join(self.working_dir, "qemu-img.log") log.info("logging to {}".format(self._qemu_img_stdout_file)) command_string = " ".join(shlex.quote(s) for s in command) log.info("Executing qemu-img with: {}".format(command_string)) with open(self._qemu_img_stdout_file, "w", encoding="utf-8") as fd: - process = yield from asyncio.create_subprocess_exec(*command, stdout=fd, stderr=subprocess.STDOUT, cwd=self.working_dir) - retcode = yield from process.wait() + process = await asyncio.create_subprocess_exec(*command, stdout=fd, stderr=subprocess.STDOUT, cwd=self.working_dir) + retcode = await process.wait() log.info("{} returned with {}".format(self._get_qemu_img(), retcode)) return retcode - @asyncio.coroutine - def _disk_options(self): + async def _disk_options(self): options = [] qemu_img_path = self._get_qemu_img() @@ -1419,16 +1554,16 @@ class QemuVM(BaseNode): else: try: # check for corrupt disk image - retcode = yield from self._qemu_img_exec([qemu_img_path, "check", disk_image]) + retcode = await self._qemu_img_exec([qemu_img_path, "check", disk_image]) if retcode == 3: # image has leaked clusters, but is not corrupted, let's try to fix it log.warning("Qemu image {} has leaked clusters".format(disk_image)) - if (yield from self._qemu_img_exec([qemu_img_path, "check", "-r", "leaks", "{}".format(disk_image)])) == 3: + if (await self._qemu_img_exec([qemu_img_path, "check", "-r", "leaks", "{}".format(disk_image)])) == 3: self.project.emit("log.warning", {"message": "Qemu image '{}' has leaked clusters and could not be fixed".format(disk_image)}) elif retcode == 2: # image is corrupted, let's try to fix it log.warning("Qemu image {} is corrupted".format(disk_image)) - if (yield from self._qemu_img_exec([qemu_img_path, "check", "-r", "all", "{}".format(disk_image)])) == 2: + if (await self._qemu_img_exec([qemu_img_path, "check", "-r", "all", "{}".format(disk_image)])) == 2: self.project.emit("log.warning", {"message": "Qemu image '{}' is corrupted and could not be fixed".format(disk_image)}) except (OSError, subprocess.SubprocessError) as e: stdout = self.read_qemu_img_stdout() @@ -1440,7 +1575,7 @@ class QemuVM(BaseNode): # create the disk try: command = [qemu_img_path, "create", "-o", "backing_file={}".format(disk_image), "-f", "qcow2", disk] - retcode = yield from self._qemu_img_exec(command) + retcode = await self._qemu_img_exec(command) if retcode: stdout = self.read_qemu_img_stdout() raise QemuError("Could not create '{}' disk image: qemu-img returned with {}\n{}".format(disk_name, @@ -1453,7 +1588,7 @@ class QemuVM(BaseNode): # The disk exists we check if the clone works try: qcow2 = Qcow2(disk) - yield from qcow2.rebase(qemu_img_path, disk_image) + await qcow2.rebase(qemu_img_path, disk_image) except (Qcow2Error, OSError) as e: raise QemuError("Could not use qcow2 disk image '{}' for {} {}".format(disk_image, disk_name, e)) @@ -1470,6 +1605,21 @@ class QemuVM(BaseNode): return options + async def resize_disk(self, drive_name, extend): + + if self.is_running(): + raise QemuError("Cannot resize {} while the VM is running".format(drive_name)) + + if self.linked_clone: + disk_image_path = os.path.join(self.working_dir, "{}_disk.qcow2".format(drive_name)) + else: + disk_image_path = getattr(self, "{}_disk_image".format(drive_name)) + + if not os.path.exists(disk_image_path): + raise QemuError("Disk path '{}' does not exist".format(disk_image_path)) + qemu_img_path = self._get_qemu_img() + await self.manager.resize_disk(qemu_img_path, disk_image_path, extend) + def _cdrom_option(self): options = [] @@ -1518,15 +1668,14 @@ class QemuVM(BaseNode): return options - @asyncio.coroutine - def _network_options(self): + async def _network_options(self): network_options = [] network_options.extend(["-net", "none"]) # we do not want any user networking back-end if no adapter is connected. patched_qemu = False if self._legacy_networking: - version = yield from self.manager.get_qemu_version(self.qemu_path) + version = await self.manager.get_qemu_version(self.qemu_path) if version and parse_version(version) < parse_version("1.1.0"): # this is a patched Qemu if version is below 1.1.0 patched_qemu = True @@ -1539,7 +1688,7 @@ class QemuVM(BaseNode): network_options.extend(["-device", "pci-bridge,id=pci-bridge{bridge_id},bus=dmi_pci_bridge{bridge_id},chassis_nr=0x1,addr=0x{bridge_id},shpc=off".format(bridge_id=bridge_id)]) if bridge_id > 1: - qemu_version = yield from self.manager.get_qemu_version(self.qemu_path) + qemu_version = await self.manager.get_qemu_version(self.qemu_path) if qemu_version and parse_version(qemu_version) < parse_version("2.4.0"): raise QemuError("Qemu version 2.4 or later is required to run this VM with a large number of network adapters") @@ -1552,10 +1701,17 @@ class QemuVM(BaseNode): if adapter_number not in self._local_udp_tunnels: self._local_udp_tunnels[adapter_number] = self._create_local_udp_tunnel() nio = self._local_udp_tunnels[adapter_number][0] + + custom_adapter = self._get_custom_adapter_settings(adapter_number) + adapter_type = custom_adapter.get("adapter_type", self._adapter_type) + custom_mac_address = custom_adapter.get("mac_address") + if custom_mac_address: + mac = int_to_macaddress(macaddress_to_int(custom_mac_address)) + if self._legacy_networking: # legacy QEMU networking syntax (-net) if nio: - network_options.extend(["-net", "nic,vlan={},macaddr={},model={}".format(adapter_number, mac, self._adapter_type)]) + network_options.extend(["-net", "nic,vlan={},macaddr={},model={}".format(adapter_number, mac, adapter_type)]) if isinstance(nio, NIOUDP): if patched_qemu: # use patched Qemu syntax @@ -1575,11 +1731,11 @@ class QemuVM(BaseNode): elif isinstance(nio, NIOTAP): network_options.extend(["-net", "tap,name=gns3-{},ifname={}".format(adapter_number, nio.tap_device)]) else: - network_options.extend(["-net", "nic,vlan={},macaddr={},model={}".format(adapter_number, mac, self._adapter_type)]) + network_options.extend(["-net", "nic,vlan={},macaddr={},model={}".format(adapter_number, mac, adapter_type)]) else: # newer QEMU networking syntax - device_string = "{},mac={}".format(self._adapter_type, mac) + device_string = "{},mac={}".format(adapter_type, mac) bridge_id = math.floor(pci_device_id / 32) if bridge_id > 0: addr = pci_device_id % 32 @@ -1600,45 +1756,156 @@ class QemuVM(BaseNode): return network_options - def _graphic(self): + async def _disable_graphics(self): """ - Adds the correct graphic options depending of the OS + Disable graphics depending of the QEMU version """ - if sys.platform.startswith("win"): + if any(opt in self._options for opt in ["-display", "-nographic", "-curses", "-sdl" "-spice", "-vnc"]): return [] - if len(os.environ.get("DISPLAY", "")) > 0: - return [] - if "-nographic" not in self._options: + version = await self.manager.get_qemu_version(self.qemu_path) + if version and parse_version(version) >= parse_version("3.0"): + return ["-display", "none"] + else: return ["-nographic"] - return [] - def _run_with_kvm(self, qemu_path, options): + async def _run_with_hardware_acceleration(self, qemu_path, options): """ - Check if we could run qemu with KVM + Check if we can run Qemu with hardware acceleration :param qemu_path: Path to qemu :param options: String of qemu user options - :returns: Boolean True if we need to enable KVM + :returns: Boolean True if we need to enable hardware acceleration """ - if sys.platform.startswith("linux") and self.manager.config.get_section_config("Qemu").getboolean("enable_kvm", True) \ - and "-no-kvm" not in options: + enable_hardware_accel = self.manager.config.get_section_config("Qemu").getboolean("enable_hardware_acceleration", True) + require_hardware_accel = self.manager.config.get_section_config("Qemu").getboolean("require_hardware_acceleration", True) + if sys.platform.startswith("linux"): + # compatibility: these options were used before version 2.0 and have priority + enable_kvm = self.manager.config.get_section_config("Qemu").getboolean("enable_kvm") + if enable_kvm is not None: + enable_hardware_accel = enable_kvm + require_kvm = self.manager.config.get_section_config("Qemu").getboolean("require_kvm") + if require_kvm is not None: + require_hardware_accel = require_kvm - # Turn OFF kvm for non x86 architectures - if os.path.basename(qemu_path) not in ["qemu-system-x86_64", "qemu-system-i386", "qemu-kvm"]: - return False - - if not os.path.exists("/dev/kvm"): - if self.manager.config.get_section_config("Qemu").getboolean("require_kvm", True): - raise QemuError("KVM acceleration cannot be used (/dev/kvm doesn't exist). You can turn off KVM support in the gns3_server.conf by adding enable_kvm = false to the [Qemu] section.") + if enable_hardware_accel and "-no-kvm" not in options and "-no-hax" not in options: + # Turn OFF hardware acceleration for non x86 architectures + if sys.platform.startswith("win"): + supported_binaries = ["qemu-system-x86_64.exe", "qemu-system-x86_64w.exe", "qemu-system-i386.exe", "qemu-system-i386w.exe"] + else: + supported_binaries = ["qemu-system-x86_64", "qemu-system-i386", "qemu-kvm"] + if os.path.basename(qemu_path) not in supported_binaries: + if require_hardware_accel: + raise QemuError("Hardware acceleration can only be used with the following Qemu executables: {}".format(", ".join(supported_binaries))) else: return False + + if sys.platform.startswith("linux") and not os.path.exists("/dev/kvm"): + if require_hardware_accel: + raise QemuError("KVM acceleration cannot be used (/dev/kvm doesn't exist). It is possible to turn off KVM support in the gns3_server.conf by adding enable_kvm = false to the [Qemu] section.") + else: + return False + elif sys.platform.startswith("win"): + if require_hardware_accel: + # HAXM is only available starting with Qemu version 2.9.0 + version = await self.manager.get_qemu_version(self.qemu_path) + if version and parse_version(version) < parse_version("2.9.0"): + raise QemuError("HAXM acceleration can only be enable for Qemu version 2.9.0 and above (current version: {})".format(version)) + + # check if HAXM is installed + version = self.manager.get_haxm_windows_version() + if version is None: + raise QemuError("HAXM acceleration support is not installed on this host") + log.info("HAXM support version {} detected".format(version)) + + # check if the HAXM service is running + from gns3server.utils.windows_service import check_windows_service_is_running + if not check_windows_service_is_running("intelhaxm"): + raise QemuError("Intel HAXM service is not running on this host") + + else: + return False + elif sys.platform.startswith("darwin"): + process = await asyncio.create_subprocess_shell("kextstat | grep com.intel.kext.intelhaxm") + await process.wait() + if process.returncode != 0: + if require_hardware_accel: + raise QemuError("HAXM acceleration support is not installed on this host (com.intel.kext.intelhaxm extension not loaded)") + else: + return False return True return False - @asyncio.coroutine - def _build_command(self): + async def _clear_save_vm_stated(self, snapshot_name="GNS3_SAVED_STATE"): + + drives = ["a", "b", "c", "d"] + qemu_img_path = self._get_qemu_img() + for disk_index, drive in enumerate(drives): + disk_image = getattr(self, "_hd{}_disk_image".format(drive)) + if not disk_image: + continue + try: + if self.linked_clone: + disk = os.path.join(self.working_dir, "hd{}_disk.qcow2".format(drive)) + else: + disk = disk_image + if not os.path.exists(disk): + continue + output = await subprocess_check_output(qemu_img_path, "info", "--output=json", disk) + if output: + try: + json_data = json.loads(output) + except ValueError as e: + raise QemuError("Invalid JSON data returned by qemu-img while looking for the Qemu VM saved state snapshot: {}".format(e)) + if "snapshots" in json_data: + for snapshot in json_data["snapshots"]: + if snapshot["name"] == snapshot_name: + # delete the snapshot + command = [qemu_img_path, "snapshot", "-d", snapshot_name, disk] + retcode = await self._qemu_img_exec(command) + if retcode: + stdout = self.read_qemu_img_stdout() + log.warning("Could not delete saved VM state from disk {}: {}".format(disk, stdout)) + else: + log.info("Deleted saved VM state from disk {}".format(disk)) + except subprocess.SubprocessError as e: + raise QemuError("Error while looking for the Qemu VM saved state snapshot: {}".format(e)) + + async def _saved_state_option(self, snapshot_name="GNS3_SAVED_STATE"): + + drives = ["a", "b", "c", "d"] + qemu_img_path = self._get_qemu_img() + for disk_index, drive in enumerate(drives): + disk_image = getattr(self, "_hd{}_disk_image".format(drive)) + if not disk_image: + continue + try: + if self.linked_clone: + disk = os.path.join(self.working_dir, "hd{}_disk.qcow2".format(drive)) + else: + disk = disk_image + if not os.path.exists(disk): + continue + output = await subprocess_check_output(qemu_img_path, "info", "--output=json", disk) + if output: + try: + json_data = json.loads(output) + except ValueError as e: + raise QemuError("Invalid JSON data returned by qemu-img while looking for the Qemu VM saved state snapshot: {}".format(e)) + if "snapshots" in json_data: + for snapshot in json_data["snapshots"]: + if snapshot["name"] == snapshot_name: + log.info('QEMU VM "{name}" [{id}] VM saved state detected (snapshot name: {snapshot})'.format(name=self._name, + id=self.id, + snapshot=snapshot_name)) + return ["-loadvm", snapshot_name] + + except subprocess.SubprocessError as e: + raise QemuError("Error while looking for the Qemu VM saved state snapshot: {}".format(e)) + return [] + + async def _build_command(self): """ Command to start the QEMU process. (to be passed to subprocess.Popen()) @@ -1649,21 +1916,26 @@ class QemuVM(BaseNode): additional_options = additional_options.replace("%vm-id%", self._id) additional_options = additional_options.replace("%project-id%", self.project.id) additional_options = additional_options.replace("%project-path%", '"' + self.project.path.replace('"', '\\"') + '"') + if self._console: + additional_options = additional_options.replace("%console-port%", str(self._console)) command = [self.qemu_path] command.extend(["-name", self._name]) command.extend(["-m", "{}M".format(self._ram)]) command.extend(["-smp", "cpus={}".format(self._cpus)]) - if self._run_with_kvm(self.qemu_path, self._options): - command.extend(["-enable-kvm"]) - version = yield from self.manager.get_qemu_version(self.qemu_path) - # Issue on some combo Intel CPU + KVM + Qemu 2.4.0 - # https://github.com/GNS3/gns3-server/issues/685 - if version and parse_version(version) >= parse_version("2.4.0") and self.platform == "x86_64": - command.extend(["-machine", "smm=off"]) + if (await self._run_with_hardware_acceleration(self.qemu_path, self._options)): + if sys.platform.startswith("linux"): + command.extend(["-enable-kvm"]) + version = await self.manager.get_qemu_version(self.qemu_path) + # Issue on some combo Intel CPU + KVM + Qemu 2.4.0 + # https://github.com/GNS3/gns3-server/issues/685 + if version and parse_version(version) >= parse_version("2.4.0") and self.platform == "x86_64": + command.extend(["-machine", "smm=off"]) + elif sys.platform.startswith("win") or sys.platform.startswith("darwin"): + command.extend(["-enable-hax"]) command.extend(["-boot", "order={}".format(self._boot_priority)]) command.extend(self._bios_option()) command.extend(self._cdrom_option()) - command.extend((yield from self._disk_options())) + command.extend((await self._disk_options())) command.extend(self._linux_boot_options()) if "-uuid" not in additional_options: command.extend(["-uuid", self._id]) @@ -1673,11 +1945,18 @@ class QemuVM(BaseNode): command.extend(self._vnc_options()) elif self._console_type == "spice": command.extend(self._spice_options()) - else: + elif self._console_type == "spice+agent": + command.extend(self._spice_with_agent_options()) + elif self._console_type != "none": raise QemuError("Console type {} is unknown".format(self._console_type)) command.extend(self._monitor_options()) - command.extend((yield from self._network_options())) - command.extend(self._graphic()) + command.extend((await self._network_options())) + if self.on_close != "save_vm_state": + await self._clear_save_vm_stated() + else: + command.extend((await self._saved_state_option())) + if self._console_type == "telnet": + command.extend((await self._disable_graphics())) if additional_options: try: command.extend(shlex.split(additional_options)) @@ -1698,22 +1977,20 @@ class QemuVM(BaseNode): answer[field] = getattr(self, field) except AttributeError: pass - answer["hda_disk_image"] = self.manager.get_relative_image_path(self._hda_disk_image) + answer["hda_disk_image"] = self.manager.get_relative_image_path(self._hda_disk_image, self.project.path) answer["hda_disk_image_md5sum"] = md5sum(self._hda_disk_image) - answer["hdb_disk_image"] = self.manager.get_relative_image_path(self._hdb_disk_image) + answer["hdb_disk_image"] = self.manager.get_relative_image_path(self._hdb_disk_image, self.project.path) answer["hdb_disk_image_md5sum"] = md5sum(self._hdb_disk_image) - answer["hdc_disk_image"] = self.manager.get_relative_image_path(self._hdc_disk_image) + answer["hdc_disk_image"] = self.manager.get_relative_image_path(self._hdc_disk_image, self.project.path) answer["hdc_disk_image_md5sum"] = md5sum(self._hdc_disk_image) - answer["hdd_disk_image"] = self.manager.get_relative_image_path(self._hdd_disk_image) + answer["hdd_disk_image"] = self.manager.get_relative_image_path(self._hdd_disk_image, self.project.path) answer["hdd_disk_image_md5sum"] = md5sum(self._hdd_disk_image) - answer["cdrom_image"] = self.manager.get_relative_image_path(self._cdrom_image) + answer["cdrom_image"] = self.manager.get_relative_image_path(self._cdrom_image, self.project.path) answer["cdrom_image_md5sum"] = md5sum(self._cdrom_image) - answer["bios_image"] = self.manager.get_relative_image_path(self._bios_image) + answer["bios_image"] = self.manager.get_relative_image_path(self._bios_image, self.project.path) answer["bios_image_md5sum"] = md5sum(self._bios_image) - answer["initrd"] = self.manager.get_relative_image_path(self._initrd) + answer["initrd"] = self.manager.get_relative_image_path(self._initrd, self.project.path) answer["initrd_md5sum"] = md5sum(self._initrd) - - answer["kernel_image"] = self.manager.get_relative_image_path(self._kernel_image) + answer["kernel_image"] = self.manager.get_relative_image_path(self._kernel_image, self.project.path) answer["kernel_image_md5sum"] = md5sum(self._kernel_image) - return answer diff --git a/tests/handlers/api/controller/test_settings.py b/gns3server/compute/traceng/__init__.py similarity index 55% rename from tests/handlers/api/controller/test_settings.py rename to gns3server/compute/traceng/__init__.py index a87df472..66d7b627 100644 --- a/tests/handlers/api/controller/test_settings.py +++ b/gns3server/compute/traceng/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2015 GNS3 Technologies Inc. +# Copyright (C) 2018 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 @@ -16,18 +16,29 @@ # along with this program. If not, see . """ -This test suite check /version endpoint -It's also used for unittest the HTTP implementation. +TraceNG server module. """ -from gns3server.config import Config +import asyncio + +from ..base_manager import BaseManager +from .traceng_error import TraceNGError +from .traceng_vm import TraceNGVM -def test_settings(http_controller): - query = {"test": True} - response = http_controller.post('/settings', query, example=True) - assert response.status == 201 - response = http_controller.get('/settings', example=True) - assert response.status == 200 - assert response.json["test"] is True - assert response.json["modification_uuid"] is not None +class TraceNG(BaseManager): + + _NODE_CLASS = TraceNGVM + + def __init__(self): + + super().__init__() + + async def create_node(self, *args, **kwargs): + """ + Creates a new TraceNG VM. + + :returns: TraceNGVM instance + """ + + return (await super().create_node(*args, **kwargs)) diff --git a/gns3server/compute/traceng/traceng_error.py b/gns3server/compute/traceng/traceng_error.py new file mode 100644 index 00000000..623f5f59 --- /dev/null +++ b/gns3server/compute/traceng/traceng_error.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2018 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 . + +""" +Custom exceptions for the TraceNG module. +""" + +from ..error import NodeError + + +class TraceNGError(NodeError): + + pass diff --git a/gns3server/compute/traceng/traceng_vm.py b/gns3server/compute/traceng/traceng_vm.py new file mode 100644 index 00000000..f8f8c926 --- /dev/null +++ b/gns3server/compute/traceng/traceng_vm.py @@ -0,0 +1,458 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2018 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 . + +""" +TraceNG VM management in order to run a TraceNG VM. +""" + +import sys +import os +import socket +import subprocess +import asyncio +import shutil +import ipaddress + +from gns3server.utils.asyncio import wait_for_process_termination +from gns3server.utils.asyncio import monitor_process + +from .traceng_error import TraceNGError +from ..adapters.ethernet_adapter import EthernetAdapter +from ..nios.nio_udp import NIOUDP +from ..base_node import BaseNode + + +import logging +log = logging.getLogger(__name__) + + +class TraceNGVM(BaseNode): + module_name = 'traceng' + + """ + TraceNG VM implementation. + + :param name: TraceNG VM name + :param node_id: Node identifier + :param project: Project instance + :param manager: Manager instance + :param console: TCP console port + """ + + def __init__(self, name, node_id, project, manager, console=None, console_type="none"): + + super().__init__(name, node_id, project, manager, console=console, console_type=console_type) + self._process = None + self._started = False + self._ip_address = None + self._default_destination = None + self._destination = None + self._local_udp_tunnel = None + self._ethernet_adapter = EthernetAdapter() # one adapter with 1 Ethernet interface + + @property + def ethernet_adapter(self): + return self._ethernet_adapter + + async def close(self): + """ + Closes this TraceNG VM. + """ + + if not (await super().close()): + return False + + nio = self._ethernet_adapter.get_nio(0) + if isinstance(nio, NIOUDP): + self.manager.port_manager.release_udp_port(nio.lport, self._project) + + if self._local_udp_tunnel: + self.manager.port_manager.release_udp_port(self._local_udp_tunnel[0].lport, self._project) + self.manager.port_manager.release_udp_port(self._local_udp_tunnel[1].lport, self._project) + self._local_udp_tunnel = None + + await self._stop_ubridge() + + if self.is_running(): + self._terminate_process() + + return True + + async def _check_requirements(self): + """ + Check if TraceNG is available. + """ + + path = self._traceng_path() + if not path: + raise TraceNGError("No path to a TraceNG executable has been set") + + # This raise an error if ubridge is not available + self.ubridge_path + + if not os.path.isfile(path): + raise TraceNGError("TraceNG program '{}' is not accessible".format(path)) + + if not os.access(path, os.X_OK): + raise TraceNGError("TraceNG program '{}' is not executable".format(path)) + + def __json__(self): + + return {"name": self.name, + "ip_address": self.ip_address, + "default_destination": self._default_destination, + "node_id": self.id, + "node_directory": self.working_path, + "status": self.status, + "console": self._console, + "console_type": "none", + "project_id": self.project.id, + "command_line": self.command_line} + + def _traceng_path(self): + """ + Returns the TraceNG executable path. + + :returns: path to TraceNG + """ + + search_path = self._manager.config.get_section_config("TraceNG").get("traceng_path", "traceng") + path = shutil.which(search_path) + # shutil.which return None if the path doesn't exists + if not path: + return search_path + return path + + @property + def ip_address(self): + """ + Returns the IP address for this node. + + :returns: IP address + """ + + return self._ip_address + + @ip_address.setter + def ip_address(self, ip_address): + """ + Sets the IP address of this node. + + :param ip_address: IP address + """ + + try: + if ip_address: + ipaddress.IPv4Address(ip_address) + except ipaddress.AddressValueError: + raise TraceNGError("Invalid IP address: {}\n".format(ip_address)) + + self._ip_address = ip_address + log.info("{module}: {name} [{id}] set IP address to {ip_address}".format(module=self.manager.module_name, + name=self.name, + id=self.id, + ip_address=ip_address)) + + @property + def default_destination(self): + """ + Returns the default destination IP/host for this node. + + :returns: destination IP/host + """ + + return self._default_destination + + @default_destination.setter + def default_destination(self, destination): + """ + Sets the destination IP/host for this node. + + :param destination: destination IP/host + """ + + self._default_destination = destination + log.info("{module}: {name} [{id}] set default destination to {destination}".format(module=self.manager.module_name, + name=self.name, + id=self.id, + destination=destination)) + + async def start(self, destination=None): + """ + Starts the TraceNG process. + """ + + if not sys.platform.startswith("win"): + raise TraceNGError("Sorry, TraceNG can only run on Windows") + await self._check_requirements() + if not self.is_running(): + nio = self._ethernet_adapter.get_nio(0) + command = self._build_command(destination) + await self._stop_ubridge() # make use we start with a fresh uBridge instance + try: + log.info("Starting TraceNG: {}".format(command)) + flags = 0 + if hasattr(subprocess, "CREATE_NEW_CONSOLE"): + flags = subprocess.CREATE_NEW_CONSOLE + self.command_line = ' '.join(command) + self._process = await asyncio.create_subprocess_exec(*command, + cwd=self.working_dir, + creationflags=flags) + monitor_process(self._process, self._termination_callback) + + await self._start_ubridge() + if nio: + await self.add_ubridge_udp_connection("TraceNG-{}".format(self._id), self._local_udp_tunnel[1], nio) + + log.info("TraceNG instance {} started PID={}".format(self.name, self._process.pid)) + self._started = True + self.status = "started" + except (OSError, subprocess.SubprocessError) as e: + log.error("Could not start TraceNG {}: {}\n".format(self._traceng_path(), e)) + raise TraceNGError("Could not start TraceNG {}: {}\n".format(self._traceng_path(), e)) + + def _termination_callback(self, returncode): + """ + Called when the process has stopped. + + :param returncode: Process returncode + """ + + if self._started: + log.info("TraceNG process has stopped, return code: %d", returncode) + self._started = False + self.status = "stopped" + self._process = None + if returncode != 0: + self.project.emit("log.error", {"message": "TraceNG process has stopped, return code: {}\n".format(returncode)}) + + async def stop(self): + """ + Stops the TraceNG process. + """ + + await self._stop_ubridge() + if self.is_running(): + self._terminate_process() + if self._process.returncode is None: + try: + await wait_for_process_termination(self._process, timeout=3) + except asyncio.TimeoutError: + if self._process.returncode is None: + try: + self._process.kill() + except OSError as e: + log.error("Cannot stop the TraceNG process: {}".format(e)) + if self._process.returncode is None: + log.warning('TraceNG VM "{}" with PID={} is still running'.format(self._name, self._process.pid)) + + self._process = None + self._started = False + await super().stop() + + async def reload(self): + """ + Reloads the TraceNG process (stop & start). + """ + + await self.stop() + await self.start(self._destination) + + def _terminate_process(self): + """ + Terminate the process if running + """ + + log.info("Stopping TraceNG instance {} PID={}".format(self.name, self._process.pid)) + #if sys.platform.startswith("win32"): + # self._process.send_signal(signal.CTRL_BREAK_EVENT) + #else: + try: + self._process.terminate() + # Sometime the process may already be dead when we garbage collect + except ProcessLookupError: + pass + + def is_running(self): + """ + Checks if the TraceNG process is running + + :returns: True or False + """ + + if self._process and self._process.returncode is None: + return True + return False + + async def port_add_nio_binding(self, port_number, nio): + """ + Adds a port NIO binding. + + :param port_number: port number + :param nio: NIO instance to add to the slot/port + """ + + if not self._ethernet_adapter.port_exists(port_number): + raise TraceNGError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter, + port_number=port_number)) + + if self.is_running(): + await self.add_ubridge_udp_connection("TraceNG-{}".format(self._id), self._local_udp_tunnel[1], nio) + + self._ethernet_adapter.add_nio(port_number, nio) + log.info('TraceNG "{name}" [{id}]: {nio} added to port {port_number}'.format(name=self._name, + id=self.id, + nio=nio, + port_number=port_number)) + + return nio + + async def port_update_nio_binding(self, port_number, nio): + """ + Updates a port NIO binding. + + :param port_number: port number + :param nio: NIO instance to update on the slot/port + """ + + if not self._ethernet_adapter.port_exists(port_number): + raise TraceNGError("Port {port_number} doesn't exist on adapter {adapter}".format(adapter=self._ethernet_adapter, + port_number=port_number)) + if self.is_running(): + await self.update_ubridge_udp_connection("TraceNG-{}".format(self._id), self._local_udp_tunnel[1], nio) + + async def port_remove_nio_binding(self, port_number): + """ + Removes a port NIO binding. + + :param port_number: port number + + :returns: NIO instance + """ + + if not self._ethernet_adapter.port_exists(port_number): + raise TraceNGError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter, + port_number=port_number)) + + await self.stop_capture(port_number) + if self.is_running(): + await self._ubridge_send("bridge delete {name}".format(name="TraceNG-{}".format(self._id))) + + nio = self._ethernet_adapter.get_nio(port_number) + if isinstance(nio, NIOUDP): + self.manager.port_manager.release_udp_port(nio.lport, self._project) + self._ethernet_adapter.remove_nio(port_number) + + log.info('TraceNG "{name}" [{id}]: {nio} removed from port {port_number}'.format(name=self._name, + id=self.id, + nio=nio, + port_number=port_number)) + return nio + + def get_nio(self, port_number): + """ + Gets a port NIO binding. + + :param port_number: port number + + :returns: NIO instance + """ + + if not self._ethernet_adapter.port_exists(port_number): + raise TraceNGError("Port {port_number} doesn't exist on adapter {adapter}".format(adapter=self._ethernet_adapter, + port_number=port_number)) + nio = self._ethernet_adapter.get_nio(port_number) + if not nio: + raise TraceNGError("Port {} is not connected".format(port_number)) + return nio + + async def start_capture(self, port_number, output_file): + """ + Starts a packet capture. + + :param port_number: port number + :param output_file: PCAP destination file for the capture + """ + + nio = self.get_nio(port_number) + if nio.capturing: + raise TraceNGError("Packet capture is already activated on port {port_number}".format(port_number=port_number)) + + nio.start_packet_capture(output_file) + if self.ubridge: + await self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name="TraceNG-{}".format(self._id), + output_file=output_file)) + + log.info("TraceNG '{name}' [{id}]: starting packet capture on port {port_number}".format(name=self.name, + id=self.id, + port_number=port_number)) + + async def stop_capture(self, port_number): + """ + Stops a packet capture. + + :param port_number: port number + """ + + nio = self.get_nio(port_number) + if not nio.capturing: + return + + nio.stop_packet_capture() + if self.ubridge: + await self._ubridge_send('bridge stop_capture {name}'.format(name="TraceNG-{}".format(self._id))) + + log.info("TraceNG '{name}' [{id}]: stopping packet capture on port {port_number}".format(name=self.name, + id=self.id, + port_number=port_number)) + + def _build_command(self, destination): + """ + Command to start the TraceNG process. + (to be passed to subprocess.Popen()) + """ + + if not destination: + # use the default destination if no specific destination provided + destination = self.default_destination + if not destination: + raise TraceNGError("Please provide a host or IP address to trace") + if not self.ip_address: + raise TraceNGError("Please configure an IP address for this TraceNG node") + if self.ip_address == destination: + raise TraceNGError("Destination cannot be the same as the IP address") + + self._destination = destination + command = [self._traceng_path()] + # use the local UDP tunnel to uBridge instead + if not self._local_udp_tunnel: + self._local_udp_tunnel = self._create_local_udp_tunnel() + nio = self._local_udp_tunnel[0] + if nio and isinstance(nio, NIOUDP): + # UDP tunnel + command.extend(["-u"]) # enable UDP tunnel + command.extend(["-c", str(nio.lport)]) # source UDP port + command.extend(["-v", str(nio.rport)]) # destination UDP port + try: + command.extend(["-b", socket.gethostbyname(nio.rhost)]) # destination host, we need to resolve the hostname because TraceNG doesn't support it + except socket.gaierror as e: + raise TraceNGError("Can't resolve hostname {}: {}".format(nio.rhost, e)) + + command.extend(["-s", "ICMP"]) # Use ICMP probe type by default + command.extend(["-f", self._ip_address]) # source IP address to trace from + command.extend([destination]) # host or IP to trace + return command diff --git a/gns3server/compute/virtualbox/__init__.py b/gns3server/compute/virtualbox/__init__.py index a676bd1a..2ae0b729 100644 --- a/gns3server/compute/virtualbox/__init__.py +++ b/gns3server/compute/virtualbox/__init__.py @@ -20,6 +20,7 @@ VirtualBox server module. """ import os +import re import sys import shutil import asyncio @@ -93,13 +94,12 @@ class VirtualBox(BaseManager): self._vboxmanage_path = vboxmanage_path return vboxmanage_path - @asyncio.coroutine - def execute(self, subcommand, args, timeout=60): + async def execute(self, subcommand, args, timeout=60): # We use a lock prevent parallel execution due to strange errors # reported by a user and reproduced by us. # https://github.com/GNS3/gns3-gui/issues/261 - with (yield from self._execute_lock): + async with self._execute_lock: vboxmanage_path = self.vboxmanage_path if not vboxmanage_path: vboxmanage_path = self.find_vboxmanage() @@ -111,12 +111,12 @@ class VirtualBox(BaseManager): command_string = " ".join(command) log.info("Executing VBoxManage with command: {}".format(command_string)) try: - process = yield from asyncio.create_subprocess_exec(*command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + process = await asyncio.create_subprocess_exec(*command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) except (OSError, subprocess.SubprocessError) as e: raise VirtualBoxError("Could not execute VBoxManage: {}".format(e)) try: - stdout_data, stderr_data = yield from asyncio.wait_for(process.communicate(), timeout=timeout) + stdout_data, stderr_data = await asyncio.wait_for(process.communicate(), timeout=timeout) except asyncio.TimeoutError: raise VirtualBoxError("VBoxManage has timed out after {} seconds!".format(timeout)) @@ -126,15 +126,14 @@ class VirtualBox(BaseManager): return stdout_data.decode("utf-8", errors="ignore").splitlines() - @asyncio.coroutine - def _find_inaccessible_hdd_files(self): + async def _find_inaccessible_hdd_files(self): """ Finds inaccessible disk files (to clean up the VirtualBox media manager) """ hdds = [] try: - properties = yield from self.execute("list", ["hdds"]) + properties = await self.execute("list", ["hdds"]) # If VirtualBox is not available we have no inaccessible hdd except VirtualBoxError: return hdds @@ -152,43 +151,44 @@ class VirtualBox(BaseManager): flag_inaccessible = False return reversed(hdds) - @asyncio.coroutine - def project_closed(self, project): + async def project_closed(self, project): """ Called when a project is closed. :param project: Project instance """ - yield from super().project_closed(project) - hdd_files_to_close = yield from self._find_inaccessible_hdd_files() + await super().project_closed(project) + hdd_files_to_close = await self._find_inaccessible_hdd_files() for hdd_file in hdd_files_to_close: log.info("Closing VirtualBox VM disk file {}".format(os.path.basename(hdd_file))) try: - yield from self.execute("closemedium", ["disk", hdd_file]) + await self.execute("closemedium", ["disk", hdd_file]) except VirtualBoxError as e: log.warning("Could not close VirtualBox VM disk file {}: {}".format(os.path.basename(hdd_file), e)) continue - @asyncio.coroutine - def list_vms(self, allow_clone=False): + async def list_vms(self, allow_clone=False): """ Gets VirtualBox VM list. """ vbox_vms = [] - result = yield from self.execute("list", ["vms"]) + result = await self.execute("list", ["vms"]) for line in result: if len(line) == 0 or line[0] != '"' or line[-1:] != "}": continue # Broken output (perhaps a carriage return in VM name) - vmname, _ = line.rsplit(' ', 1) - vmname = vmname.strip('"') + match = re.search(r"\"(.*)\"\ {(.*)}", line) + if not match: + continue + vmname = match.group(1) + uuid = match.group(2) if vmname == "": continue # ignore inaccessible VMs - extra_data = yield from self.execute("getextradata", [vmname, "GNS3/Clone"]) + extra_data = await self.execute("getextradata", [uuid, "GNS3/Clone"]) if allow_clone or len(extra_data) == 0 or not extra_data[0].strip() == "Value: yes": # get the amount of RAM - info_results = yield from self.execute("showvminfo", [vmname, "--machinereadable"]) + info_results = await self.execute("showvminfo", [uuid, "--machinereadable"]) ram = 0 for info in info_results: try: diff --git a/gns3server/compute/virtualbox/virtualbox_vm.py b/gns3server/compute/virtualbox/virtualbox_vm.py index 1e20ebaf..5337852f 100644 --- a/gns3server/compute/virtualbox/virtualbox_vm.py +++ b/gns3server/compute/virtualbox/virtualbox_vm.py @@ -33,7 +33,7 @@ import xml.etree.ElementTree as ET from gns3server.utils import parse_version from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer from gns3server.utils.asyncio.serial import asyncio_open_serial -from gns3server.utils.asyncio import locked_coroutine +from gns3server.utils.asyncio import locking from gns3server.compute.virtualbox.virtualbox_error import VirtualBoxError from gns3server.compute.nios.nio_udp import NIOUDP from gns3server.compute.adapters.ethernet_adapter import EthernetAdapter @@ -53,10 +53,11 @@ class VirtualBoxVM(BaseNode): VirtualBox VM implementation. """ - def __init__(self, name, node_id, project, manager, vmname, linked_clone=False, console=None, adapters=0): + def __init__(self, name, node_id, project, manager, vmname, linked_clone=False, console=None, console_type="telnet", adapters=0): - super().__init__(name, node_id, project, manager, console=console, linked_clone=linked_clone, console_type="telnet") + super().__init__(name, node_id, project, manager, console=console, linked_clone=linked_clone, console_type=console_type) + self._uuid = None # UUID in VirtualBox self._maximum_adapters = 8 self._system_properties = {} self._telnet_server = None @@ -66,7 +67,7 @@ class VirtualBoxVM(BaseNode): self._adapters = adapters self._ethernet_adapters = {} self._headless = False - self._acpi_shutdown = False + self._on_close = "power_off" self._vmname = vmname self._use_any_adapter = False self._ram = 0 @@ -75,13 +76,14 @@ class VirtualBoxVM(BaseNode): def __json__(self): json = {"name": self.name, + "usage": self.usage, "node_id": self.id, "console": self.console, "console_type": self.console_type, "project_id": self.project.id, "vmname": self.vmname, "headless": self.headless, - "acpi_shutdown": self.acpi_shutdown, + "on_close": self.on_close, "adapters": self._adapters, "adapter_type": self.adapter_type, "ram": self.ram, @@ -98,10 +100,9 @@ class VirtualBoxVM(BaseNode): def ethernet_adapters(self): return self._ethernet_adapters - @asyncio.coroutine - def _get_system_properties(self): + async def _get_system_properties(self): - properties = yield from self.manager.execute("list", ["systemproperties"]) + properties = await self.manager.execute("list", ["systemproperties"]) for prop in properties: try: name, value = prop.split(':', 1) @@ -109,15 +110,14 @@ class VirtualBoxVM(BaseNode): continue self._system_properties[name.strip()] = value.strip() - @asyncio.coroutine - def _get_vm_state(self): + async def _get_vm_state(self): """ Returns the VM state (e.g. running, paused etc.) :returns: state (string) """ - results = yield from self.manager.execute("showvminfo", [self._vmname, "--machinereadable"]) + results = await self.manager.execute("showvminfo", [self._uuid, "--machinereadable"]) for info in results: if '=' in info: name, value = info.split('=', 1) @@ -125,8 +125,7 @@ class VirtualBoxVM(BaseNode): return value.strip('"') raise VirtualBoxError("Could not get VM state for {}".format(self._vmname)) - @asyncio.coroutine - def _control_vm(self, params): + async def _control_vm(self, params): """ Change setting in this VM when running. @@ -136,11 +135,10 @@ class VirtualBoxVM(BaseNode): """ args = shlex.split(params) - result = yield from self.manager.execute("controlvm", [self._vmname] + args) + result = await self.manager.execute("controlvm", [self._uuid] + args) return result - @asyncio.coroutine - def _modify_vm(self, params): + async def _modify_vm(self, params): """ Change setting in this VM when not running. @@ -148,10 +146,9 @@ class VirtualBoxVM(BaseNode): """ args = shlex.split(params) - yield from self.manager.execute("modifyvm", [self._vmname] + args) + await self.manager.execute("modifyvm", [self._uuid] + args) - @asyncio.coroutine - def _check_duplicate_linked_clone(self): + async def _check_duplicate_linked_clone(self): """ Without linked clone two VM using the same image can't run at the same time. @@ -175,34 +172,42 @@ class VirtualBoxVM(BaseNode): if not found: return trial += 1 - yield from asyncio.sleep(1) + await asyncio.sleep(1) + + async def create(self): - @asyncio.coroutine - def create(self): if not self.linked_clone: - yield from self._check_duplicate_linked_clone() + await self._check_duplicate_linked_clone() - yield from self._get_system_properties() + await self._get_system_properties() if "API version" not in self._system_properties: raise VirtualBoxError("Can't access to VirtualBox API version:\n{}".format(self._system_properties)) if parse_version(self._system_properties["API version"]) < parse_version("4_3"): raise VirtualBoxError("The VirtualBox API version is lower than 4.3") log.info("VirtualBox VM '{name}' [{id}] created".format(name=self.name, id=self.id)) + vm_info = await self._get_vm_info() + if "memory" in vm_info: + self._ram = int(vm_info["memory"]) + if "UUID" in vm_info: + self._uuid = vm_info["UUID"] + if not self._uuid: + raise VirtualBoxError("Could not find any UUID for VM '{}'".format(self._vmname)) + if self.linked_clone: if self.id and os.path.isdir(os.path.join(self.working_dir, self._vmname)): self._patch_vm_uuid() - yield from self.manager.execute("registervm", [self._linked_vbox_file()]) - yield from self._reattach_linked_hdds() + await self.manager.execute("registervm", [self._linked_vbox_file()]) + await self._reattach_linked_hdds() + vm_info = await self._get_vm_info() + self._uuid = vm_info.get("UUID") + if not self._uuid: + raise VirtualBoxError("Could not find any UUID for VM '{}'".format(self._vmname)) else: - yield from self._create_linked_clone() + await self._create_linked_clone() if self._adapters: - yield from self.set_adapters(self._adapters) - - vm_info = yield from self._get_vm_info() - if "memory" in vm_info: - self._ram = int(vm_info["memory"]) + await self.set_adapters(self._adapters) def _linked_vbox_file(self): return os.path.join(self.working_dir, self._vmname, self._vmname + ".vbox") @@ -217,6 +222,8 @@ class VirtualBoxVM(BaseNode): except ET.ParseError: raise VirtualBoxError("Cannot modify VirtualBox linked nodes file. " "File {} is corrupted.".format(self._linked_vbox_file())) + except OSError as e: + raise VirtualBoxError("Cannot modify VirtualBox linked nodes file '{}': {}".format(self._linked_vbox_file(), e)) machine = tree.getroot().find("{http://www.virtualbox.org/}Machine") if machine is not None and machine.get("uuid") != "{" + self.id + "}": @@ -224,7 +231,7 @@ class VirtualBoxVM(BaseNode): for image in tree.getroot().findall("{http://www.virtualbox.org/}Image"): currentSnapshot = machine.get("currentSnapshot") if currentSnapshot: - newSnapshot = re.sub("\{.*\}", "{" + str(uuid.uuid4()) + "}", currentSnapshot) + newSnapshot = re.sub(r"\{.*\}", "{" + str(uuid.uuid4()) + "}", currentSnapshot) shutil.move(os.path.join(self.working_dir, self._vmname, "Snapshots", currentSnapshot) + ".vdi", os.path.join(self.working_dir, self._vmname, "Snapshots", newSnapshot) + ".vdi") image.set("uuid", newSnapshot) @@ -232,21 +239,20 @@ class VirtualBoxVM(BaseNode): machine.set("uuid", "{" + self.id + "}") tree.write(self._linked_vbox_file()) - @asyncio.coroutine - def check_hw_virtualization(self): + async def check_hw_virtualization(self): """ Returns either hardware virtualization is activated or not. :returns: boolean """ - vm_info = yield from self._get_vm_info() + vm_info = await self._get_vm_info() if "hwvirtex" in vm_info and vm_info["hwvirtex"] == "on": return True return False - @asyncio.coroutine - def start(self): + @locking + async def start(self): """ Starts this VirtualBox VM. """ @@ -255,136 +261,137 @@ class VirtualBoxVM(BaseNode): return # resume the VM if it is paused - vm_state = yield from self._get_vm_state() + vm_state = await self._get_vm_state() if vm_state == "paused": - yield from self.resume() + await self.resume() return # VM must be powered off to start it if vm_state != "poweroff": raise VirtualBoxError("VirtualBox VM not powered off") - yield from self._set_network_options() - yield from self._set_serial_console() + await self._set_network_options() + await self._set_serial_console() # check if there is enough RAM to run self.check_available_ram(self.ram) - args = [self._vmname] + args = [self._uuid] if self._headless: args.extend(["--type", "headless"]) - result = yield from self.manager.execute("startvm", args) + result = await self.manager.execute("startvm", args) self.status = "started" log.info("VirtualBox VM '{name}' [{id}] started".format(name=self.name, id=self.id)) log.debug("Start result: {}".format(result)) # add a guest property to let the VM know about the GNS3 name - yield from self.manager.execute("guestproperty", ["set", self._vmname, "NameInGNS3", self.name]) + await self.manager.execute("guestproperty", ["set", self._uuid, "NameInGNS3", self.name]) # add a guest property to let the VM know about the GNS3 project directory - yield from self.manager.execute("guestproperty", ["set", self._vmname, "ProjectDirInGNS3", self.working_dir]) + await self.manager.execute("guestproperty", ["set", self._uuid, "ProjectDirInGNS3", self.working_dir]) - yield from self._start_ubridge() + await self._start_ubridge() for adapter_number in range(0, self._adapters): nio = self._ethernet_adapters[adapter_number].get_nio(0) if nio: - yield from self.add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number), + await self.add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number), self._local_udp_tunnels[adapter_number][1], nio) - yield from self._start_console() + await self._start_console() - if (yield from self.check_hw_virtualization()): + if (await self.check_hw_virtualization()): self._hw_virtualization = True - @locked_coroutine - def stop(self): + @locking + async def stop(self): """ Stops this VirtualBox VM. """ self._hw_virtualization = False - yield from self._stop_ubridge() - yield from self._stop_remote_console() - vm_state = yield from self._get_vm_state() + await self._stop_ubridge() + await self._stop_remote_console() + vm_state = await self._get_vm_state() if vm_state == "running" or vm_state == "paused" or vm_state == "stuck": - if self.acpi_shutdown: + + if self.on_close == "save_vm_state": + result = await self._control_vm("savestate") + self.status = "stopped" + log.debug("Stop result: {}".format(result)) + elif self.on_close == "shutdown_signal": # use ACPI to shutdown the VM - result = yield from self._control_vm("acpipowerbutton") + result = await self._control_vm("acpipowerbutton") trial = 0 while True: - vm_state = yield from self._get_vm_state() + vm_state = await self._get_vm_state() if vm_state == "poweroff": break - yield from asyncio.sleep(1) + await asyncio.sleep(1) trial += 1 if trial >= 120: - yield from self._control_vm("poweroff") + await self._control_vm("poweroff") break self.status = "stopped" log.debug("ACPI shutdown result: {}".format(result)) else: # power off the VM - result = yield from self._control_vm("poweroff") + result = await self._control_vm("poweroff") self.status = "stopped" log.debug("Stop result: {}".format(result)) log.info("VirtualBox VM '{name}' [{id}] stopped".format(name=self.name, id=self.id)) - yield from asyncio.sleep(0.5) # give some time for VirtualBox to unlock the VM + await asyncio.sleep(0.5) # give some time for VirtualBox to unlock the VM try: # deactivate the first serial port - yield from self._modify_vm("--uart1 off") + await self._modify_vm("--uart1 off") except VirtualBoxError as e: - log.warn("Could not deactivate the first serial port: {}".format(e)) + log.warning("Could not deactivate the first serial port: {}".format(e)) for adapter_number in range(0, self._adapters): nio = self._ethernet_adapters[adapter_number].get_nio(0) if nio: - yield from self._modify_vm("--nictrace{} off".format(adapter_number + 1)) - yield from self._modify_vm("--cableconnected{} off".format(adapter_number + 1)) - yield from self._modify_vm("--nic{} null".format(adapter_number + 1)) - yield from super().stop() + await self._modify_vm("--nictrace{} off".format(adapter_number + 1)) + await self._modify_vm("--cableconnected{} off".format(adapter_number + 1)) + await self._modify_vm("--nic{} null".format(adapter_number + 1)) + await super().stop() - @asyncio.coroutine - def suspend(self): + async def suspend(self): """ Suspends this VirtualBox VM. """ - vm_state = yield from self._get_vm_state() + vm_state = await self._get_vm_state() if vm_state == "running": - yield from self._control_vm("pause") + await self._control_vm("pause") self.status = "suspended" log.info("VirtualBox VM '{name}' [{id}] suspended".format(name=self.name, id=self.id)) else: - log.warn("VirtualBox VM '{name}' [{id}] cannot be suspended, current state: {state}".format(name=self.name, + log.warning("VirtualBox VM '{name}' [{id}] cannot be suspended, current state: {state}".format(name=self.name, id=self.id, state=vm_state)) - @asyncio.coroutine - def resume(self): + async def resume(self): """ Resumes this VirtualBox VM. """ - yield from self._control_vm("resume") + await self._control_vm("resume") self.status = "started" log.info("VirtualBox VM '{name}' [{id}] resumed".format(name=self.name, id=self.id)) - @asyncio.coroutine - def reload(self): + async def reload(self): """ Reloads this VirtualBox VM. """ - result = yield from self._control_vm("reset") + result = await self._control_vm("reset") log.info("VirtualBox VM '{name}' [{id}] reloaded".format(name=self.name, id=self.id)) log.debug("Reload result: {}".format(result)) - @asyncio.coroutine - def _get_all_hdd_files(self): + async def _get_all_hdd_files(self): hdds = [] - properties = yield from self.manager.execute("list", ["hdds"]) + properties = await self.manager.execute("list", ["hdds"]) for prop in properties: try: name, value = prop.split(':', 1) @@ -394,8 +401,7 @@ class VirtualBoxVM(BaseNode): hdds.append(value.strip()) return hdds - @asyncio.coroutine - def _reattach_linked_hdds(self): + async def _reattach_linked_hdds(self): """ Reattach linked cloned hard disks. """ @@ -419,13 +425,13 @@ class VirtualBoxVM(BaseNode): medium=hdd_file)) try: - yield from self._storage_attach('--storagectl "{}" --port {} --device {} --type hdd --medium "{}"'.format(hdd_info["controller"], + await self._storage_attach('--storagectl "{}" --port {} --device {} --type hdd --medium "{}"'.format(hdd_info["controller"], hdd_info["port"], hdd_info["device"], hdd_file)) except VirtualBoxError as e: - log.warn("VirtualBox VM '{name}' [{id}] error reattaching HDD {controller} {port} {device} {medium}: {error}".format(name=self.name, + log.warning("VirtualBox VM '{name}' [{id}] error reattaching HDD {controller} {port} {device} {medium}: {error}".format(name=self.name, id=self.id, controller=hdd_info["controller"], port=hdd_info["port"], @@ -434,8 +440,7 @@ class VirtualBoxVM(BaseNode): error=e)) continue - @asyncio.coroutine - def save_linked_hdds_info(self): + async def save_linked_hdds_info(self): """ Save linked cloned hard disks information. @@ -445,10 +450,10 @@ class VirtualBoxVM(BaseNode): hdd_table = [] if self.linked_clone: if os.path.exists(self.working_dir): - hdd_files = yield from self._get_all_hdd_files() - vm_info = yield from self._get_vm_info() + hdd_files = await self._get_all_hdd_files() + vm_info = await self._get_vm_info() for entry, value in vm_info.items(): - match = re.search("^([\s\w]+)\-(\d)\-(\d)$", entry) # match Controller-PortNumber-DeviceNumber entry + match = re.search(r"^([\s\w]+)\-(\d)\-(\d)$", entry) # match Controller-PortNumber-DeviceNumber entry if match: controller = match.group(1) port = match.group(2) @@ -480,8 +485,7 @@ class VirtualBoxVM(BaseNode): return hdd_table - @asyncio.coroutine - def close(self): + async def close(self): """ Closes this VirtualBox VM. """ @@ -490,7 +494,7 @@ class VirtualBoxVM(BaseNode): # VM is already closed return - if not (yield from super().close()): + if not (await super().close()): return False log.debug("VirtualBox VM '{name}' [{id}] is closing".format(name=self.name, id=self.id)) @@ -509,11 +513,11 @@ class VirtualBoxVM(BaseNode): self.manager.port_manager.release_udp_port(udp_tunnel[1].lport, self._project) self._local_udp_tunnels = {} - self.acpi_shutdown = False - yield from self.stop() + self.on_close = "power_off" + await self.stop() if self.linked_clone: - hdd_table = yield from self.save_linked_hdds_info() + hdd_table = await self.save_linked_hdds_info() for hdd in hdd_table.copy(): log.info("VirtualBox VM '{name}' [{id}] detaching HDD {controller} {port} {device}".format(name=self.name, id=self.id, @@ -521,11 +525,11 @@ class VirtualBoxVM(BaseNode): port=hdd["port"], device=hdd["device"])) try: - yield from self._storage_attach('--storagectl "{}" --port {} --device {} --type hdd --medium none'.format(hdd["controller"], + await self._storage_attach('--storagectl "{}" --port {} --device {} --type hdd --medium none'.format(hdd["controller"], hdd["port"], hdd["device"])) except VirtualBoxError as e: - log.warn("VirtualBox VM '{name}' [{id}] error detaching HDD {controller} {port} {device}: {error}".format(name=self.name, + log.warning("VirtualBox VM '{name}' [{id}] error detaching HDD {controller} {port} {device}: {error}".format(name=self.name, id=self.id, controller=hdd["controller"], port=hdd["port"], @@ -534,7 +538,7 @@ class VirtualBoxVM(BaseNode): continue log.info("VirtualBox VM '{name}' [{id}] unregistering".format(name=self.name, id=self.id)) - yield from self.manager.execute("unregistervm", [self._name]) + await self.manager.execute("unregistervm", [self._name]) log.info("VirtualBox VM '{name}' [{id}] closed".format(name=self.name, id=self.id)) self._closed = True @@ -564,28 +568,25 @@ class VirtualBoxVM(BaseNode): self._headless = headless @property - def acpi_shutdown(self): + def on_close(self): """ - Returns either the VM will use ACPI shutdown + Returns the action to execute when the VM is stopped/closed - :returns: boolean + :returns: string """ - return self._acpi_shutdown + return self._on_close - @acpi_shutdown.setter - def acpi_shutdown(self, acpi_shutdown): + @on_close.setter + def on_close(self, on_close): """ - Sets either the VM will use ACPI shutdown + Sets the action to execute when the VM is stopped/closed - :param acpi_shutdown: boolean + :param on_close: string """ - if acpi_shutdown: - log.info("VirtualBox VM '{name}' [{id}] has enabled the ACPI shutdown mode".format(name=self.name, id=self.id)) - else: - log.info("VirtualBox VM '{name}' [{id}] has disabled the ACPI shutdown mode".format(name=self.name, id=self.id)) - self._acpi_shutdown = acpi_shutdown + log.info('VirtualBox VM "{name}" [{id}] set the close action to "{action}"'.format(name=self._name, id=self._id, action=on_close)) + self._on_close = on_close @property def ram(self): @@ -597,8 +598,7 @@ class VirtualBoxVM(BaseNode): return self._ram - @asyncio.coroutine - def set_ram(self, ram): + async def set_ram(self, ram): """ Set the amount of RAM allocated to this VirtualBox VM. @@ -608,7 +608,7 @@ class VirtualBoxVM(BaseNode): if ram == 0: return - yield from self._modify_vm('--memory {}'.format(ram)) + await self._modify_vm('--memory {}'.format(ram)) log.info("VirtualBox VM '{name}' [{id}] has set amount of RAM to {ram}".format(name=self.name, id=self.id, ram=ram)) self._ram = ram @@ -623,8 +623,7 @@ class VirtualBoxVM(BaseNode): return self._vmname - @asyncio.coroutine - def set_vmname(self, vmname): + async def set_vmname(self, vmname): """ Renames the VirtualBox VM. @@ -638,10 +637,10 @@ class VirtualBoxVM(BaseNode): if self.status == "started": raise VirtualBoxError("You can't change the name of running VM {}".format(self._name)) # We can't rename a VM to name that already exists - vms = yield from self.manager.list_vms(allow_clone=True) + vms = await self.manager.list_vms(allow_clone=True) if vmname in [vm["vmname"] for vm in vms]: raise VirtualBoxError("You can't change the name to {} it's already use in VirtualBox".format(vmname)) - yield from self._modify_vm('--name "{}"'.format(vmname)) + await self._modify_vm('--name "{}"'.format(vmname)) log.info("VirtualBox VM '{name}' [{id}] has set the VM name to '{vmname}'".format(name=self.name, id=self.id, vmname=vmname)) self._vmname = vmname @@ -656,8 +655,7 @@ class VirtualBoxVM(BaseNode): return self._adapters - @asyncio.coroutine - def set_adapters(self, adapters): + async def set_adapters(self, adapters): """ Sets the number of Ethernet adapters for this VirtualBox VM instance. @@ -665,7 +663,7 @@ class VirtualBoxVM(BaseNode): """ # check for the maximum adapters supported by the VM - vm_info = yield from self._get_vm_info() + vm_info = await self._get_vm_info() chipset = "piix3" # default chipset for VirtualBox VMs self._maximum_adapters = 8 # default maximum network adapter count for PIIX3 chipset if "chipset" in vm_info: @@ -743,8 +741,7 @@ class VirtualBoxVM(BaseNode): id=self.id, adapter_type=adapter_type)) - @asyncio.coroutine - def _get_vm_info(self): + async def _get_vm_info(self): """ Returns this VM info. @@ -752,7 +749,7 @@ class VirtualBoxVM(BaseNode): """ vm_info = {} - results = yield from self.manager.execute("showvminfo", [self._vmname, "--machinereadable"]) + results = await self.manager.execute("showvminfo", ["--machinereadable", "--", self._vmname]) # "--" is to protect against vm names containing the "-" character for info in results: try: name, value = info.split('=', 1) @@ -778,22 +775,20 @@ class VirtualBoxVM(BaseNode): raise VirtualBoxError("Could not create the VirtualBox pipe directory: {}".format(e)) return pipe_name - @asyncio.coroutine - def _set_serial_console(self): + async def _set_serial_console(self): """ Configures the first serial port to allow a serial console connection. """ # activate the first serial port - yield from self._modify_vm("--uart1 0x3F8 4") + await self._modify_vm("--uart1 0x3F8 4") # set server mode with a pipe on the first serial port pipe_name = self._get_pipe_name() - args = [self._vmname, "--uartmode1", "server", pipe_name] - yield from self.manager.execute("modifyvm", args) + args = [self._uuid, "--uartmode1", "server", pipe_name] + await self.manager.execute("modifyvm", args) - @asyncio.coroutine - def _storage_attach(self, params): + async def _storage_attach(self, params): """ Change storage medium in this VM. @@ -801,10 +796,9 @@ class VirtualBoxVM(BaseNode): """ args = shlex.split(params) - yield from self.manager.execute("storageattach", [self._vmname] + args) + await self.manager.execute("storageattach", [self._uuid] + args) - @asyncio.coroutine - def _get_nic_attachements(self, maximum_adapters): + async def _get_nic_attachements(self, maximum_adapters): """ Returns NIC attachements. @@ -813,7 +807,7 @@ class VirtualBoxVM(BaseNode): """ nics = [] - vm_info = yield from self._get_vm_info() + vm_info = await self._get_vm_info() for adapter_number in range(0, maximum_adapters): entry = "nic{}".format(adapter_number + 1) if entry in vm_info: @@ -823,22 +817,21 @@ class VirtualBoxVM(BaseNode): nics.append(None) return nics - @asyncio.coroutine - def _set_network_options(self): + async def _set_network_options(self): """ Configures network options. """ - nic_attachments = yield from self._get_nic_attachements(self._maximum_adapters) + nic_attachments = await self._get_nic_attachements(self._maximum_adapters) for adapter_number in range(0, self._adapters): attachment = nic_attachments[adapter_number] if attachment == "null": # disconnect the cable if no backend is attached. - yield from self._modify_vm("--cableconnected{} off".format(adapter_number + 1)) + await self._modify_vm("--cableconnected{} off".format(adapter_number + 1)) if attachment == "none": # set the backend to null to avoid a difference in the number of interfaces in the Guest. - yield from self._modify_vm("--nic{} null".format(adapter_number + 1)) - yield from self._modify_vm("--cableconnected{} off".format(adapter_number + 1)) + await self._modify_vm("--nic{} null".format(adapter_number + 1)) + await self._modify_vm("--cableconnected{} off".format(adapter_number + 1)) # use a local UDP tunnel to connect to uBridge instead if adapter_number not in self._local_udp_tunnels: @@ -849,60 +842,66 @@ class VirtualBoxVM(BaseNode): if not self._use_any_adapter and attachment in ("nat", "bridged", "intnet", "hostonly", "natnetwork"): continue - yield from self._modify_vm("--nictrace{} off".format(adapter_number + 1)) + await self._modify_vm("--nictrace{} off".format(adapter_number + 1)) + + custom_adapter = self._get_custom_adapter_settings(adapter_number) + adapter_type = custom_adapter.get("adapter_type", self._adapter_type) + vbox_adapter_type = "82540EM" - if self._adapter_type == "PCnet-PCI II (Am79C970A)": + if adapter_type == "PCnet-PCI II (Am79C970A)": vbox_adapter_type = "Am79C970A" - if self._adapter_type == "PCNet-FAST III (Am79C973)": + if adapter_type == "PCNet-FAST III (Am79C973)": vbox_adapter_type = "Am79C973" - if self._adapter_type == "Intel PRO/1000 MT Desktop (82540EM)": + if adapter_type == "Intel PRO/1000 MT Desktop (82540EM)": vbox_adapter_type = "82540EM" - if self._adapter_type == "Intel PRO/1000 T Server (82543GC)": + if adapter_type == "Intel PRO/1000 T Server (82543GC)": vbox_adapter_type = "82543GC" - if self._adapter_type == "Intel PRO/1000 MT Server (82545EM)": + if adapter_type == "Intel PRO/1000 MT Server (82545EM)": vbox_adapter_type = "82545EM" - if self._adapter_type == "Paravirtualized Network (virtio-net)": + if adapter_type == "Paravirtualized Network (virtio-net)": vbox_adapter_type = "virtio" - args = [self._vmname, "--nictype{}".format(adapter_number + 1), vbox_adapter_type] - yield from self.manager.execute("modifyvm", args) + args = [self._uuid, "--nictype{}".format(adapter_number + 1), vbox_adapter_type] + await self.manager.execute("modifyvm", args) if isinstance(nio, NIOUDP): log.debug("setting UDP params on adapter {}".format(adapter_number)) - yield from self._modify_vm("--nic{} generic".format(adapter_number + 1)) - yield from self._modify_vm("--nicgenericdrv{} UDPTunnel".format(adapter_number + 1)) - yield from self._modify_vm("--nicproperty{} sport={}".format(adapter_number + 1, nio.lport)) - yield from self._modify_vm("--nicproperty{} dest={}".format(adapter_number + 1, nio.rhost)) - yield from self._modify_vm("--nicproperty{} dport={}".format(adapter_number + 1, nio.rport)) - yield from self._modify_vm("--cableconnected{} on".format(adapter_number + 1)) + await self._modify_vm("--nic{} generic".format(adapter_number + 1)) + await self._modify_vm("--nicgenericdrv{} UDPTunnel".format(adapter_number + 1)) + await self._modify_vm("--nicproperty{} sport={}".format(adapter_number + 1, nio.lport)) + await self._modify_vm("--nicproperty{} dest={}".format(adapter_number + 1, nio.rhost)) + await self._modify_vm("--nicproperty{} dport={}".format(adapter_number + 1, nio.rport)) + if nio.suspend: + await self._modify_vm("--cableconnected{} off".format(adapter_number + 1)) + else: + await self._modify_vm("--cableconnected{} on".format(adapter_number + 1)) if nio.capturing: - yield from self._modify_vm("--nictrace{} on".format(adapter_number + 1)) - yield from self._modify_vm('--nictracefile{} "{}"'.format(adapter_number + 1, nio.pcap_output_file)) + await self._modify_vm("--nictrace{} on".format(adapter_number + 1)) + await self._modify_vm('--nictracefile{} "{}"'.format(adapter_number + 1, nio.pcap_output_file)) if not self._ethernet_adapters[adapter_number].get_nio(0): - yield from self._modify_vm("--cableconnected{} off".format(adapter_number + 1)) + await self._modify_vm("--cableconnected{} off".format(adapter_number + 1)) for adapter_number in range(self._adapters, self._maximum_adapters): log.debug("disabling remaining adapter {}".format(adapter_number)) - yield from self._modify_vm("--nic{} none".format(adapter_number + 1)) + await self._modify_vm("--nic{} none".format(adapter_number + 1)) - @asyncio.coroutine - def _create_linked_clone(self): + async def _create_linked_clone(self): """ Creates a new linked clone. """ gns3_snapshot_exists = False - vm_info = yield from self._get_vm_info() + vm_info = await self._get_vm_info() for entry, value in vm_info.items(): if entry.startswith("SnapshotName") and value == "GNS3 Linked Base for clones": gns3_snapshot_exists = True if not gns3_snapshot_exists: - result = yield from self.manager.execute("snapshot", [self._vmname, "take", "GNS3 Linked Base for clones"]) + result = await self.manager.execute("snapshot", [self._uuid, "take", "GNS3 Linked Base for clones"]) log.debug("GNS3 snapshot created: {}".format(result)) - args = [self._vmname, + args = [self._uuid, "--snapshot", "GNS3 Linked Base for clones", "--options", @@ -913,50 +912,69 @@ class VirtualBoxVM(BaseNode): self.working_dir, "--register"] - result = yield from self.manager.execute("clonevm", args) + result = await self.manager.execute("clonevm", args) log.debug("VirtualBox VM: {} cloned".format(result)) self._vmname = self._name - yield from self.manager.execute("setextradata", [self._vmname, "GNS3/Clone", "yes"]) + await self.manager.execute("setextradata", [self._uuid, "GNS3/Clone", "yes"]) # We create a reset snapshot in order to simplify life of user who want to rollback their VM # Warning: Do not document this it's seem buggy we keep it because Raizo students use it. try: - args = [self._vmname, "take", "reset"] - result = yield from self.manager.execute("snapshot", args) + args = [self._uuid, "take", "reset"] + result = await self.manager.execute("snapshot", args) log.debug("Snapshot 'reset' created: {}".format(result)) # It seem sometimes this failed due to internal race condition of Vbox # we have no real explanation of this. except VirtualBoxError: - log.warn("Snapshot 'reset' not created") + log.warning("Snapshot 'reset' not created") os.makedirs(os.path.join(self.working_dir, self._vmname), exist_ok=True) - @asyncio.coroutine - def _start_console(self): + async def _start_console(self): """ Starts remote console support for this VM. """ - self._remote_pipe = yield from asyncio_open_serial(self._get_pipe_name()) - server = AsyncioTelnetServer(reader=self._remote_pipe, - writer=self._remote_pipe, - binary=True, - echo=True) - self._telnet_server = yield from asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console) - @asyncio.coroutine - def _stop_remote_console(self): + if self.console and self.console_type == "telnet": + pipe_name = self._get_pipe_name() + try: + self._remote_pipe = await asyncio_open_serial(pipe_name) + except OSError as e: + raise VirtualBoxError("Could not open serial pipe '{}': {}".format(pipe_name, e)) + server = AsyncioTelnetServer(reader=self._remote_pipe, + writer=self._remote_pipe, + binary=True, + echo=True) + try: + self._telnet_server = await asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console) + except OSError as e: + self.project.emit("log.warning", {"message": "Could not start Telnet server on socket {}:{}: {}".format(self._manager.port_manager.console_host, self.console, e)}) + + async def _stop_remote_console(self): """ Stops remote console support for this VM. """ if self._telnet_server: self._telnet_server.close() - yield from self._telnet_server.wait_closed() + await self._telnet_server.wait_closed() self._remote_pipe.close() self._telnet_server = None - @asyncio.coroutine - def adapter_add_nio_binding(self, adapter_number, nio): + @BaseNode.console_type.setter + def console_type(self, new_console_type): + """ + Sets the console type for this VirtualBox VM. + + :param new_console_type: console type (string) + """ + + if self.is_running() and self.console_type != new_console_type: + raise VirtualBoxError('"{name}" must be stopped to change the console type to {new_console_type}'.format(name=self._name, new_console_type=new_console_type)) + + super(VirtualBoxVM, VirtualBoxVM).console_type.__set__(self, new_console_type) + + async def adapter_add_nio_binding(self, adapter_number, nio): """ Adds an adapter NIO binding. @@ -971,7 +989,7 @@ class VirtualBoxVM(BaseNode): adapter_number=adapter_number)) # check if trying to connect to a nat, bridged, host-only or any other special adapter - nic_attachments = yield from self._get_nic_attachements(self._maximum_adapters) + nic_attachments = await self._get_nic_attachements(self._maximum_adapters) attachment = nic_attachments[adapter_number] if attachment in ("nat", "bridged", "intnet", "hostonly", "natnetwork"): if not self._use_any_adapter: @@ -983,21 +1001,21 @@ class VirtualBoxVM(BaseNode): # dynamically configure an UDP tunnel attachment if the VM is already running local_nio = self._local_udp_tunnels[adapter_number][0] if local_nio and isinstance(local_nio, NIOUDP): - yield from self._control_vm("nic{} generic UDPTunnel".format(adapter_number + 1)) - yield from self._control_vm("nicproperty{} sport={}".format(adapter_number + 1, local_nio.lport)) - yield from self._control_vm("nicproperty{} dest={}".format(adapter_number + 1, local_nio.rhost)) - yield from self._control_vm("nicproperty{} dport={}".format(adapter_number + 1, local_nio.rport)) - yield from self._control_vm("setlinkstate{} on".format(adapter_number + 1)) + await self._control_vm("nic{} generic UDPTunnel".format(adapter_number + 1)) + await self._control_vm("nicproperty{} sport={}".format(adapter_number + 1, local_nio.lport)) + await self._control_vm("nicproperty{} dest={}".format(adapter_number + 1, local_nio.rhost)) + await self._control_vm("nicproperty{} dport={}".format(adapter_number + 1, local_nio.rport)) + await self._control_vm("setlinkstate{} on".format(adapter_number + 1)) if self.is_running(): try: - yield from self.add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number), + await self.add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number), self._local_udp_tunnels[adapter_number][1], nio) except KeyError: raise VirtualBoxError("Adapter {adapter_number} doesn't exist on VirtualBox VM '{name}'".format(name=self.name, adapter_number=adapter_number)) - yield from self._control_vm("setlinkstate{} on".format(adapter_number + 1)) + await self._control_vm("setlinkstate{} on".format(adapter_number + 1)) adapter.add_nio(0, nio) log.info("VirtualBox VM '{name}' [{id}]: {nio} added to adapter {adapter_number}".format(name=self.name, @@ -1005,29 +1023,28 @@ class VirtualBoxVM(BaseNode): nio=nio, adapter_number=adapter_number)) - @asyncio.coroutine - def adapter_update_nio_binding(self, adapter_number, nio): + async def adapter_update_nio_binding(self, adapter_number, nio): """ - Update a port NIO binding. + Update an adapter NIO binding. :param adapter_number: adapter number - :param nio: NIO instance to add to the adapter + :param nio: NIO instance to update on the adapter """ if self.is_running(): try: - yield from self.update_ubridge_udp_connection( - "VBOX-{}-{}".format(self._id, adapter_number), - self._local_udp_tunnels[adapter_number][1], - nio) + await self.update_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number), + self._local_udp_tunnels[adapter_number][1], + nio) + if nio.suspend: + await self._control_vm("setlinkstate{} off".format(adapter_number + 1)) + else: + await self._control_vm("setlinkstate{} on".format(adapter_number + 1)) except IndexError: - raise VirtualBoxError('Adapter {adapter_number} does not exist on VirtualBox VM "{name}"'.format( - name=self._name, - adapter_number=adapter_number - )) + raise VirtualBoxError('Adapter {adapter_number} does not exist on VirtualBox VM "{name}"'.format(name=self._name, + adapter_number=adapter_number)) - @asyncio.coroutine - def adapter_remove_nio_binding(self, adapter_number): + async def adapter_remove_nio_binding(self, adapter_number): """ Removes an adapter NIO binding. @@ -1042,11 +1059,12 @@ class VirtualBoxVM(BaseNode): raise VirtualBoxError("Adapter {adapter_number} doesn't exist on VirtualBox VM '{name}'".format(name=self.name, adapter_number=adapter_number)) + await self.stop_capture(adapter_number) if self.is_running(): - yield from self._ubridge_send("bridge delete {name}".format(name="VBOX-{}-{}".format(self._id, adapter_number))) - vm_state = yield from self._get_vm_state() + await self._ubridge_send("bridge delete {name}".format(name="VBOX-{}-{}".format(self._id, adapter_number))) + vm_state = await self._get_vm_state() if vm_state == "running": - yield from self._control_vm("setlinkstate{} off".format(adapter_number + 1)) + await self._control_vm("setlinkstate{} off".format(adapter_number + 1)) nio = adapter.get_nio(0) if isinstance(nio, NIOUDP): @@ -1059,14 +1077,35 @@ class VirtualBoxVM(BaseNode): adapter_number=adapter_number)) return nio + def get_nio(self, adapter_number): + """ + Gets an adapter NIO binding. + + :param adapter_number: adapter number + + :returns: NIO instance + """ + + try: + adapter = self.ethernet_adapters[adapter_number] + except KeyError: + raise VirtualBoxError("Adapter {adapter_number} doesn't exist on VirtualBox VM '{name}'".format(name=self.name, + adapter_number=adapter_number)) + + nio = adapter.get_nio(0) + + if not nio: + raise VirtualBoxError("Adapter {} is not connected".format(adapter_number)) + + return nio + def is_running(self): """ :returns: True if the vm is not stopped """ return self.ubridge is not None - @asyncio.coroutine - def start_capture(self, adapter_number, output_file): + async def start_capture(self, adapter_number, output_file): """ Starts a packet capture. @@ -1074,52 +1113,33 @@ class VirtualBoxVM(BaseNode): :param output_file: PCAP destination file for the capture """ - try: - adapter = self._ethernet_adapters[adapter_number] - except KeyError: - raise VirtualBoxError("Adapter {adapter_number} doesn't exist on VirtualBox VM '{name}'".format(name=self.name, - adapter_number=adapter_number)) - - nio = adapter.get_nio(0) - - if not nio: - raise VirtualBoxError("Adapter {} is not connected".format(adapter_number)) - + nio = self.get_nio(adapter_number) if nio.capturing: raise VirtualBoxError("Packet capture is already activated on adapter {adapter_number}".format(adapter_number=adapter_number)) - nio.startPacketCapture(output_file) - + nio.start_packet_capture(output_file) if self.ubridge: - yield from self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name="VBOX-{}-{}".format(self._id, adapter_number), + await self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name="VBOX-{}-{}".format(self._id, adapter_number), output_file=output_file)) log.info("VirtualBox VM '{name}' [{id}]: starting packet capture on adapter {adapter_number}".format(name=self.name, id=self.id, adapter_number=adapter_number)) - def stop_capture(self, adapter_number): + async def stop_capture(self, adapter_number): """ Stops a packet capture. :param adapter_number: adapter number """ - try: - adapter = self._ethernet_adapters[adapter_number] - except KeyError: - raise VirtualBoxError("Adapter {adapter_number} doesn't exist on VirtualBox VM '{name}'".format(name=self.name, - adapter_number=adapter_number)) - - nio = adapter.get_nio(0) - - if not nio: - raise VirtualBoxError("Adapter {} is not connected".format(adapter_number)) - - nio.stopPacketCapture() + nio = self.get_nio(adapter_number) + if not nio.capturing: + return + nio.stop_packet_capture() if self.ubridge: - yield from self._ubridge_send('bridge stop_capture {name}'.format(name="VBOX-{}-{}".format(self._id, adapter_number))) + await self._ubridge_send('bridge stop_capture {name}'.format(name="VBOX-{}-{}".format(self._id, adapter_number))) log.info("VirtualBox VM '{name}' [{id}]: stopping packet capture on adapter {adapter_number}".format(name=self.name, id=self.id, diff --git a/gns3server/compute/vmware/__init__.py b/gns3server/compute/vmware/__init__.py index 73f258f9..ce8845e7 100644 --- a/gns3server/compute/vmware/__init__.py +++ b/gns3server/compute/vmware/__init__.py @@ -135,19 +135,19 @@ class VMware(BaseManager): except OSError: pass if version is not None: - match = re.search("([0-9]+)\.", version) + match = re.search(r"([0-9]+)\.", version) if match: version = match.group(1) return version - @asyncio.coroutine - def _check_vmware_player_requirements(self, player_version): + async def _check_vmware_player_requirements(self, player_version): """ Check minimum requirements to use VMware Player. VIX 1.13 was the release for Player 6. VIX 1.14 was the release for Player 7. VIX 1.15 was the release for Workstation Player 12. + VIX 1.17 was the release for Workstation Player 14. :param player_version: VMware Player major version. """ @@ -156,21 +156,23 @@ class VMware(BaseManager): if player_version < 6: raise VMwareError("Using VMware Player requires version 6 or above") elif player_version == 6: - yield from self.check_vmrun_version(minimum_required_version="1.13.0") + await self.check_vmrun_version(minimum_required_version="1.13.0") elif player_version == 7: - yield from self.check_vmrun_version(minimum_required_version="1.14.0") + await self.check_vmrun_version(minimum_required_version="1.14.0") elif player_version >= 12: - yield from self.check_vmrun_version(minimum_required_version="1.15.0") + await self.check_vmrun_version(minimum_required_version="1.15.0") + elif player_version >= 14: + await self.check_vmrun_version(minimum_required_version="1.17.0") self._host_type = "player" - @asyncio.coroutine - def _check_vmware_workstation_requirements(self, ws_version): + async def _check_vmware_workstation_requirements(self, ws_version): """ Check minimum requirements to use VMware Workstation. VIX 1.13 was the release for Workstation 10. VIX 1.14 was the release for Workstation 11. VIX 1.15 was the release for Workstation Pro 12. + VIX 1.17 was the release for Workstation Pro 14. :param ws_version: VMware Workstation major version. """ @@ -179,15 +181,16 @@ class VMware(BaseManager): if ws_version < 10: raise VMwareError("Using VMware Workstation requires version 10 or above") elif ws_version == 10: - yield from self.check_vmrun_version(minimum_required_version="1.13.0") + await self.check_vmrun_version(minimum_required_version="1.13.0") elif ws_version == 11: - yield from self.check_vmrun_version(minimum_required_version="1.14.0") + await self.check_vmrun_version(minimum_required_version="1.14.0") elif ws_version >= 12: - yield from self.check_vmrun_version(minimum_required_version="1.15.0") + await self.check_vmrun_version(minimum_required_version="1.15.0") + elif ws_version >= 14: + await self.check_vmrun_version(minimum_required_version="1.17.0") self._host_type = "ws" - @asyncio.coroutine - def check_vmware_version(self): + async def check_vmware_version(self): """ Check VMware version """ @@ -199,13 +202,13 @@ class VMware(BaseManager): player_version = self._find_vmware_version_registry(r"SOFTWARE\Wow6432Node\VMware, Inc.\VMware Player") if player_version: log.debug("VMware Player version {} detected".format(player_version)) - yield from self._check_vmware_player_requirements(player_version) + await self._check_vmware_player_requirements(player_version) else: log.warning("Could not find VMware version") self._host_type = "ws" else: log.debug("VMware Workstation version {} detected".format(ws_version)) - yield from self._check_vmware_workstation_requirements(ws_version) + await self._check_vmware_workstation_requirements(ws_version) else: if sys.platform.startswith("darwin"): if not os.path.isdir("/Applications/VMware Fusion.app"): @@ -218,20 +221,20 @@ class VMware(BaseManager): raise VMwareError("VMware is not installed (vmware or vmplayer executable could not be found in $PATH)") try: - output = yield from subprocess_check_output(vmware_path, "-v") - match = re.search("VMware Workstation ([0-9]+)\.", output) + output = await subprocess_check_output(vmware_path, "-v") + match = re.search(r"VMware Workstation ([0-9]+)\.", output) version = None if match: # VMware Workstation has been detected version = match.group(1) log.debug("VMware Workstation version {} detected".format(version)) - yield from self._check_vmware_workstation_requirements(version) - match = re.search("VMware Player ([0-9]+)\.", output) + await self._check_vmware_workstation_requirements(version) + match = re.search(r"VMware Player ([0-9]+)\.", output) if match: # VMware Player has been detected version = match.group(1) log.debug("VMware Player version {} detected".format(version)) - yield from self._check_vmware_player_requirements(version) + await self._check_vmware_player_requirements(version) if version is None: log.warning("Could not find VMware version. Output of VMware: {}".format(output)) raise VMwareError("Could not find VMware version. Output of VMware: {}".format(output)) @@ -253,7 +256,7 @@ class VMware(BaseManager): if winreg.QueryInfoKey(hkeyvmnet)[1]: # the vmnet has not been configure if the key has no values vmnet = vmnet.replace("vm", "VM") - if vmnet not in ("VMnet1", "VMnet8"): + if vmnet not in ("VMnet0", "VMnet1", "VMnet8"): vmnet_interfaces.append(vmnet) winreg.CloseKey(hkeyvmnet) winreg.CloseKey(hkey) @@ -275,10 +278,10 @@ class VMware(BaseManager): try: with open(vmware_networking_file, "r", encoding="utf-8") as f: for line in f.read().splitlines(): - match = re.search("VNET_([0-9]+)_VIRTUAL_ADAPTER", line) + match = re.search(r"VNET_([0-9]+)_VIRTUAL_ADAPTER", line) if match: vmnet = "vmnet{}".format(match.group(1)) - if vmnet not in ("vmnet1", "vmnet8"): + if vmnet not in ("vmnet0", "vmnet1", "vmnet8"): vmnet_interfaces.append(vmnet) except OSError as e: raise VMwareError("Cannot open {}: {}".format(vmware_networking_file, e)) @@ -294,14 +297,14 @@ class VMware(BaseManager): windows_name = interface["netcard"] else: windows_name = interface["name"] - match = re.search("(VMnet[0-9]+)", windows_name) + match = re.search(r"(VMnet[0-9]+)", windows_name) if match: vmnet = match.group(1) - if vmnet not in ("VMnet1", "VMnet8"): + if vmnet not in ("VMnet0", "VMnet1", "VMnet8"): vmnet_interfaces.append(vmnet) elif interface["name"].startswith("vmnet"): vmnet = interface["name"] - if vmnet not in ("vmnet1", "vmnet8"): + if vmnet not in ("vmnet0", "vmnet1", "vmnet8"): vmnet_interfaces.append(interface["name"]) return vmnet_interfaces @@ -309,7 +312,7 @@ class VMware(BaseManager): self._vmnet_start_range = self.config.get_section_config("VMware").getint("vmnet_start_range", self._vmnet_start_range) self._vmnet_end_range = self.config.get_section_config("VMware").getint("vmnet_end_range", self._vmnet_end_range) - match = re.search("vmnet([0-9]+)$", vmnet, re.IGNORECASE) + match = re.search(r"vmnet([0-9]+)$", vmnet, re.IGNORECASE) if match: vmnet_number = match.group(1) if self._vmnet_start_range <= int(vmnet_number) <= self._vmnet_end_range: @@ -357,28 +360,26 @@ class VMware(BaseManager): return self._host_type - @asyncio.coroutine - def execute(self, subcommand, args, timeout=120, log_level=logging.INFO): + async def execute(self, subcommand, args, timeout=120, log_level=logging.INFO): trial = 2 while True: try: - return (yield from self._execute(subcommand, args, timeout=timeout, log_level=log_level)) + return (await self._execute(subcommand, args, timeout=timeout, log_level=log_level)) except VMwareError as e: # We can fail to detect that it's VMware player instead of Workstation (due to marketing change Player is now Player Workstation) if self.host_type == "ws" and "VIX_SERVICEPROVIDER_VMWARE_WORKSTATION" in str(e): self._host_type = "player" - return (yield from self._execute(subcommand, args, timeout=timeout, log_level=log_level)) + return (await self._execute(subcommand, args, timeout=timeout, log_level=log_level)) else: if trial <= 0: raise e trial -= 1 - yield from asyncio.sleep(0.5) + await asyncio.sleep(0.5) - @asyncio.coroutine - def _execute(self, subcommand, args, timeout=120, log_level=logging.INFO): + async def _execute(self, subcommand, args, timeout=120, log_level=logging.INFO): if self.host_type is None: - yield from self.check_vmware_version() + await self.check_vmware_version() vmrun_path = self.vmrun_path if not vmrun_path: @@ -389,12 +390,12 @@ class VMware(BaseManager): command_string = " ".join([shlex.quote(c) for c in command]) log.log(log_level, "Executing vmrun with command: {}".format(command_string)) try: - process = yield from asyncio.create_subprocess_exec(*command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + process = await asyncio.create_subprocess_exec(*command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) except (OSError, subprocess.SubprocessError) as e: raise VMwareError("Could not execute vmrun: {}".format(e)) try: - stdout_data, _ = yield from asyncio.wait_for(process.communicate(), timeout=timeout) + stdout_data, _ = await asyncio.wait_for(process.communicate(), timeout=timeout) except asyncio.TimeoutError: raise VMwareError("vmrun has timed out after {} seconds!\nTry to run {} in a terminal to see more details.\n\nMake sure GNS3 and VMware run under the same user and whitelist vmrun.exe in your antivirus.".format(timeout, command_string)) @@ -405,8 +406,7 @@ class VMware(BaseManager): return stdout_data.decode("utf-8", errors="ignore").splitlines() - @asyncio.coroutine - def check_vmrun_version(self, minimum_required_version="1.13.0"): + async def check_vmrun_version(self, minimum_required_version="1.13.0"): """ Checks the vmrun version. @@ -423,8 +423,8 @@ class VMware(BaseManager): vmrun_path = self.find_vmrun() try: - output = yield from subprocess_check_output(vmrun_path) - match = re.search("vmrun version ([0-9\.]+)", output) + output = await subprocess_check_output(vmrun_path) + match = re.search(r"vmrun version ([0-9\.]+)", output) version = None if match: version = match.group(1) @@ -438,15 +438,14 @@ class VMware(BaseManager): log.error("Error while looking for the VMware vmrun version: {}".format(e)) raise VMwareError("Error while looking for the VMware vmrun version: {}".format(e)) - @asyncio.coroutine - def remove_from_vmware_inventory(self, vmx_path): + async def remove_from_vmware_inventory(self, vmx_path): """ Removes a linked clone from the VMware inventory file. :param vmx_path: path of the linked clone VMX file """ - with (yield from self._vmware_inventory_lock): + async with self._vmware_inventory_lock: inventory_path = self.get_vmware_inventory_path() if os.path.exists(inventory_path): try: @@ -669,14 +668,13 @@ class VMware(BaseManager): else: return [os.path.expanduser("~/vmware")] - @asyncio.coroutine - def list_vms(self): + async def list_vms(self): """ Gets VMware VM list. """ # check for the right VMware version - yield from self.check_vmware_version() + await self.check_vmware_version() vmware_vms = [] inventory_path = self.get_vmware_inventory_path() if os.path.exists(inventory_path) and self.host_type != "player": @@ -738,4 +736,4 @@ if __name__ == '__main__': loop = asyncio.get_event_loop() vmware = VMware.instance() print("=> Check version") - loop.run_until_complete(asyncio.async(vmware.check_vmware_version())) + loop.run_until_complete(asyncio.ensure_future(vmware.check_vmware_version())) diff --git a/gns3server/compute/vmware/vmware_vm.py b/gns3server/compute/vmware/vmware_vm.py index 3e2e58df..28b67ca2 100644 --- a/gns3server/compute/vmware/vmware_vm.py +++ b/gns3server/compute/vmware/vmware_vm.py @@ -24,10 +24,9 @@ import os import asyncio import tempfile -from gns3server.utils.interfaces import interfaces from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer from gns3server.utils.asyncio.serial import asyncio_open_serial -from gns3server.utils.asyncio import locked_coroutine +from gns3server.utils.asyncio import locking from collections import OrderedDict from .vmware_error import VMwareError from ..nios.nio_udp import NIOUDP @@ -45,9 +44,9 @@ class VMwareVM(BaseNode): VMware VM implementation. """ - def __init__(self, name, node_id, project, manager, vmx_path, linked_clone=False, console=None): + def __init__(self, name, node_id, project, manager, vmx_path, linked_clone=False, console=None, console_type="telnet"): - super().__init__(name, node_id, project, manager, console=console, linked_clone=linked_clone) + super().__init__(name, node_id, project, manager, console=console, console_type=console_type, linked_clone=linked_clone) self._vmx_pairs = OrderedDict() self._telnet_server = None @@ -59,7 +58,7 @@ class VMwareVM(BaseNode): # VMware VM settings self._headless = False self._vmx_path = vmx_path - self._acpi_shutdown = False + self._on_close = "power_off" self._adapters = 0 self._ethernet_adapters = {} self._adapter_type = "e1000" @@ -75,13 +74,14 @@ class VMwareVM(BaseNode): def __json__(self): json = {"name": self.name, + "usage": self.usage, "node_id": self.id, "console": self.console, "console_type": self.console_type, "project_id": self.project.id, "vmx_path": self.vmx_path, "headless": self.headless, - "acpi_shutdown": self.acpi_shutdown, + "on_close": self.on_close, "adapters": self._adapters, "adapter_type": self.adapter_type, "use_any_adapter": self.use_any_adapter, @@ -95,12 +95,12 @@ class VMwareVM(BaseNode): return self._vmnets - @locked_coroutine - def _control_vm(self, subcommand, *additional_args): + @locking + async def _control_vm(self, subcommand, *additional_args): args = [self._vmx_path] args.extend(additional_args) - result = yield from self.manager.execute(subcommand, args) + result = await self.manager.execute(subcommand, args) log.debug("Control VM '{}' result: {}".format(subcommand, result)) return result @@ -124,16 +124,14 @@ class VMwareVM(BaseNode): except OSError as e: raise VMwareError('Could not write VMware VMX file "{}": {}'.format(self._vmx_path, e)) - @asyncio.coroutine - def is_running(self): + async def is_running(self): - result = yield from self.manager.execute("list", []) + result = await self.manager.execute("list", []) if self._vmx_path in result: return True return False - @asyncio.coroutine - def _check_duplicate_linked_clone(self): + async def _check_duplicate_linked_clone(self): """ Without linked clone two VM using the same image can't run at the same time. @@ -157,17 +155,16 @@ class VMwareVM(BaseNode): if not found: return trial += 1 - yield from asyncio.sleep(1) + await asyncio.sleep(1) - @asyncio.coroutine - def create(self): + async def create(self): """ Creates this VM and handle linked clones. """ if not self.linked_clone: - yield from self._check_duplicate_linked_clone() + await self._check_duplicate_linked_clone() - yield from self.manager.check_vmrun_version() + await self.manager.check_vmrun_version() if self.linked_clone and not os.path.exists(os.path.join(self.working_dir, os.path.basename(self._vmx_path))): if self.manager.host_type == "player": raise VMwareError("Linked clones are not supported by VMware Player") @@ -187,15 +184,15 @@ class VMwareVM(BaseNode): break if not gns3_snapshot_exists: log.info("Creating snapshot '{}'".format(base_snapshot_name)) - yield from self._control_vm("snapshot", base_snapshot_name) + await self._control_vm("snapshot", base_snapshot_name) # create the linked clone based on the base snapshot new_vmx_path = os.path.join(self.working_dir, self.name + ".vmx") - yield from self._control_vm("clone", - new_vmx_path, - "linked", - "-snapshot={}".format(base_snapshot_name), - "-cloneName={}".format(self.name)) + await self._control_vm("clone", + new_vmx_path, + "linked", + "-snapshot={}".format(base_snapshot_name), + "-cloneName={}".format(self.name)) try: vmsd_pairs = self.manager.parse_vmware_file(vmsd_path) @@ -259,17 +256,20 @@ class VMwareVM(BaseNode): self.manager.refresh_vmnet_list() for adapter_number in range(0, self._adapters): + custom_adapter = self._get_custom_adapter_settings(adapter_number) + adapter_type = custom_adapter.get("adapter_type", self._adapter_type) + # add/update the interface - if self._adapter_type == "default": + if adapter_type == "default": # force default to e1000 because some guest OS don't detect the adapter (i.e. Windows 2012 server) # when 'virtualdev' is not set in the VMX file. - adapter_type = "e1000" + vmware_adapter_type = "e1000" else: - adapter_type = self._adapter_type + vmware_adapter_type = adapter_type ethernet_adapter = {"ethernet{}.present".format(adapter_number): "TRUE", "ethernet{}.addresstype".format(adapter_number): "generated", "ethernet{}.generatedaddressoffset".format(adapter_number): "0", - "ethernet{}.virtualdev".format(adapter_number): adapter_type} + "ethernet{}.virtualdev".format(adapter_number): vmware_adapter_type} self._vmx_pairs.update(ethernet_adapter) connection_type = "ethernet{}.connectiontype".format(adapter_number) @@ -277,6 +277,7 @@ class VMwareVM(BaseNode): continue self._vmx_pairs["ethernet{}.connectiontype".format(adapter_number)] = "custom" + # make sure we have a vmnet per adapter if we use uBridge allocate_vmnet = False @@ -285,7 +286,7 @@ class VMwareVM(BaseNode): if vnet in self._vmx_pairs: vmnet = os.path.basename(self._vmx_pairs[vnet]) if self.manager.is_managed_vmnet(vmnet) or vmnet in ("vmnet0", "vmnet1", "vmnet8"): - # vmnet already managed, try to allocate a new one + # vmnet already managed or a special vmnet, try to allocate a new one allocate_vmnet = True else: # otherwise allocate a new one @@ -299,7 +300,7 @@ class VMwareVM(BaseNode): self._vmnets.clear() raise - # mark the vmnet managed by us + # mark the vmnet as managed by us if vmnet not in self._vmnets: self._vmnets.append(vmnet) self._vmx_pairs["ethernet{}.vnet".format(adapter_number)] = vmnet @@ -319,8 +320,7 @@ class VMwareVM(BaseNode): raise VMwareError("vnet {} not in VMX file".format(vnet)) return vnet - @asyncio.coroutine - def _add_ubridge_connection(self, nio, adapter_number): + async def _add_ubridge_connection(self, nio, adapter_number): """ Creates a connection in uBridge. @@ -329,30 +329,29 @@ class VMwareVM(BaseNode): """ vnet = self._get_vnet(adapter_number) - yield from self._ubridge_send("bridge create {name}".format(name=vnet)) + await self._ubridge_send("bridge create {name}".format(name=vnet)) vmnet_interface = os.path.basename(self._vmx_pairs[vnet]) if sys.platform.startswith("darwin"): # special case on OSX, we cannot bind VMnet interfaces using the libpcap - yield from self._ubridge_send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=vnet, interface=vmnet_interface)) + await self._ubridge_send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=vnet, interface=vmnet_interface)) else: block_host_traffic = self.manager.config.get_section_config("VMware").getboolean("block_host_traffic", False) - yield from self._add_ubridge_ethernet_connection(vnet, vmnet_interface, block_host_traffic) + await self._add_ubridge_ethernet_connection(vnet, vmnet_interface, block_host_traffic) if isinstance(nio, NIOUDP): - yield from self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=vnet, + await self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=vnet, lport=nio.lport, rhost=nio.rhost, rport=nio.rport)) if nio.capturing: - yield from self._ubridge_send('bridge start_capture {name} "{pcap_file}"'.format(name=vnet, pcap_file=nio.pcap_output_file)) + await self._ubridge_send('bridge start_capture {name} "{pcap_file}"'.format(name=vnet, pcap_file=nio.pcap_output_file)) - yield from self._ubridge_send('bridge start {name}'.format(name=vnet)) - yield from self._ubridge_apply_filters(vnet, nio.filters) + await self._ubridge_send('bridge start {name}'.format(name=vnet)) + await self._ubridge_apply_filters(vnet, nio.filters) - @asyncio.coroutine - def _update_ubridge_connection(self, adapter_number, nio): + async def _update_ubridge_connection(self, adapter_number, nio): """ Update a connection in uBridge. @@ -363,10 +362,9 @@ class VMwareVM(BaseNode): bridge_name = self._get_vnet(adapter_number) except VMwareError: return # vnet not yet available - yield from self._ubridge_apply_filters(bridge_name, nio.filters) + await self._ubridge_apply_filters(bridge_name, nio.filters) - @asyncio.coroutine - def _delete_ubridge_connection(self, adapter_number): + async def _delete_ubridge_connection(self, adapter_number): """ Deletes a connection in uBridge. @@ -376,10 +374,9 @@ class VMwareVM(BaseNode): vnet = "ethernet{}.vnet".format(adapter_number) if vnet not in self._vmx_pairs: raise VMwareError("vnet {} not in VMX file".format(vnet)) - yield from self._ubridge_send("bridge delete {name}".format(name=vnet)) + await self._ubridge_send("bridge delete {name}".format(name=vnet)) - @asyncio.coroutine - def _start_ubridge_capture(self, adapter_number, output_file): + async def _start_ubridge_capture(self, adapter_number, output_file): """ Start a packet capture in uBridge. @@ -392,11 +389,10 @@ class VMwareVM(BaseNode): raise VMwareError("vnet {} not in VMX file".format(vnet)) if not self._ubridge_hypervisor: raise VMwareError("Cannot start the packet capture: uBridge is not running") - yield from self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name=vnet, + await self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name=vnet, output_file=output_file)) - @asyncio.coroutine - def _stop_ubridge_capture(self, adapter_number): + async def _stop_ubridge_capture(self, adapter_number): """ Stop a packet capture in uBridge. @@ -408,7 +404,7 @@ class VMwareVM(BaseNode): raise VMwareError("vnet {} not in VMX file".format(vnet)) if not self._ubridge_hypervisor: raise VMwareError("Cannot stop the packet capture: uBridge is not running") - yield from self._ubridge_send("bridge stop_capture {name}".format(name=vnet)) + await self._ubridge_send("bridge stop_capture {name}".format(name=vnet)) def check_hw_virtualization(self): """ @@ -422,8 +418,7 @@ class VMwareVM(BaseNode): return True return False - @asyncio.coroutine - def start(self): + async def start(self): """ Starts this VMware VM. """ @@ -431,14 +426,14 @@ class VMwareVM(BaseNode): if self.status == "started": return - if (yield from self.is_running()): + if (await self.is_running()): raise VMwareError("The VM is already running in VMware") ubridge_path = self.ubridge_path if not ubridge_path or not os.path.isfile(ubridge_path): raise VMwareError("ubridge is necessary to start a VMware VM") - yield from self._start_ubridge() + await self._start_ubridge(require_privileged_access=True) self._read_vmx_file() # check if there is enough RAM to run if "memsize" in self._vmx_pairs: @@ -448,20 +443,20 @@ class VMwareVM(BaseNode): self._write_vmx_file() if self._headless: - yield from self._control_vm("start", "nogui") + await self._control_vm("start", "nogui") else: - yield from self._control_vm("start") + await self._control_vm("start") try: if self._ubridge_hypervisor: for adapter_number in range(0, self._adapters): nio = self._ethernet_adapters[adapter_number].get_nio(0) if nio: - yield from self._add_ubridge_connection(nio, adapter_number) + await self._add_ubridge_connection(nio, adapter_number) - yield from self._start_console() + await self._start_console() except VMwareError: - yield from self.stop() + await self.stop() raise if self._get_vmx_setting("vhv.enable", "TRUE"): @@ -471,23 +466,24 @@ class VMwareVM(BaseNode): self.status = "started" log.info("VMware VM '{name}' [{id}] started".format(name=self.name, id=self.id)) - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops this VMware VM. """ self._hw_virtualization = False - yield from self._stop_remote_console() - yield from self._stop_ubridge() + await self._stop_remote_console() + await self._stop_ubridge() try: - if (yield from self.is_running()): - if self.acpi_shutdown: + if (await self.is_running()): + if self.on_close == "save_vm_state": + await self._control_vm("suspend") + elif self.on_close == "shutdown_signal": # use ACPI to shutdown the VM - yield from self._control_vm("stop", "soft") + await self._control_vm("stop", "soft") else: - yield from self._control_vm("stop") + await self._control_vm("stop") finally: self._started = False self.status = "stopped" @@ -513,49 +509,45 @@ class VMwareVM(BaseNode): self._vmx_pairs["ethernet{}.startconnected".format(adapter_number)] = "TRUE" self._write_vmx_file() - yield from super().stop() + await super().stop() log.info("VMware VM '{name}' [{id}] stopped".format(name=self.name, id=self.id)) - @asyncio.coroutine - def suspend(self): + async def suspend(self): """ Suspends this VMware VM. """ if self.manager.host_type != "ws": raise VMwareError("Pausing a VM is only supported by VMware Workstation") - yield from self._control_vm("pause") + await self._control_vm("pause") self.status = "suspended" log.info("VMware VM '{name}' [{id}] paused".format(name=self.name, id=self.id)) - @asyncio.coroutine - def resume(self): + async def resume(self): """ Resumes this VMware VM. """ if self.manager.host_type != "ws": raise VMwareError("Unpausing a VM is only supported by VMware Workstation") - yield from self._control_vm("unpause") + await self._control_vm("unpause") self.status = "started" log.info("VMware VM '{name}' [{id}] resumed".format(name=self.name, id=self.id)) - @asyncio.coroutine - def reload(self): + async def reload(self): """ Reloads this VMware VM. """ - yield from self._control_vm("reset") + await self._control_vm("reset") log.info("VMware VM '{name}' [{id}] reloaded".format(name=self.name, id=self.id)) - @asyncio.coroutine - def close(self): + async def close(self): """ Closes this VMware VM. """ - if not (yield from super().close()): + if not (await super().close()): return False for adapter in self._ethernet_adapters.values(): @@ -564,13 +556,13 @@ class VMwareVM(BaseNode): if nio and isinstance(nio, NIOUDP): self.manager.port_manager.release_udp_port(nio.lport, self._project) try: - self.acpi_shutdown = False - yield from self.stop() + self.on_close = "power_off" + await self.stop() except VMwareError: pass if self.linked_clone: - yield from self.manager.remove_from_vmware_inventory(self._vmx_path) + await self.manager.remove_from_vmware_inventory(self._vmx_path) @property def headless(self): @@ -597,28 +589,25 @@ class VMwareVM(BaseNode): self._headless = headless @property - def acpi_shutdown(self): + def on_close(self): """ - Returns either the VM will use ACPI shutdown + Returns the action to execute when the VM is stopped/closed - :returns: boolean + :returns: string """ - return self._acpi_shutdown + return self._on_close - @acpi_shutdown.setter - def acpi_shutdown(self, acpi_shutdown): + @on_close.setter + def on_close(self, on_close): """ - Sets either the VM will use ACPI shutdown + Sets the action to execute when the VM is stopped/closed - :param acpi_shutdown: boolean + :param on_close: string """ - if acpi_shutdown: - log.info("VMware VM '{name}' [{id}] has enabled the ACPI shutdown mode".format(name=self.name, id=self.id)) - else: - log.info("VMware VM '{name}' [{id}] has disabled the ACPI shutdown mode".format(name=self.name, id=self.id)) - self._acpi_shutdown = acpi_shutdown + log.info('VMware VM "{name}" [{id}] set the close action to "{action}"'.format(name=self._name, id=self._id, action=on_close)) + self._on_close = on_close @property def vmx_path(self): @@ -719,8 +708,7 @@ class VMwareVM(BaseNode): log.info("VMware VM '{name}' [{id}] is not allowed to use any adapter".format(name=self.name, id=self.id)) self._use_any_adapter = use_any_adapter - @asyncio.coroutine - def adapter_add_nio_binding(self, adapter_number, nio): + async def adapter_add_nio_binding(self, adapter_number, nio): """ Adds an adapter NIO binding. @@ -739,47 +727,44 @@ class VMwareVM(BaseNode): if self._get_vmx_setting("ethernet{}.present".format(adapter_number), "TRUE"): # check for the connection type connection_type = "ethernet{}.connectiontype".format(adapter_number) - if connection_type in self._vmx_pairs and self._vmx_pairs[connection_type] in ("nat", "bridged", "hostonly"): - if not self._use_any_adapter: - raise VMwareError("Attachment '{attachment}' is already configured on network adapter {adapter_number}. " - "Please remove it or allow VMware VM '{name}' to use any adapter.".format(attachment=self._vmx_pairs[connection_type], - adapter_number=adapter_number, - name=self.name)) - elif (yield from self.is_running()): + if not self._use_any_adapter and connection_type in self._vmx_pairs and self._vmx_pairs[connection_type] in ("nat", "bridged", "hostonly"): + if (await self.is_running()): raise VMwareError("Attachment '{attachment}' is configured on network adapter {adapter_number}. " "Please stop VMware VM '{name}' to link to this adapter and allow GNS3 to change the attachment type.".format(attachment=self._vmx_pairs[connection_type], adapter_number=adapter_number, name=self.name)) + else: + raise VMwareError("Attachment '{attachment}' is already configured on network adapter {adapter_number}. " + "Please remove it or allow VMware VM '{name}' to use any adapter.".format(attachment=self._vmx_pairs[connection_type], + adapter_number=adapter_number, + name=self.name)) + adapter.add_nio(0, nio) if self._started and self._ubridge_hypervisor: - yield from self._add_ubridge_connection(nio, adapter_number) + await self._add_ubridge_connection(nio, adapter_number) log.info("VMware VM '{name}' [{id}]: {nio} added to adapter {adapter_number}".format(name=self.name, id=self.id, nio=nio, adapter_number=adapter_number)) - @asyncio.coroutine - def adapter_update_nio_binding(self, adapter_number, nio): + async def adapter_update_nio_binding(self, adapter_number, nio): """ - Update a port NIO binding. + Updates an adapter NIO binding. :param adapter_number: adapter number - :param nio: NIO instance to add to the adapter + :param nio: NIO instance to update on the adapter """ if self._ubridge_hypervisor: try: - yield from self._update_ubridge_connection(adapter_number, nio) + await self._update_ubridge_connection(adapter_number, nio) except IndexError: - raise VMwareError('Adapter {adapter_number} does not exist on VMware VM "{name}"'.format( - name=self._name, - adapter_number=adapter_number - )) + raise VMwareError('Adapter {adapter_number} does not exist on VMware VM "{name}"'.format(name=self._name, + adapter_number=adapter_number)) - @asyncio.coroutine - def adapter_remove_nio_binding(self, adapter_number): + async def adapter_remove_nio_binding(self, adapter_number): """ Removes an adapter NIO binding. @@ -794,12 +779,13 @@ class VMwareVM(BaseNode): raise VMwareError("Adapter {adapter_number} doesn't exist on VMware VM '{name}'".format(name=self.name, adapter_number=adapter_number)) + await self.stop_capture(adapter_number) nio = adapter.get_nio(0) if isinstance(nio, NIOUDP): self.manager.port_manager.release_udp_port(nio.lport, self._project) adapter.remove_nio(0) if self._started and self._ubridge_hypervisor: - yield from self._delete_ubridge_connection(adapter_number) + await self._delete_ubridge_connection(adapter_number) log.info("VMware VM '{name}' [{id}]: {nio} removed from adapter {adapter_number}".format(name=self.name, id=self.id, @@ -808,6 +794,27 @@ class VMwareVM(BaseNode): return nio + def get_nio(self, adapter_number): + """ + Gets an adapter NIO binding. + + :param adapter_number: adapter number + + :returns: NIO instance + """ + + try: + adapter = self.ethernet_adapters[adapter_number] + except KeyError: + raise VMwareError("Adapter {adapter_number} doesn't exist on VMware VM '{name}'".format(name=self.name, + adapter_number=adapter_number)) + + nio = adapter.get_nio(0) + if not nio: + raise VMwareError("Adapter {} is not connected".format(adapter_number)) + + return nio + def _get_pipe_name(self): """ Returns the pipe name to create a serial connection. @@ -838,31 +845,50 @@ class VMwareVM(BaseNode): "serial0.startconnected": "TRUE"} self._vmx_pairs.update(serial_port) - @asyncio.coroutine - def _start_console(self): + async def _start_console(self): """ Starts remote console support for this VM. """ - self._remote_pipe = yield from asyncio_open_serial(self._get_pipe_name()) - server = AsyncioTelnetServer(reader=self._remote_pipe, - writer=self._remote_pipe, - binary=True, - echo=True) - self._telnet_server = yield from asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console) - @asyncio.coroutine - def _stop_remote_console(self): + if self.console and self.console_type == "telnet": + pipe_name = self._get_pipe_name() + try: + self._remote_pipe = await asyncio_open_serial(self._get_pipe_name()) + except OSError as e: + raise VMwareError("Could not open serial pipe '{}': {}".format(pipe_name, e)) + server = AsyncioTelnetServer(reader=self._remote_pipe, + writer=self._remote_pipe, + binary=True, + echo=True) + try: + self._telnet_server = await asyncio.start_server(server.run, self._manager.port_manager.console_host, self.console) + except OSError as e: + self.project.emit("log.warning", {"message": "Could not start Telnet server on socket {}:{}: {}".format(self._manager.port_manager.console_host, self.console, e)}) + + async def _stop_remote_console(self): """ Stops remote console support for this VM. """ if self._telnet_server: self._telnet_server.close() - yield from self._telnet_server.wait_closed() + await self._telnet_server.wait_closed() self._remote_pipe.close() self._telnet_server = None - @asyncio.coroutine - def start_capture(self, adapter_number, output_file): + @BaseNode.console_type.setter + def console_type(self, new_console_type): + """ + Sets the console type for this VMware VM. + + :param new_console_type: console type (string) + """ + + if self._started and self.console_type != new_console_type: + raise VMwareError('"{name}" must be stopped to change the console type to {new_console_type}'.format(name=self._name, new_console_type=new_console_type)) + + super(VMwareVM, VMwareVM).console_type.__set__(self, new_console_type) + + async def start_capture(self, adapter_number, output_file): """ Starts a packet capture. @@ -870,51 +896,32 @@ class VMwareVM(BaseNode): :param output_file: PCAP destination file for the capture """ - try: - adapter = self._ethernet_adapters[adapter_number] - except KeyError: - raise VMwareError("Adapter {adapter_number} doesn't exist on VMware VM '{name}'".format(name=self.name, - adapter_number=adapter_number)) - - nio = adapter.get_nio(0) - - if not nio: - raise VMwareError("Adapter {} is not connected".format(adapter_number)) - + nio = self.get_nio(adapter_number) if nio.capturing: raise VMwareError("Packet capture is already activated on adapter {adapter_number}".format(adapter_number=adapter_number)) - nio.startPacketCapture(output_file) - + nio.start_packet_capture(output_file) if self._started: - yield from self._start_ubridge_capture(adapter_number, output_file) + await self._start_ubridge_capture(adapter_number, output_file) log.info("VMware VM '{name}' [{id}]: starting packet capture on adapter {adapter_number}".format(name=self.name, id=self.id, adapter_number=adapter_number)) - def stop_capture(self, adapter_number): + async def stop_capture(self, adapter_number): """ Stops a packet capture. :param adapter_number: adapter number """ - try: - adapter = self._ethernet_adapters[adapter_number] - except KeyError: - raise VMwareError("Adapter {adapter_number} doesn't exist on VMware VM '{name}'".format(name=self.name, - adapter_number=adapter_number)) - - nio = adapter.get_nio(0) - - if not nio: - raise VMwareError("Adapter {} is not connected".format(adapter_number)) - - nio.stopPacketCapture() + nio = self.get_nio(adapter_number) + if not nio.capturing: + return + nio.stop_packet_capture() if self._started: - yield from self._stop_ubridge_capture(adapter_number) + await self._stop_ubridge_capture(adapter_number) log.info("VMware VM '{name}' [{id}]: stopping packet capture on adapter {adapter_number}".format(name=self.name, id=self.id, diff --git a/gns3server/compute/vpcs/__init__.py b/gns3server/compute/vpcs/__init__.py index acd0087a..d1ee9abd 100644 --- a/gns3server/compute/vpcs/__init__.py +++ b/gns3server/compute/vpcs/__init__.py @@ -37,15 +37,14 @@ class VPCS(BaseManager): self._free_mac_ids = {} self._used_mac_ids = {} - @asyncio.coroutine - def create_node(self, *args, **kwargs): + async def create_node(self, *args, **kwargs): """ Creates a new VPCS VM. :returns: VPCSVM instance """ - node = yield from super().create_node(*args, **kwargs) + node = await super().create_node(*args, **kwargs) self._free_mac_ids.setdefault(node.project.id, list(range(0, 255))) try: self._used_mac_ids[node.id] = self._free_mac_ids[node.project.id].pop(0) @@ -53,8 +52,7 @@ class VPCS(BaseManager): raise VPCSError("Cannot create a new VPCS VM (limit of 255 VMs reached on this host)") return node - @asyncio.coroutine - def close_node(self, node_id, *args, **kwargs): + async def close_node(self, node_id, *args, **kwargs): """ Closes a VPCS VM. @@ -66,7 +64,7 @@ class VPCS(BaseManager): i = self._used_mac_ids[node_id] self._free_mac_ids[node.project.id].insert(0, i) del self._used_mac_ids[node_id] - yield from super().close_node(node_id, *args, **kwargs) + await super().close_node(node_id, *args, **kwargs) return node def get_mac_id(self, node_id): diff --git a/gns3server/compute/vpcs/vpcs_vm.py b/gns3server/compute/vpcs/vpcs_vm.py index 787c0aa6..80eb8d5b 100644 --- a/gns3server/compute/vpcs/vpcs_vm.py +++ b/gns3server/compute/vpcs/vpcs_vm.py @@ -37,7 +37,6 @@ from gns3server.utils import parse_version from .vpcs_error import VPCSError from ..adapters.ethernet_adapter import EthernetAdapter from ..nios.nio_udp import NIOUDP -from ..nios.nio_tap import NIOTAP from ..base_node import BaseNode @@ -59,9 +58,9 @@ class VPCSVM(BaseNode): :param startup_script: content of the startup script file """ - def __init__(self, name, node_id, project, manager, console=None, startup_script=None): + def __init__(self, name, node_id, project, manager, console=None, console_type="telnet", startup_script=None): - super().__init__(name, node_id, project, manager, console=console, wrap_console=True) + super().__init__(name, node_id, project, manager, console=console, console_type=console_type, wrap_console=True) self._process = None self._vpcs_stdout_file = "" self._vpcs_version = None @@ -77,13 +76,12 @@ class VPCSVM(BaseNode): def ethernet_adapter(self): return self._ethernet_adapter - @asyncio.coroutine - def close(self): + async def close(self): """ Closes this VPCS VM. """ - if not (yield from super().close()): + if not (await super().close()): return False nio = self._ethernet_adapter.get_nio(0) @@ -95,15 +93,14 @@ class VPCSVM(BaseNode): self.manager.port_manager.release_udp_port(self._local_udp_tunnel[1].lport, self._project) self._local_udp_tunnel = None - yield from self._stop_ubridge() + await self._stop_ubridge() if self.is_running(): self._terminate_process() return True - @asyncio.coroutine - def _check_requirements(self): + async def _check_requirements(self): """ Check if VPCS is available with the correct version. """ @@ -121,7 +118,7 @@ class VPCSVM(BaseNode): if not os.access(path, os.X_OK): raise VPCSError("VPCS program '{}' is not executable".format(path)) - yield from self._check_vpcs_version() + await self._check_vpcs_version() def __json__(self): @@ -130,7 +127,7 @@ class VPCSVM(BaseNode): "node_directory": self.working_path, "status": self.status, "console": self._console, - "console_type": "telnet", + "console_type": self._console_type, "project_id": self.project.id, "command_line": self.command_line} @@ -141,12 +138,10 @@ class VPCSVM(BaseNode): :returns: path to VPCS """ - search_path = self._manager.config.get_section_config("VPCS").get("vpcs_path", "vpcs") - path = shutil.which(search_path) - # shutil.which return None if the path doesn't exists - if not path: - return search_path - return path + vpcs_path = self._manager.config.get_section_config("VPCS").get("vpcs_path", "vpcs") + if not os.path.isabs(vpcs_path): + vpcs_path = shutil.which(vpcs_path) + return vpcs_path @BaseNode.name.setter def name(self, new_name): @@ -200,14 +195,13 @@ class VPCSVM(BaseNode): except OSError as e: raise VPCSError('Cannot write the startup script file "{}": {}'.format(startup_script_path, e)) - @asyncio.coroutine - def _check_vpcs_version(self): + async def _check_vpcs_version(self): """ Checks if the VPCS executable version is >= 0.8b or == 0.6.1. """ try: - output = yield from subprocess_check_output(self._vpcs_path(), "-v", cwd=self.working_dir) - match = re.search("Welcome to Virtual PC Simulator, version ([0-9a-z\.]+)", output) + output = await subprocess_check_output(self._vpcs_path(), "-v", cwd=self.working_dir) + match = re.search(r"Welcome to Virtual PC Simulator, version ([0-9a-z\.]+)", output) if match: version = match.group(1) self._vpcs_version = parse_version(version) @@ -218,13 +212,12 @@ class VPCSVM(BaseNode): except (OSError, subprocess.SubprocessError) as e: raise VPCSError("Error while looking for the VPCS version: {}".format(e)) - @asyncio.coroutine - def start(self): + async def start(self): """ Starts the VPCS process. """ - yield from self._check_requirements() + await self._check_requirements() if not self.is_running(): nio = self._ethernet_adapter.get_nio(0) command = self._build_command() @@ -237,18 +230,18 @@ class VPCSVM(BaseNode): flags = subprocess.CREATE_NEW_PROCESS_GROUP with open(self._vpcs_stdout_file, "w", encoding="utf-8") as fd: self.command_line = ' '.join(command) - self._process = yield from asyncio.create_subprocess_exec(*command, + self._process = await asyncio.create_subprocess_exec(*command, stdout=fd, stderr=subprocess.STDOUT, cwd=self.working_dir, creationflags=flags) monitor_process(self._process, self._termination_callback) - yield from self._start_ubridge() + await self._start_ubridge() if nio: - yield from self.add_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) + await self.add_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) - yield from self.start_wrap_console() + await self.start_wrap_console() log.info("VPCS instance {} started PID={}".format(self.name, self._process.pid)) self._started = True @@ -264,6 +257,7 @@ class VPCSVM(BaseNode): :param returncode: Process returncode """ + if self._started: log.info("VPCS process has stopped, return code: %d", returncode) self._started = False @@ -272,18 +266,17 @@ class VPCSVM(BaseNode): if returncode != 0: self.project.emit("log.error", {"message": "VPCS process has stopped, return code: {}\n{}".format(returncode, self.read_vpcs_stdout())}) - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops the VPCS process. """ - yield from self._stop_ubridge() + await self._stop_ubridge() if self.is_running(): self._terminate_process() if self._process.returncode is None: try: - yield from wait_for_process_termination(self._process, timeout=3) + await wait_for_process_termination(self._process, timeout=3) except asyncio.TimeoutError: if self._process.returncode is None: try: @@ -291,20 +284,19 @@ class VPCSVM(BaseNode): except OSError as e: log.error("Cannot stop the VPCS process: {}".format(e)) if self._process.returncode is None: - log.warn('VPCS VM "{}" with PID={} is still running'.format(self._name, self._process.pid)) + log.warning('VPCS VM "{}" with PID={} is still running'.format(self._name, self._process.pid)) self._process = None self._started = False - yield from super().stop() + await super().stop() - @asyncio.coroutine - def reload(self): + async def reload(self): """ Reloads the VPCS process (stop & start). """ - yield from self.stop() - yield from self.start() + await self.stop() + await self.start() def _terminate_process(self): """ @@ -313,7 +305,10 @@ class VPCSVM(BaseNode): log.info("Stopping VPCS instance {} PID={}".format(self.name, self._process.pid)) if sys.platform.startswith("win32"): - self._process.send_signal(signal.CTRL_BREAK_EVENT) + try: + self._process.send_signal(signal.CTRL_BREAK_EVENT) + except (SystemError, OSError): + pass else: try: self._process.terminate() @@ -333,7 +328,7 @@ class VPCSVM(BaseNode): with open(self._vpcs_stdout_file, "rb") as file: output = file.read().decode("utf-8", errors="replace") except OSError as e: - log.warn("Could not read {}: {}".format(self._vpcs_stdout_file, e)) + log.warning("Could not read {}: {}".format(self._vpcs_stdout_file, e)) return output def is_running(self): @@ -347,8 +342,20 @@ class VPCSVM(BaseNode): return True return False - @asyncio.coroutine - def port_add_nio_binding(self, port_number, nio): + @BaseNode.console_type.setter + def console_type(self, new_console_type): + """ + Sets the console type for this VPCS VM. + + :param new_console_type: console type (string) + """ + + if self.is_running() and self.console_type != new_console_type: + raise VPCSError('"{name}" must be stopped to change the console type to {new_console_type}'.format(name=self._name, new_console_type=new_console_type)) + + super(VPCSVM, VPCSVM).console_type.__set__(self, new_console_type) + + async def port_add_nio_binding(self, port_number, nio): """ Adds a port NIO binding. @@ -357,11 +364,11 @@ class VPCSVM(BaseNode): """ if not self._ethernet_adapter.port_exists(port_number): - raise VPCSError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter, + raise VPCSError("Port {port_number} doesn't exist on adapter {adapter}".format(adapter=self._ethernet_adapter, port_number=port_number)) if self.is_running(): - yield from self.add_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) + await self.add_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) self._ethernet_adapter.add_nio(port_number, nio) log.info('VPCS "{name}" [{id}]: {nio} added to port {port_number}'.format(name=self._name, @@ -371,16 +378,21 @@ class VPCSVM(BaseNode): return nio - @asyncio.coroutine - def port_update_nio_binding(self, port_number, nio): + async def port_update_nio_binding(self, port_number, nio): + """ + Updates a port NIO binding. + + :param port_number: port number + :param nio: NIO instance to update on the slot/port + """ + if not self._ethernet_adapter.port_exists(port_number): - raise VPCSError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter, + raise VPCSError("Port {port_number} doesn't exist on adapter {adapter}".format(adapter=self._ethernet_adapter, port_number=port_number)) if self.is_running(): - yield from self.update_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) + await self.update_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) - @asyncio.coroutine - def port_remove_nio_binding(self, port_number): + async def port_remove_nio_binding(self, port_number): """ Removes a port NIO binding. @@ -390,11 +402,12 @@ class VPCSVM(BaseNode): """ if not self._ethernet_adapter.port_exists(port_number): - raise VPCSError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter, + raise VPCSError("Port {port_number} doesn't exist on adapter {adapter}".format(adapter=self._ethernet_adapter, port_number=port_number)) + await self.stop_capture(port_number) if self.is_running(): - yield from self._ubridge_send("bridge delete {name}".format(name="VPCS-{}".format(self._id))) + await self._ubridge_send("bridge delete {name}".format(name="VPCS-{}".format(self._id))) nio = self._ethernet_adapter.get_nio(port_number) if isinstance(nio, NIOUDP): @@ -407,8 +420,24 @@ class VPCSVM(BaseNode): port_number=port_number)) return nio - @asyncio.coroutine - def start_capture(self, port_number, output_file): + def get_nio(self, port_number): + """ + Gets a port NIO binding. + + :param port_number: port number + + :returns: NIO instance + """ + + if not self._ethernet_adapter.port_exists(port_number): + raise VPCSError("Port {port_number} doesn't exist on adapter {adapter}".format(adapter=self._ethernet_adapter, + port_number=port_number)) + nio = self._ethernet_adapter.get_nio(port_number) + if not nio: + raise VPCSError("Port {} is not connected".format(port_number)) + return nio + + async def start_capture(self, port_number, output_file): """ Starts a packet capture. @@ -416,49 +445,33 @@ class VPCSVM(BaseNode): :param output_file: PCAP destination file for the capture """ - if not self._ethernet_adapter.port_exists(port_number): - raise VPCSError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter, - port_number=port_number)) - - nio = self._ethernet_adapter.get_nio(0) - - if not nio: - raise VPCSError("Port {} is not connected".format(port_number)) - + nio = self.get_nio(port_number) if nio.capturing: - raise VPCSError("Packet capture is already activated on port {port_number}".format(port_number=port_number)) - - nio.startPacketCapture(output_file) + raise VPCSError("Packet capture is already active on port {port_number}".format(port_number=port_number)) + nio.start_packet_capture(output_file) if self.ubridge: - yield from self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name="VPCS-{}".format(self._id), + await self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name="VPCS-{}".format(self._id), output_file=output_file)) log.info("VPCS '{name}' [{id}]: starting packet capture on port {port_number}".format(name=self.name, id=self.id, port_number=port_number)) - @asyncio.coroutine - def stop_capture(self, port_number): + async def stop_capture(self, port_number): """ Stops a packet capture. :param port_number: port number """ - if not self._ethernet_adapter.port_exists(port_number): - raise VPCSError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter, - port_number=port_number)) - - nio = self._ethernet_adapter.get_nio(0) - - if not nio: - raise VPCSError("Port {} is not connected".format(port_number)) - - nio.stopPacketCapture() + nio = self.get_nio(port_number) + if not nio.capturing: + return + nio.stop_packet_capture() if self.ubridge: - yield from self._ubridge_send('bridge stop_capture {name}'.format(name="VPCS-{}".format(self._id))) + await self._ubridge_send('bridge stop_capture {name}'.format(name="VPCS-{}".format(self._id))) log.info("VPCS '{name}' [{id}]: stopping packet capture on port {port_number}".format(name=self.name, id=self.id, @@ -508,28 +521,20 @@ class VPCSVM(BaseNode): if self._vpcs_version >= parse_version("0.8b"): command.extend(["-R"]) # disable the relay feature of VPCS (starting with VPCS 0.8) else: - log.warn("The VPCS relay feature could not be disabled because the VPCS version is below 0.8b") + log.warning("The VPCS relay feature could not be disabled because the VPCS version is below 0.8b") # use the local UDP tunnel to uBridge instead if not self._local_udp_tunnel: self._local_udp_tunnel = self._create_local_udp_tunnel() nio = self._local_udp_tunnel[0] - if nio: - - if isinstance(nio, NIOUDP): - # UDP tunnel - command.extend(["-s", str(nio.lport)]) # source UDP port - command.extend(["-c", str(nio.rport)]) # destination UDP port - try: - command.extend(["-t", socket.gethostbyname(nio.rhost)]) # destination host, we need to resolve the hostname because VPCS doesn't support it - except socket.gaierror as e: - raise VPCSError("Can't resolve hostname {}".format(nio.rhost)) - - elif isinstance(nio, NIOTAP): - # FIXME: remove old code - # TAP interface - command.extend(["-e"]) - command.extend(["-d", nio.tap_device]) + if nio and isinstance(nio, NIOUDP): + # UDP tunnel + command.extend(["-s", str(nio.lport)]) # source UDP port + command.extend(["-c", str(nio.rport)]) # destination UDP port + try: + command.extend(["-t", socket.gethostbyname(nio.rhost)]) # destination host, we need to resolve the hostname because VPCS doesn't support it + except socket.gaierror as e: + raise VPCSError("Can't resolve hostname {}".format(nio.rhost)) if self.script_file: command.extend([os.path.basename(self.script_file)]) diff --git a/gns3server/config.py b/gns3server/config.py index d15d32f0..07ad9ae2 100644 --- a/gns3server/config.py +++ b/gns3server/config.py @@ -21,9 +21,10 @@ Reads the configuration file and store the settings for the controller & compute import sys import os +import shutil import configparser -import asyncio +from .version import __version_info__ from .utils.file_watcher import FileWatcher import logging @@ -52,9 +53,10 @@ class Config: self._watched_files = {} self._watch_callback = [] - if sys.platform.startswith("win"): + appname = "GNS3" + version = "{}.{}".format(__version_info__[0], __version_info__[1]) - appname = "GNS3" + if sys.platform.startswith("win"): # On windows, the configuration file location can be one of the following: # 1: %APPDATA%/GNS3/gns3_server.ini @@ -67,16 +69,28 @@ class Config: common_appdata = os.path.expandvars("%COMMON_APPDATA%") if self._profile: - user_dir = os.path.join(appdata, appname, "profiles", self._profile) + legacy_user_dir = os.path.join(appdata, appname, "profiles", self._profile) + versioned_user_dir = legacy_user_dir else: - user_dir = os.path.join(appdata, appname) + legacy_user_dir = os.path.join(appdata, appname) + versioned_user_dir = os.path.join(appdata, appname, version) + + server_filename = "gns3_server.ini" + controller_filename = "gns3_controller.ini" + + # move gns3_controller.conf to gns3_controller.ini (file was renamed in 2.2.0 on Windows) + old_controller_filename = os.path.join(legacy_user_dir, "gns3_controller.conf") + if os.path.exists(old_controller_filename): + try: + shutil.copyfile(old_controller_filename, os.path.join(legacy_user_dir, controller_filename)) + except OSError as e: + log.error("Cannot move old controller configuration file: {}".format(e)) - filename = "gns3_server.ini" if self._files is None and not hasattr(sys, "_called_from_test"): - self._files = [os.path.join(os.getcwd(), filename), - os.path.join(user_dir, filename), + self._files = [os.path.join(os.getcwd(), server_filename), + os.path.join(versioned_user_dir, server_filename), os.path.join(appdata, appname + ".ini"), - os.path.join(common_appdata, appname, filename), + os.path.join(common_appdata, appname, server_filename), os.path.join(common_appdata, appname + ".ini")] else: @@ -87,28 +101,49 @@ class Config: # 4: /etc/xdg/GNS3.conf # 5: gns3_server.conf in the current working directory - appname = "GNS3" home = os.path.expanduser("~") - filename = "gns3_server.conf" + server_filename = "gns3_server.conf" + controller_filename = "gns3_controller.conf" if self._profile: - user_dir = os.path.join(home, ".config", appname, "profiles", self._profile) + legacy_user_dir = os.path.join(home, ".config", appname, "profiles", self._profile) + versioned_user_dir = legacy_user_dir else: - user_dir = os.path.join(home, ".config", appname) + legacy_user_dir = os.path.join(home, ".config", appname) + versioned_user_dir = os.path.join(home, ".config", appname, version) if self._files is None and not hasattr(sys, "_called_from_test"): - self._files = [os.path.join(os.getcwd(), filename), - os.path.join(user_dir, filename), + self._files = [os.path.join(os.getcwd(), server_filename), + os.path.join(versioned_user_dir, server_filename), os.path.join(home, ".config", appname + ".conf"), - os.path.join("/etc/gns3", filename), - os.path.join("/etc/xdg", appname, filename), + os.path.join("/etc/gns3", server_filename), + os.path.join("/etc/xdg", appname, server_filename), os.path.join("/etc/xdg", appname + ".conf")] if self._files is None: self._files = [] if self._main_config_file is None: - self._main_config_file = os.path.join(user_dir, filename) + + # TODO: migrate versioned config file from a previous version of GNS3 (for instance 2.2 -> 2.3) + support profiles + # migrate post version 2.2.0 config files if they exist + os.makedirs(versioned_user_dir, exist_ok=True) + try: + # migrate the server config file + old_server_config = os.path.join(legacy_user_dir, server_filename) + new_server_config = os.path.join(versioned_user_dir, server_filename) + if not os.path.exists(new_server_config) and os.path.exists(old_server_config): + shutil.copyfile(old_server_config, new_server_config) + + # migrate the controller config file + old_controller_config = os.path.join(legacy_user_dir, controller_filename) + new_controller_config = os.path.join(versioned_user_dir, controller_filename) + if not os.path.exists(new_controller_config) and os.path.exists(old_controller_config): + shutil.copyfile(old_controller_config, os.path.join(versioned_user_dir, new_controller_config)) + except OSError as e: + log.error("Cannot migrate old config files: {}".format(e)) + + self._main_config_file = os.path.join(versioned_user_dir, server_filename) for file in self._files: if os.path.exists(file): self._main_config_file = file @@ -132,8 +167,18 @@ class Config: @property def config_dir(self): + return os.path.dirname(self._main_config_file) + @property + def controller_config(self): + + if sys.platform.startswith("win"): + controller_config_filename = "gns3_controller.ini" + else: + controller_config_filename = "gns3_controller.conf" + return os.path.join(self.config_dir, controller_config_filename) + def clear(self): """Restart with a clean config""" self._config = configparser.RawConfigParser() diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index 5c914f57..e1c887c6 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -21,13 +21,14 @@ import json import uuid import socket import shutil -import asyncio import aiohttp from ..config import Config from .project import Project +from .template import Template from .appliance import Appliance -from .appliance_template import ApplianceTemplate +from .appliance_manager import ApplianceManager +from .template_manager import TemplateManager from .compute import Compute, ComputeError from .notification import Notification from .symbols import Symbols @@ -42,132 +43,35 @@ log = logging.getLogger(__name__) class Controller: - """The controller is responsible to manage one or more compute servers""" + """ + The controller is responsible to manage one or more computes. + """ def __init__(self): self._computes = {} self._projects = {} - - # Store settings shared by the different GUI will be replaced - # by dedicated API later - self._settings = {} - self._notification = Notification(self) self.gns3vm = GNS3VM(self) self.symbols = Symbols() - - # Store settings shared by the different GUI will be replace by dedicated API later - self._settings = None - self._appliances = {} - self._appliance_templates = {} - - self._config_file = os.path.join(Config.instance().config_dir, "gns3_controller.conf") + self._appliance_manager = ApplianceManager() + self._template_manager = TemplateManager() + self._iou_license_settings = {"iourc_content": "", + "license_check": True} + self._config_loaded = False + self._config_file = Config.instance().controller_config log.info("Load controller configuration file {}".format(self._config_file)) - def load_appliances(self): - self._appliance_templates = {} - for directory, builtin in ( - (get_resource('appliances'), True,), (self.appliances_path(), False,) - ): - if os.path.isdir(directory): - for file in os.listdir(directory): - if not file.endswith('.gns3a') and not file.endswith('.gns3appliance'): - continue - path = os.path.join(directory, file) - appliance_id = uuid.uuid3(uuid.NAMESPACE_URL, path) # Generate the UUID from path to avoid change between reboots - try: - with open(path, 'r', encoding='utf-8') as f: - appliance = ApplianceTemplate(appliance_id, json.load(f), builtin=builtin) - appliance.__json__() # Check if loaded without error - if appliance.status != 'broken': - self._appliance_templates[appliance.id] = appliance - except (ValueError, OSError, KeyError) as e: - log.warning("Cannot load appliance template file '%s': %s", path, str(e)) - continue + async def start(self): - self._appliances = {} - vms = [] - for vm in self._settings.get("Qemu", {}).get("vms", []): - vm["node_type"] = "qemu" - vms.append(vm) - for vm in self._settings.get("IOU", {}).get("devices", []): - vm["node_type"] = "iou" - vms.append(vm) - for vm in self._settings.get("Docker", {}).get("containers", []): - vm["node_type"] = "docker" - vms.append(vm) - for vm in self._settings.get("Builtin", {}).get("cloud_nodes", []): - vm["node_type"] = "cloud" - vms.append(vm) - for vm in self._settings.get("Builtin", {}).get("ethernet_switches", []): - vm["node_type"] = "ethernet_switch" - vms.append(vm) - for vm in self._settings.get("Builtin", {}).get("ethernet_hubs", []): - vm["node_type"] = "ethernet_hub" - vms.append(vm) - for vm in self._settings.get("Dynamips", {}).get("routers", []): - vm["node_type"] = "dynamips" - vms.append(vm) - for vm in self._settings.get("VMware", {}).get("vms", []): - vm["node_type"] = "vmware" - vms.append(vm) - for vm in self._settings.get("VirtualBox", {}).get("vms", []): - vm["node_type"] = "virtualbox" - vms.append(vm) - for vm in self._settings.get("VPCS", {}).get("nodes", []): - vm["node_type"] = "vpcs" - vms.append(vm) - - for vm in vms: - # remove deprecated properties - for prop in vm.copy(): - if prop in ["enable_remote_console", "use_ubridge"]: - del vm[prop] - - # remove deprecated default_symbol and hover_symbol - # and set symbol if not present - deprecated = ["default_symbol", "hover_symbol"] - if len([prop for prop in vm.keys() if prop in deprecated]) > 0: - if "default_symbol" in vm.keys(): - del vm["default_symbol"] - if "hover_symbol" in vm.keys(): - del vm["hover_symbol"] - - if "symbol" not in vm.keys(): - vm["symbol"] = ":/symbols/computer.svg" - - vm.setdefault("appliance_id", str(uuid.uuid4())) - try: - appliance = Appliance(vm["appliance_id"], vm) - appliance.__json__() # Check if loaded without error - self._appliances[appliance.id] = appliance - except KeyError as e: - # appliance data is not complete (missing name or type) - log.warning("Cannot load appliance template {} ('{}'): missing key {}".format(vm["appliance_id"], vm.get("name", "unknown"), e)) - continue - - # Add builtins - builtins = [] - builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "cloud"), {"node_type": "cloud", "name": "Cloud", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True)) - builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "nat"), {"node_type": "nat", "name": "NAT", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True)) - builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "vpcs"), {"node_type": "vpcs", "name": "VPCS", "default_name_format": "PC-{0}", "category": 2, "symbol": ":/symbols/vpcs_guest.svg", "properties": {"base_script_file": "vpcs_base_config.txt"}}, builtin=True)) - builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_switch"), {"node_type": "ethernet_switch", "name": "Ethernet switch", "category": 1, "symbol": ":/symbols/ethernet_switch.svg"}, builtin=True)) - builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_hub"), {"node_type": "ethernet_hub", "name": "Ethernet hub", "category": 1, "symbol": ":/symbols/hub.svg"}, builtin=True)) - builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "frame_relay_switch"), {"node_type": "frame_relay_switch", "name": "Frame Relay switch", "category": 1, "symbol": ":/symbols/frame_relay_switch.svg"}, builtin=True)) - builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "atm_switch"), {"node_type": "atm_switch", "name": "ATM switch", "category": 1, "symbol": ":/symbols/atm_switch.svg"}, builtin=True)) - for b in builtins: - self._appliances[b.id] = b - - @asyncio.coroutine - def start(self): - log.info("Start controller") + log.info("Controller is starting") self.load_base_files() server_config = Config.instance().get_section_config("Server") Config.instance().listen_for_config_changes(self._update_config) host = server_config.get("host", "localhost") + port = server_config.getint("port", 3080) - # If console_host is 0.0.0.0 client will use the ip they use - # to connect to the controller + # clients will use the IP they use to connect to + # the controller if console_host is 0.0.0.0 console_host = host if host == "0.0.0.0": host = "127.0.0.1" @@ -176,54 +80,55 @@ class Controller: if name == "gns3vm": name = "Main server" - computes = yield from self._load_controller_settings() + computes = await self._load_controller_settings() try: - self._local_server = yield from self.add_compute(compute_id="local", - name=name, - protocol=server_config.get("protocol", "http"), - host=host, - console_host=console_host, - port=server_config.getint("port", 3080), - user=server_config.get("user", ""), - password=server_config.get("password", ""), - force=True) - except aiohttp.web_exceptions.HTTPConflict as e: - log.fatal("Can't access to the local server, make sure anything else is not running on the same port") + self._local_server = await self.add_compute(compute_id="local", + name=name, + protocol=server_config.get("protocol", "http"), + host=host, + console_host=console_host, + port=port, + user=server_config.get("user", ""), + password=server_config.get("password", ""), + force=True) + except aiohttp.web.HTTPConflict: + log.fatal("Cannot access to the local server, make sure something else is not running on the TCP port {}".format(port)) sys.exit(1) for c in computes: try: - yield from self.add_compute(**c) - except (aiohttp.web_exceptions.HTTPConflict, KeyError): + await self.add_compute(**c) + except (aiohttp.web.HTTPError, KeyError): pass # Skip not available servers at loading - yield from self.load_projects() + await self.load_projects() try: - yield from self.gns3vm.auto_start_vm() + await self.gns3vm.auto_start_vm() except GNS3VMError as e: - log.warn(str(e)) - yield from self._project_auto_open() + log.warning(str(e)) + await self._project_auto_open() def _update_config(self): """ - Call this when the server configuration file - change + Call this when the server configuration file changes. """ + if self._local_server: server_config = Config.instance().get_section_config("Server") self._local_server.user = server_config.get("user") self._local_server.password = server_config.get("password") - @asyncio.coroutine - def stop(self): - log.info("Stop controller") + async def stop(self): + + log.info("Controller is Stopping") for project in self._projects.values(): - yield from project.close() + await project.close() for compute in self._computes.values(): try: - yield from compute.close() + await compute.close() # We don't care if a compute is down at this step - except (ComputeError, aiohttp.web_exceptions.HTTPError, OSError): + except (ComputeError, aiohttp.web.HTTPError, OSError): pass - yield from self.gns3vm.exit_vm() + await self.gns3vm.exit_vm() + #self.save() self._computes = {} self._projects = {} @@ -231,65 +136,73 @@ class Controller: """ Save the controller configuration on disk """ - # We don't save during the loading otherwise we could lost stuff - if self._settings is None: - return - data = { - "computes": [], - "settings": self._settings, - "gns3vm": self.gns3vm.__json__(), - "version": __version__ - } - for c in self._computes.values(): - if c.id != "local" and c.id != "vm": - data["computes"].append({ - "host": c.host, - "name": c.name, - "port": c.port, - "protocol": c.protocol, - "user": c.user, - "password": c.password, - "compute_id": c.id - }) + if self._config_loaded is False: + return + + controller_settings = {"computes": [], + "templates": [], + "gns3vm": self.gns3vm.__json__(), + "iou_license": self._iou_license_settings, + "appliances_etag": self._appliance_manager.appliances_etag, + "version": __version__} + + for template in self._template_manager.templates.values(): + if not template.builtin: + controller_settings["templates"].append(template.__json__()) + + for compute in self._computes.values(): + if compute.id != "local" and compute.id != "vm": + controller_settings["computes"].append({"host": compute.host, + "name": compute.name, + "port": compute.port, + "protocol": compute.protocol, + "user": compute.user, + "password": compute.password, + "compute_id": compute.id}) + try: os.makedirs(os.path.dirname(self._config_file), exist_ok=True) with open(self._config_file, 'w+') as f: - json.dump(data, f, indent=4) + json.dump(controller_settings, f, indent=4) except OSError as e: - log.error("Can't write the configuration {}: {}".format(self._config_file, str(e))) + log.error("Cannot write controller configuration file '{}': {}".format(self._config_file, e)) - @asyncio.coroutine - def _load_controller_settings(self): + async def _load_controller_settings(self): """ Reload the controller configuration from disk """ + try: if not os.path.exists(self._config_file): - yield from self._import_gns3_gui_conf() + await self._import_gns3_gui_conf() + self._config_loaded = True self.save() with open(self._config_file) as f: - data = json.load(f) + controller_settings = json.load(f) except (OSError, ValueError) as e: - log.critical("Cannot load %s: %s", self._config_file, str(e)) - self._settings = {} + log.critical("Cannot load configuration file '{}': {}".format(self._config_file, e)) return [] - if "settings" in data and data["settings"] is not None: - self._settings = data["settings"] - else: - self._settings = {} - if "gns3vm" in data: - self.gns3vm.settings = data["gns3vm"] + # load GNS3 VM settings + if "gns3vm" in controller_settings: + self.gns3vm.settings = controller_settings["gns3vm"] - self.load_appliances() - return data.get("computes", []) + # load the IOU license settings + if "iou_license" in controller_settings: + self._iou_license_settings = controller_settings["iou_license"] - @asyncio.coroutine - def load_projects(self): + self._appliance_manager.appliances_etag = controller_settings.get("appliances_etag") + self._appliance_manager.load_appliances() + self._template_manager.load_templates(controller_settings.get("templates")) + self._config_loaded = True + return controller_settings.get("computes", []) + + async def load_projects(self): """ Preload the list of projects from disk """ + server_config = Config.instance().get_section_config("Server") projects_path = os.path.expanduser(server_config.get("projects_path", "~/GNS3/projects")) os.makedirs(projects_path, exist_ok=True) @@ -300,8 +213,8 @@ class Controller: for file in os.listdir(project_dir): if file.endswith(".gns3"): try: - yield from self.load_project(os.path.join(project_dir, file), load=False) - except (aiohttp.web_exceptions.HTTPConflict, NotImplementedError): + await self.load_project(os.path.join(project_dir, file), load=False) + except (aiohttp.web.HTTPConflict, NotImplementedError): pass # Skip not compatible projects except OSError as e: log.error(str(e)) @@ -311,6 +224,7 @@ class Controller: At startup we copy base file to the user location to allow them to customize it """ + dst_path = self.configs_path() src_path = get_resource('configs') try: @@ -324,6 +238,7 @@ class Controller: """ Get the image storage directory """ + server_config = Config.instance().get_section_config("Server") images_path = os.path.expanduser(server_config.get("images_path", "~/GNS3/projects")) os.makedirs(images_path, exist_ok=True) @@ -333,40 +248,30 @@ class Controller: """ Get the configs storage directory """ + server_config = Config.instance().get_section_config("Server") images_path = os.path.expanduser(server_config.get("configs_path", "~/GNS3/projects")) os.makedirs(images_path, exist_ok=True) return images_path - def appliances_path(self): - """ - Get the image storage directory - """ - server_config = Config.instance().get_section_config("Server") - appliances_path = os.path.expanduser(server_config.get("appliances_path", "~/GNS3/projects")) - os.makedirs(appliances_path, exist_ok=True) - return appliances_path - - @asyncio.coroutine - def _import_gns3_gui_conf(self): + async def _import_gns3_gui_conf(self): """ Import old config from GNS3 GUI """ + config_file = os.path.join(os.path.dirname(self._config_file), "gns3_gui.conf") if os.path.exists(config_file): with open(config_file) as f: - data = json.load(f) - server_settings = data.get("Servers", {}) + settings = json.load(f) + server_settings = settings.get("Servers", {}) for remote in server_settings.get("remote_servers", []): try: - yield from self.add_compute( - host=remote.get("host", "localhost"), - port=remote.get("port", 3080), - protocol=remote.get("protocol", "http"), - name=remote.get("url"), - user=remote.get("user"), - password=remote.get("password") - ) + await self.add_compute(host=remote.get("host", "localhost"), + port=remote.get("port", 3080), + protocol=remote.get("protocol", "http"), + name=remote.get("url"), + user=remote.get("user"), + password=remote.get("password")) except aiohttp.web.HTTPConflict: pass # if the server is broken we skip it if "vm" in server_settings: @@ -397,29 +302,75 @@ class Controller: "headless": vm_settings.get("headless", False), "vmname": vmname } - self._settings = {} - @property - def settings(self): + vms = [] + for vm in settings.get("Qemu", {}).get("vms", []): + vm["template_type"] = "qemu" + vms.append(vm) + for vm in settings.get("IOU", {}).get("devices", []): + vm["template_type"] = "iou" + vms.append(vm) + for vm in settings.get("Docker", {}).get("containers", []): + vm["template_type"] = "docker" + vms.append(vm) + for vm in settings.get("Builtin", {}).get("cloud_nodes", []): + vm["template_type"] = "cloud" + vms.append(vm) + for vm in settings.get("Builtin", {}).get("ethernet_switches", []): + vm["template_type"] = "ethernet_switch" + vms.append(vm) + for vm in settings.get("Builtin", {}).get("ethernet_hubs", []): + vm["template_type"] = "ethernet_hub" + vms.append(vm) + for vm in settings.get("Dynamips", {}).get("routers", []): + vm["template_type"] = "dynamips" + vms.append(vm) + for vm in settings.get("VMware", {}).get("vms", []): + vm["template_type"] = "vmware" + vms.append(vm) + for vm in settings.get("VirtualBox", {}).get("vms", []): + vm["template_type"] = "virtualbox" + vms.append(vm) + for vm in settings.get("VPCS", {}).get("nodes", []): + vm["template_type"] = "vpcs" + vms.append(vm) + for vm in settings.get("TraceNG", {}).get("nodes", []): + vm["template_type"] = "traceng" + vms.append(vm) + + for vm in vms: + # remove deprecated properties + for prop in vm.copy(): + if prop in ["enable_remote_console", "use_ubridge", "acpi_shutdown"]: + del vm[prop] + + # remove deprecated default_symbol and hover_symbol + # and set symbol if not present + deprecated = ["default_symbol", "hover_symbol"] + if len([prop for prop in vm.keys() if prop in deprecated]) > 0: + if "default_symbol" in vm.keys(): + del vm["default_symbol"] + if "hover_symbol" in vm.keys(): + del vm["hover_symbol"] + + if "symbol" not in vm.keys(): + vm["symbol"] = ":/symbols/computer.svg" + + vm.setdefault("template_id", str(uuid.uuid4())) + try: + template = Template(vm["template_id"], vm) + template.__json__() # Check if loaded without error + self.template_manager.templates[template.id] = template + except KeyError as e: + # template data is not complete (missing name or type) + log.warning("Cannot load template {} ('{}'): missing key {}".format(vm["template_id"], vm.get("name", "unknown"), e)) + continue + + async def add_compute(self, compute_id=None, name=None, force=False, connect=True, **kwargs): """ - Store settings shared by the different GUI will be replace by dedicated API later. Dictionnary - """ - return self._settings + Add a server to the dictionary of computes controlled by this controller - @settings.setter - def settings(self, val): - self._settings = val - self._settings["modification_uuid"] = str(uuid.uuid4()) # We add a modification id to the settings it's help the gui to detect changes - self.save() - self.load_appliances() - self.notification.emit("settings.updated", val) - - @asyncio.coroutine - def add_compute(self, compute_id=None, name=None, force=False, connect=True, **kwargs): - """ - Add a server to the dictionary of compute servers controlled by this controller - - :param compute_id: Compute server identifier + :param compute_id: Compute identifier :param name: Compute name :param force: True skip security check :param connect: True connect to the compute immediately @@ -445,74 +396,89 @@ class Controller: self._computes[compute.id] = compute self.save() if connect: - yield from compute.connect() - self.notification.emit("compute.created", compute.__json__()) + await compute.connect() + self.notification.controller_emit("compute.created", compute.__json__()) return compute else: if connect: - yield from self._computes[compute_id].connect() - self.notification.emit("compute.updated", self._computes[compute_id].__json__()) + await self._computes[compute_id].connect() + self.notification.controller_emit("compute.updated", self._computes[compute_id].__json__()) return self._computes[compute_id] - @asyncio.coroutine - def close_compute_projects(self, compute): + async def close_compute_projects(self, compute): """ Close projects running on a compute """ + for project in self._projects.values(): if compute in project.computes: - yield from project.close() + await project.close() - @asyncio.coroutine - def delete_compute(self, compute_id): + def compute_has_open_project(self, compute): + """ + Check is compute has a project opened. + + :returns: True if a project is open + """ + + for project in self._projects.values(): + if compute in project.computes and project.status == "opened": + return True + return False + + async def delete_compute(self, compute_id): """ Delete a compute node. Project using this compute will be close - :param compute_id: Compute server identifier + :param compute_id: Compute identifier """ + try: compute = self.get_compute(compute_id) except aiohttp.web.HTTPNotFound: return - yield from self.close_compute_projects(compute) - yield from compute.close() + await self.close_compute_projects(compute) + await compute.close() del self._computes[compute_id] self.save() - self.notification.emit("compute.deleted", compute.__json__()) + self.notification.controller_emit("compute.deleted", compute.__json__()) @property def notification(self): """ The notification system """ + return self._notification @property def computes(self): """ - :returns: The dictionary of compute server managed by this controller + :returns: The dictionary of computes managed by this controller """ + return self._computes def get_compute(self, compute_id): """ - Returns a compute server or raise a 404 error. + Returns a compute or raise a 404 error. """ + try: return self._computes[compute_id] except KeyError: if compute_id == "vm": - raise aiohttp.web.HTTPNotFound(text="You try to use a node on the GNS3 VM server but the GNS3 VM is not configured") + raise aiohttp.web.HTTPNotFound(text="Cannot use a node on the GNS3 VM server with the GNS3 VM not configured") raise aiohttp.web.HTTPNotFound(text="Compute ID {} doesn't exist".format(compute_id)) def has_compute(self, compute_id): """ Return True if the compute exist in the controller """ + return compute_id in self._computes - @asyncio.coroutine - def add_project(self, project_id=None, name=None, **kwargs): + async def add_project(self, project_id=None, name=None, path=None, **kwargs): """ Creates a project or returns an existing project @@ -520,12 +486,15 @@ class Controller: :param name: Project name :param kwargs: See the documentation of Project """ - if project_id not in self._projects: + if project_id not in self._projects: for project in self._projects.values(): if name and project.name == name: - raise aiohttp.web.HTTPConflict(text='Project name "{}" already exists'.format(name)) - project = Project(project_id=project_id, controller=self, name=name, **kwargs) + if path and path == project.path: + raise aiohttp.web.HTTPConflict(text='Project "{}" already exists in location "{}"'.format(name, path)) + else: + raise aiohttp.web.HTTPConflict(text='Project "{}" already exists'.format(name)) + project = Project(project_id=project_id, controller=self, name=name, path=path, **kwargs) self._projects[project.id] = project return self._projects[project.id] return self._projects[project_id] @@ -534,34 +503,36 @@ class Controller: """ Returns a project or raise a 404 error. """ + try: return self._projects[project_id] except KeyError: raise aiohttp.web.HTTPNotFound(text="Project ID {} doesn't exist".format(project_id)) - @asyncio.coroutine - def get_loaded_project(self, project_id): + async def get_loaded_project(self, project_id): """ Returns a project or raise a 404 error. If project is not finished to load wait for it """ + project = self.get_project(project_id) - yield from project.wait_loaded() + await project.wait_loaded() return project def remove_project(self, project): + if project.id in self._projects: del self._projects[project.id] - @asyncio.coroutine - def load_project(self, path, load=True): + async def load_project(self, path, load=True): """ Load a project from a .gns3 :param path: Path of the .gns3 :param load: Load the topology """ + topo_data = load_topology(path) topo_data.pop("topology") topo_data.pop("version") @@ -571,24 +542,25 @@ class Controller: if topo_data["project_id"] in self._projects: project = self._projects[topo_data["project_id"]] else: - project = yield from self.add_project(path=os.path.dirname(path), status="closed", filename=os.path.basename(path), **topo_data) + project = await self.add_project(path=os.path.dirname(path), status="closed", filename=os.path.basename(path), **topo_data) if load or project.auto_open: - yield from project.open() + await project.open() return project - @asyncio.coroutine - def _project_auto_open(self): + async def _project_auto_open(self): """ Auto open the project with auto open enable """ + for project in self._projects.values(): if project.auto_open: - yield from project.open() + await project.open() def get_free_project_name(self, base_name): """ Generate a free project name base on the base name """ + names = [p.name for p in self._projects.values()] if base_name not in names: return base_name @@ -610,23 +582,35 @@ class Controller: """ :returns: The dictionary of projects managed by GNS3 """ + return self._projects @property - def appliance_templates(self): + def appliance_manager(self): """ - :returns: The dictionary of appliances templates managed by GNS3 + :returns: Appliance Manager instance """ - return self._appliance_templates + + return self._appliance_manager @property - def appliances(self): + def template_manager(self): """ - :returns: The dictionary of appliances managed by GNS3 + :returns: Template Manager instance """ - return self._appliances + + return self._template_manager + + @property + def iou_license(self): + """ + :returns: The dictionary of IOU license settings + """ + + return self._iou_license_settings def projects_directory(self): + server_config = Config.instance().get_section_config("Server") return os.path.expanduser(server_config.get("projects_path", "~/GNS3/projects")) @@ -642,8 +626,7 @@ class Controller: Controller._instance = Controller() return Controller._instance - @asyncio.coroutine - def autoidlepc(self, compute_id, platform, image, ram): + async def autoidlepc(self, compute_id, platform, image, ram): """ Compute and IDLE PC value for an image @@ -652,14 +635,26 @@ class Controller: :param image: Image to use :param ram: amount of RAM to use """ + compute = self.get_compute(compute_id) for project in list(self._projects.values()): if project.name == "AUTOIDLEPC": - yield from project.delete() + await project.delete() self.remove_project(project) - project = yield from self.add_project(name="AUTOIDLEPC") - node = yield from project.add_node(compute, "AUTOIDLEPC", str(uuid.uuid4()), node_type="dynamips", platform=platform, image=image, ram=ram) - res = yield from node.dynamips_auto_idlepc() - yield from project.delete() + project = await self.add_project(name="AUTOIDLEPC") + node = await project.add_node(compute, "AUTOIDLEPC", str(uuid.uuid4()), node_type="dynamips", platform=platform, image=image, ram=ram) + res = await node.dynamips_auto_idlepc() + await project.delete() self.remove_project(project) return res + + async def compute_ports(self, compute_id): + """ + Get the ports used by a compute. + + :param compute_id: ID of the compute + """ + + compute = self.get_compute(compute_id) + response = await compute.get("/network/ports") + return response.json diff --git a/gns3server/controller/appliance.py b/gns3server/controller/appliance.py index 8b7b2995..aba9beb2 100644 --- a/gns3server/controller/appliance.py +++ b/gns3server/controller/appliance.py @@ -19,18 +19,9 @@ import copy import uuid -# Convert old GUI category to text category -ID_TO_CATEGORY = { - 3: "firewall", - 2: "guest", - 1: "switch", - 0: "router" -} - - class Appliance: - def __init__(self, appliance_id, data, builtin=False): + def __init__(self, appliance_id, data, builtin=True): if appliance_id is None: self._id = str(uuid.uuid4()) elif isinstance(appliance_id, uuid.UUID): @@ -38,56 +29,30 @@ class Appliance: else: self._id = appliance_id self._data = data.copy() + self._builtin = builtin if "appliance_id" in self._data: del self._data["appliance_id"] - # Version of the gui before 2.1 use linked_base - # and the server linked_clone - if "linked_base" in self._data: - linked_base = self._data.pop("linked_base") - if "linked_clone" not in self._data: - self._data["linked_clone"] = linked_base - if data["node_type"] == "iou" and "image" in data: - del self._data["image"] - self._builtin = builtin - @property def id(self): return self._id @property - def data(self): - return copy.deepcopy(self._data) + def status(self): + return self._data["status"] @property - def name(self): - return self._data["name"] + def symbol(self): + return self._data.get("symbol") - @property - def compute_id(self): - return self._data.get("server") - - @property - def builtin(self): - return self._builtin + @symbol.setter + def symbol(self, new_symbol): + self._data["symbol"] = new_symbol def __json__(self): """ Appliance data (a hash) """ - try: - category = ID_TO_CATEGORY[self._data["category"]] - except KeyError: - category = self._data["category"] - - return { - "appliance_id": self._id, - "node_type": self._data["node_type"], - "name": self._data["name"], - "default_name_format": self._data.get("default_name_format", "{name}-{0}"), - "category": category, - "symbol": self._data.get("symbol", ":/symbols/computer.svg"), - "compute_id": self.compute_id, - "builtin": self._builtin, - "platform": self._data.get("platform", None) - } + data = copy.deepcopy(self._data) + data["builtin"] = self._builtin + return data diff --git a/gns3server/controller/appliance_manager.py b/gns3server/controller/appliance_manager.py new file mode 100644 index 00000000..17c7fd30 --- /dev/null +++ b/gns3server/controller/appliance_manager.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 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 json +import uuid +import asyncio +import aiohttp + +from .appliance import Appliance +from ..config import Config +from ..utils.asyncio import locking +from ..utils.get_resource import get_resource + +import logging +log = logging.getLogger(__name__) + + +class ApplianceManager: + """ + Manages appliances + """ + + def __init__(self): + + self._appliances = {} + self._appliances_etag = None + + @property + def appliances_etag(self): + """ + :returns: ETag for downloaded appliances + """ + + return self._appliances_etag + + @appliances_etag.setter + def appliances_etag(self, etag): + """ + :param etag: ETag for downloaded appliances + """ + + self._appliances_etag = etag + + @property + def appliances(self): + """ + :returns: The dictionary of appliances managed by GNS3 + """ + + return self._appliances + + def appliances_path(self): + """ + Get the image storage directory + """ + + server_config = Config.instance().get_section_config("Server") + appliances_path = os.path.expanduser(server_config.get("appliances_path", "~/GNS3/projects")) + os.makedirs(appliances_path, exist_ok=True) + return appliances_path + + def load_appliances(self, symbol_theme="Classic"): + """ + Loads appliance files from disk. + """ + + self._appliances = {} + for directory, builtin in ((get_resource('appliances'), True,), (self.appliances_path(), False,)): + if directory and os.path.isdir(directory): + for file in os.listdir(directory): + if not file.endswith('.gns3a') and not file.endswith('.gns3appliance'): + continue + path = os.path.join(directory, file) + appliance_id = uuid.uuid3(uuid.NAMESPACE_URL, path) # Generate UUID from path to avoid change between reboots + try: + with open(path, 'r', encoding='utf-8') as f: + appliance = Appliance(appliance_id, json.load(f), builtin=builtin) + json_data = appliance.__json__() # Check if loaded without error + if appliance.status != 'broken': + self._appliances[appliance.id] = appliance + if not appliance.symbol or appliance.symbol.startswith(":/symbols/"): + # apply a default symbol if the appliance has none or a default symbol + default_symbol = self._get_default_symbol(json_data, symbol_theme) + if default_symbol: + appliance.symbol = default_symbol + except (ValueError, OSError, KeyError) as e: + log.warning("Cannot load appliance file '%s': %s", path, str(e)) + continue + + def _get_default_symbol(self, appliance, symbol_theme): + """ + Returns the default symbol for a given appliance. + """ + + from . import Controller + controller = Controller.instance() + category = appliance["category"] + if category == "guest": + if "docker" in appliance: + return controller.symbols.get_default_symbol("docker_guest", symbol_theme) + elif "qemu" in appliance: + return controller.symbols.get_default_symbol("qemu_guest", symbol_theme) + return controller.symbols.get_default_symbol(category, symbol_theme) + + async def download_custom_symbols(self): + """ + Download custom appliance symbols from our GitHub registry repository. + """ + + from . import Controller + symbol_dir = Controller.instance().symbols.symbols_path() + self.load_appliances() + for appliance in self._appliances.values(): + symbol = appliance.symbol + if symbol and not symbol.startswith(":/symbols/"): + destination_path = os.path.join(symbol_dir, symbol) + if not os.path.exists(destination_path): + await self._download_symbol(symbol, destination_path) + + # refresh the symbol cache + Controller.instance().symbols.list() + + async def _download_symbol(self, symbol, destination_path): + """ + Download a custom appliance symbol from our GitHub registry repository. + """ + + symbol_url = "https://raw.githubusercontent.com/GNS3/gns3-registry/master/symbols/{}".format(symbol) + async with aiohttp.ClientSession() as session: + async with session.get(symbol_url) as response: + if response.status != 200: + log.warning("Could not retrieve appliance symbol {} from GitHub due to HTTP error code {}".format(symbol, response.status)) + else: + try: + symbol_data = await response.read() + log.info("Saving {} symbol to {}".format(symbol, destination_path)) + with open(destination_path, 'wb') as f: + f.write(symbol_data) + except asyncio.TimeoutError: + log.warning("Timeout while downloading '{}'".format(symbol_url)) + except OSError as e: + log.warning("Could not write appliance symbol '{}': {}".format(destination_path, e)) + + @locking + async def download_appliances(self): + """ + Downloads appliance files from GitHub registry repository. + """ + + try: + headers = {} + if self._appliances_etag: + log.info("Checking if appliances are up-to-date (ETag {})".format(self._appliances_etag)) + headers["If-None-Match"] = self._appliances_etag + async with aiohttp.ClientSession() as session: + async with session.get('https://api.github.com/repos/GNS3/gns3-registry/contents/appliances', headers=headers) as response: + if response.status == 304: + log.info("Appliances are already up-to-date (ETag {})".format(self._appliances_etag)) + return + elif response.status != 200: + raise aiohttp.web.HTTPConflict(text="Could not retrieve appliances from GitHub due to HTTP error code {}".format(response.status)) + etag = response.headers.get("ETag") + if etag: + self._appliances_etag = etag + from . import Controller + Controller.instance().save() + json_data = await response.json() + appliances_dir = get_resource('appliances') + for appliance in json_data: + if appliance["type"] == "file": + appliance_name = appliance["name"] + log.info("Download appliance file from '{}'".format(appliance["download_url"])) + async with session.get(appliance["download_url"]) as response: + if response.status != 200: + log.warning("Could not download '{}' due to HTTP error code {}".format(appliance["download_url"], response.status)) + continue + try: + appliance_data = await response.read() + except asyncio.TimeoutError: + log.warning("Timeout while downloading '{}'".format(appliance["download_url"])) + continue + path = os.path.join(appliances_dir, appliance_name) + try: + log.info("Saving {} file to {}".format(appliance_name, path)) + with open(path, 'wb') as f: + f.write(appliance_data) + except OSError as e: + raise aiohttp.web.HTTPConflict(text="Could not write appliance file '{}': {}".format(path, e)) + except ValueError as e: + raise aiohttp.web.HTTPConflict(text="Could not read appliances information from GitHub: {}".format(e)) + + # download the custom symbols + await self.download_custom_symbols() diff --git a/gns3server/controller/appliance_template.py b/gns3server/controller/appliance_template.py deleted file mode 100644 index caf18f7e..00000000 --- a/gns3server/controller/appliance_template.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2016 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 copy -import uuid - - -class ApplianceTemplate: - - def __init__(self, appliance_id, data, builtin=True): - if appliance_id is None: - self._id = str(uuid.uuid4()) - elif isinstance(appliance_id, uuid.UUID): - self._id = str(appliance_id) - else: - self._id = appliance_id - self._data = data.copy() - self._builtin = builtin - if "appliance_id" in self._data: - del self._data["appliance_id"] - - @property - def id(self): - return self._id - - @property - def status(self): - return self._data["status"] - - def __json__(self): - """ - Appliance data (a hash) - """ - data = copy.deepcopy(self._data) - data["builtin"] = self._builtin - return data diff --git a/gns3server/controller/compute.py b/gns3server/controller/compute.py index e1948a35..419d3e07 100644 --- a/gns3server/controller/compute.py +++ b/gns3server/controller/compute.py @@ -18,6 +18,7 @@ import ipaddress import aiohttp import asyncio +import async_timeout import socket import json import uuid @@ -26,10 +27,9 @@ import io from operator import itemgetter from ..utils import parse_version -from ..utils.images import list_images -from ..utils.asyncio import locked_coroutine +from ..utils.asyncio import locking from ..controller.controller_error import ControllerError -from ..version import __version__ +from ..version import __version__, __version_info__ import logging @@ -52,22 +52,6 @@ class ComputeConflict(aiohttp.web.HTTPConflict): self.response = response -class Timeout(aiohttp.Timeout): - """ - Could be removed with aiohttp 0.22 that support None timeout - """ - - def __enter__(self): - if self._timeout: - return super().__enter__() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - if self._timeout: - return super().__exit__(exc_type, exc_val, exc_tb) - return self - - class Compute: """ A GNS3 compute. @@ -90,22 +74,20 @@ class Compute: self._user = None self._password = None self._connected = False + self._notifications = None self._closed = False # Close mean we are destroying the compute node self._controller = controller self._set_auth(user, password) self._cpu_usage_percent = None self._memory_usage_percent = None + self._last_error = None self._capabilities = { "version": None, "node_types": [] } self.name = name - # Websocket for notifications - self._ws = None - # Cache of interfaces on remote host self._interfaces_cache = None - self._connection_failure = 0 def _session(self): @@ -113,9 +95,10 @@ class Compute: self._http_session = aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=None, force_close=True)) return self._http_session - def __del__(self): - if self._http_session: - self._http_session.close() + #def __del__(self): + # + # if self._http_session: + # self._http_session.close() def _set_auth(self, user, password): """ @@ -137,38 +120,46 @@ class Compute: self._password = None self._auth = aiohttp.BasicAuth(self._user, "") - @asyncio.coroutine - def interfaces(self): + def set_last_error(self, msg): + """ + Set the last error message for this compute. + + :param msg: message + """ + self._last_error = msg + + async def interfaces(self): """ Get the list of network on compute """ if not self._interfaces_cache: - response = yield from self.get("/network/interfaces") + response = await self.get("/network/interfaces") self._interfaces_cache = response.json return self._interfaces_cache - @asyncio.coroutine - def update(self, **kwargs): + async def update(self, **kwargs): for kw in kwargs: if kw not in ("user", "password"): setattr(self, kw, kwargs[kw]) # It's important to set user and password at the same time if "user" in kwargs or "password" in kwargs: self._set_auth(kwargs.get("user", self._user), kwargs.get("password", self._password)) - if self._http_session: - self._http_session.close() + if self._http_session and not self._http_session.closed: + await self._http_session.close() self._connected = False - self._controller.notification.emit("compute.updated", self.__json__()) + self._controller.notification.controller_emit("compute.updated", self.__json__()) self._controller.save() - @asyncio.coroutine - def close(self): + async def close(self): + self._connected = False - if self._http_session: - self._http_session.close() - if self._ws: - yield from self._ws.close() - self._ws = None + if self._http_session and not self._http_session.closed: + await self._http_session.close() + try: + if self._notifications: + await self._notifications + except asyncio.CancelledError: + pass self._closed = True @property @@ -301,11 +292,11 @@ class Compute: "connected": self._connected, "cpu_usage_percent": self._cpu_usage_percent, "memory_usage_percent": self._memory_usage_percent, - "capabilities": self._capabilities + "capabilities": self._capabilities, + "last_error": self._last_error } - @asyncio.coroutine - def download_file(self, project, path): + async def download_file(self, project, path): """ Read file of a project and download it @@ -315,13 +306,12 @@ class Compute: """ url = self._getUrl("/projects/{}/files/{}".format(project.id, path)) - response = yield from self._session().request("GET", url, auth=self._auth) + response = await self._session().request("GET", url, auth=self._auth) if response.status == 404: raise aiohttp.web.HTTPNotFound(text="{} not found on compute".format(path)) return response - @asyncio.coroutine - def download_image(self, image_type, image): + async def download_image(self, image_type, image): """ Read file of a project and download it @@ -331,91 +321,57 @@ class Compute: """ url = self._getUrl("/{}/images/{}".format(image_type, image)) - response = yield from self._session().request("GET", url, auth=self._auth) + response = await self._session().request("GET", url, auth=self._auth) if response.status == 404: raise aiohttp.web.HTTPNotFound(text="{} not found on compute".format(image)) return response - @asyncio.coroutine - def stream_file(self, project, path): - """ - Read file of a project and stream it - - :param project: A project object - :param path: The path of the file in the project - :returns: A file stream - """ - - # Due to Python 3.4 limitation we can't use with and asyncio - # https://www.python.org/dev/peps/pep-0492/ - # that why we wrap the answer - class StreamResponse: - - def __init__(self, response): - self._response = response - - def __enter__(self): - return self._response.content - - def __exit__(self): - self._response.close() - - url = self._getUrl("/projects/{}/stream/{}".format(project.id, path)) - response = yield from self._session().request("GET", url, auth=self._auth, timeout=None) - if response.status == 404: - raise aiohttp.web.HTTPNotFound(text="{} not found on compute".format(path)) - elif response.status == 403: - raise aiohttp.web.HTTPForbidden(text="forbidden to open {} on compute".format(path)) - elif response.status != 200: - raise aiohttp.web.HTTPInternalServerError(text="Unexpected error {}: {}: while opening {} on compute".format(response.status, - response.reason, - path)) - return StreamResponse(response) - - @asyncio.coroutine - def http_query(self, method, path, data=None, dont_connect=False, **kwargs): + async def http_query(self, method, path, data=None, dont_connect=False, **kwargs): """ :param dont_connect: If true do not reconnect if not connected """ if not self._connected and not dont_connect: if self._id == "vm" and not self._controller.gns3vm.running: - yield from self._controller.gns3vm.start() - yield from self.connect() + await self._controller.gns3vm.start() + await self.connect() if not self._connected and not dont_connect: raise ComputeError("Cannot connect to compute '{}' with request {} {}".format(self._name, method, path)) - response = yield from self._run_http_query(method, path, data=data, **kwargs) + response = await self._run_http_query(method, path, data=data, **kwargs) return response - @asyncio.coroutine - def _try_reconnect(self): + async def _try_reconnect(self): """ We catch error during reconnect """ try: - yield from self.connect() + await self.connect() except aiohttp.web.HTTPConflict: pass - @locked_coroutine - def connect(self): + @locking + async def connect(self): """ Check if remote server is accessible """ - if not self._connected and not self._closed: + if not self._connected and not self._closed and self.host: try: log.info("Connecting to compute '{}'".format(self._id)) - response = yield from self._run_http_query("GET", "/capabilities") + response = await self._run_http_query("GET", "/capabilities") except ComputeError as e: - # Try to reconnect after 2 seconds if server unavailable only if not during tests (otherwise we create a ressources usage bomb) + log.warning("Cannot connect to compute '{}': {}".format(self._id, e)) + # Try to reconnect after 2 seconds if server unavailable only if not during tests (otherwise we create a ressource usage bomb) if not hasattr(sys, "_called_from_test") or not sys._called_from_test: + if self.id != "local" and not self._controller.compute_has_open_project(self): + log.info("Not reconnecting to compute '{}' because there is no project opened on it".format(self._id)) + return self._connection_failure += 1 # After 5 failure we close the project using the compute to avoid sync issues - if self._connection_failure == 5: - log.warning("Cannot connect to compute '{}': {}".format(self._id, e)) - yield from self._controller.close_compute_projects(self) - asyncio.get_event_loop().call_later(2, lambda: asyncio.async(self._try_reconnect())) + if self._connection_failure == 10: + log.error("Could not connect to compute '{}' after multiple attempts: {}".format(self._id, e)) + await self._controller.close_compute_projects(self) + asyncio.get_event_loop().call_later(2, lambda: asyncio.ensure_future(self._try_reconnect())) return except aiohttp.web.HTTPNotFound: raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server or it's a 1.X server".format(self._id)) @@ -427,56 +383,85 @@ class Compute: raise aiohttp.web.HTTPConflict(text="Invalid server url for server {}".format(self._id)) if "version" not in response.json: - self._http_session.close() - raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server".format(self._id)) + msg = "The server {} is not a GNS3 server".format(self._id) + log.error(msg) + await self._http_session.close() + raise aiohttp.web.HTTPConflict(text=msg) self._capabilities = response.json - if parse_version(__version__)[:2] != parse_version(response.json["version"])[:2]: - self._http_session.close() - raise aiohttp.web.HTTPConflict(text="The server {} versions are not compatible {} != {}".format(self._id, __version__, response.json["version"])) + + if response.json["version"].split("-")[0] != __version__.split("-")[0]: + if self._name.startswith("GNS3 VM"): + msg = "GNS3 version {} is not the same as the GNS3 VM version {}. Please upgrade the GNS3 VM.".format(__version__, + response.json["version"]) + else: + msg = "GNS3 controller version {} is not the same as compute {} version {}".format(__version__, + self._name, + response.json["version"]) + if __version_info__[3] == 0: + # Stable release + log.error(msg) + await self._http_session.close() + self._last_error = msg + raise aiohttp.web.HTTPConflict(text=msg) + elif parse_version(__version__)[:2] != parse_version(response.json["version"])[:2]: + # We don't allow different major version to interact even with dev build + log.error(msg) + await self._http_session.close() + self._last_error = msg + raise aiohttp.web.HTTPConflict(text=msg) + else: + msg = "{}\nUsing different versions may result in unexpected problems. Please use at your own risk.".format(msg) + self._controller.notification.controller_emit("log.warning", {"message": msg}) self._notifications = asyncio.gather(self._connect_notification()) self._connected = True self._connection_failure = 0 - self._controller.notification.emit("compute.updated", self.__json__()) + self._last_error = None + self._controller.notification.controller_emit("compute.updated", self.__json__()) - @asyncio.coroutine - def _connect_notification(self): + async def _connect_notification(self): """ Connect to the notification stream """ + + ws_url = self._getUrl("/notifications/ws") try: - self._ws = yield from self._session().ws_connect(self._getUrl("/notifications/ws"), auth=self._auth) - except (aiohttp.WSServerHandshakeError, aiohttp.ClientResponseError): - self._ws = None - while self._ws is not None: - try: - response = yield from self._ws.receive() - except aiohttp.WSServerHandshakeError: - self._ws = None - break - if response.tp == aiohttp.WSMsgType.closed or response.tp == aiohttp.WSMsgType.error or response.data is None: - self._connected = False - break - msg = json.loads(response.data) - action = msg.pop("action") - event = msg.pop("event") + async with self._session().ws_connect(ws_url, auth=self._auth, heartbeat=10) as ws: + log.info("Connected to compute WebSocket '{}'".format(ws_url)) + async for response in ws: + if response.type == aiohttp.WSMsgType.TEXT: + msg = json.loads(response.data) + action = msg.pop("action") + event = msg.pop("event") + project_id = msg.pop("project_id", None) + if action == "ping": + self._cpu_usage_percent = event["cpu_usage_percent"] + self._memory_usage_percent = event["memory_usage_percent"] + #FIXME: slow down number of compute events + self._controller.notification.controller_emit("compute.updated", self.__json__()) + else: + await self._controller.notification.dispatch(action, event, project_id=project_id, compute_id=self.id) + else: + if response.type == aiohttp.WSMsgType.CLOSE: + await ws.close() + elif response.type == aiohttp.WSMsgType.ERROR: + log.error("Error received on compute WebSocket '{}': {}".format(ws_url, ws.exception())) + elif response.type == aiohttp.WSMsgType.CLOSED: + pass + self._connected = False + break + except aiohttp.client_exceptions.ClientResponseError as e: + log.error("Client response error received on compute WebSocket '{}': {}".format(ws_url,e)) + finally: + log.info("Connection closed to compute WebSocket '{}'".format(ws_url)) - if action == "ping": - self._cpu_usage_percent = event["cpu_usage_percent"] - self._memory_usage_percent = event["memory_usage_percent"] - self._controller.notification.emit("compute.updated", self.__json__()) - else: - yield from self._controller.notification.dispatch(action, event, compute_id=self.id) - if self._ws: - yield from self._ws.close() - - # Try to reconnect after 1 seconds if server unavailable only if not during tests (otherwise we create a ressources usage bomb) + # Try to reconnect after 1 second if server unavailable only if not during tests (otherwise we create a ressources usage bomb) if not hasattr(sys, "_called_from_test") or not sys._called_from_test: - asyncio.get_event_loop().call_later(1, lambda: asyncio.async(self.connect())) - self._ws = None + asyncio.get_event_loop().call_later(1, lambda: asyncio.ensure_future(self.connect())) + self._cpu_usage_percent = None self._memory_usage_percent = None - self._controller.notification.emit("compute.updated", self.__json__()) + self._controller.notification.controller_emit("compute.updated", self.__json__()) def _getUrl(self, path): host = self._host @@ -497,9 +482,8 @@ class Compute: """ Returns URL for specific path at Compute""" return self._getUrl(path) - @asyncio.coroutine - def _run_http_query(self, method, path, data=None, timeout=20, raw=False): - with Timeout(timeout): + async def _run_http_query(self, method, path, data=None, timeout=20, raw=False): + with async_timeout.timeout(timeout): url = self._getUrl(path) headers = {} headers['content-type'] = 'application/json' @@ -522,18 +506,14 @@ class Compute: else: data = json.dumps(data).encode("utf-8") try: - log.debug("Attempting request to compute: {method} {url} {headers}".format( - method=method, - url=url, - headers=headers - )) - response = yield from self._session().request(method, url, headers=headers, data=data, auth=self._auth, chunked=chunked, timeout=timeout) - except asyncio.TimeoutError as e: - raise ComputeError("Timeout error when connecting to {}".format(url)) + log.debug("Attempting request to compute: {method} {url} {headers}".format(method=method, url=url, headers=headers)) + response = await self._session().request(method, url, headers=headers, data=data, auth=self._auth, chunked=chunked, timeout=timeout) + except asyncio.TimeoutError: + raise ComputeError("Timeout error for {} call to {} after {}s".format(method, url, timeout)) except (aiohttp.ClientError, aiohttp.ServerDisconnectedError, ValueError, KeyError, socket.gaierror) as e: # aiohttp 2.3.1 raises socket.gaierror when cannot find host raise ComputeError(str(e)) - body = yield from response.read() + body = await response.read() if body and not raw: body = body.decode() @@ -568,7 +548,7 @@ class Compute: elif response.status == 503: raise aiohttp.web.HTTPServiceUnavailable(text="Service unavailable {} {}".format(url, body)) else: - raise NotImplementedError("{} status code is not supported".format(response.status)) + raise NotImplementedError("{} status code is not supported for {} '{}'".format(response.status, method, url)) if body and len(body): if raw: response.body = body @@ -582,73 +562,64 @@ class Compute: response.body = b"" return response - @asyncio.coroutine - def get(self, path, **kwargs): - return (yield from self.http_query("GET", path, **kwargs)) + async def get(self, path, **kwargs): + return (await self.http_query("GET", path, **kwargs)) - @asyncio.coroutine - def post(self, path, data={}, **kwargs): - response = yield from self.http_query("POST", path, data, **kwargs) + async def post(self, path, data={}, **kwargs): + response = await self.http_query("POST", path, data, **kwargs) return response - @asyncio.coroutine - def put(self, path, data={}, **kwargs): - response = yield from self.http_query("PUT", path, data, **kwargs) + async def put(self, path, data={}, **kwargs): + response = await self.http_query("PUT", path, data, **kwargs) return response - @asyncio.coroutine - def delete(self, path, **kwargs): - return (yield from self.http_query("DELETE", path, **kwargs)) + async def delete(self, path, **kwargs): + return (await self.http_query("DELETE", path, **kwargs)) - @asyncio.coroutine - def forward(self, method, type, path, data=None): + async def forward(self, method, type, path, data=None): """ Forward a call to the emulator on compute """ try: action = "/{}/{}".format(type, path) - res = yield from self.http_query(method, action, data=data, timeout=None) + res = await self.http_query(method, action, data=data, timeout=None) except aiohttp.ServerDisconnectedError: log.error("Connection lost to %s during %s %s", self._id, method, action) raise aiohttp.web.HTTPGatewayTimeout() return res.json - @asyncio.coroutine - def images(self, type): + async def images(self, type): """ - Return the list of images available for this type on controller - and on the compute node. + Return the list of images available for this type on the compute node. """ images = [] - res = yield from self.http_query("GET", "/{}/images".format(type), timeout=None) + res = await self.http_query("GET", "/{}/images".format(type), timeout=None) images = res.json try: if type in ["qemu", "dynamips", "iou"]: - for local_image in list_images(type): - if local_image['filename'] not in [i['filename'] for i in images]: - images.append(local_image) + #for local_image in list_images(type): + # if local_image['filename'] not in [i['filename'] for i in images]: + # images.append(local_image) images = sorted(images, key=itemgetter('filename')) else: images = sorted(images, key=itemgetter('image')) except OSError as e: - raise ComputeError("Can't list images: {}".format(str(e))) + raise ComputeError("Cannot list images: {}".format(str(e))) return images - @asyncio.coroutine - def list_files(self, project): + async def list_files(self, project): """ List files in the project on computes """ path = "/projects/{}/files".format(project.id) - res = yield from self.http_query("GET", path, timeout=120) + res = await self.http_query("GET", path, timeout=None) return res.json - @asyncio.coroutine - def get_ip_on_same_subnet(self, other_compute): + async def get_ip_on_same_subnet(self, other_compute): """ - Try to found the best ip for communication from one compute + Try to find the best ip for communication from one compute to another :returns: Tuple (ip_for_this_compute, ip_for_other_compute) @@ -660,8 +631,8 @@ class Compute: if (self.host_ip not in ('0.0.0.0', '127.0.0.1') and other_compute.host_ip not in ('0.0.0.0', '127.0.0.1')): return (self.host_ip, other_compute.host_ip) - this_compute_interfaces = yield from self.interfaces() - other_compute_interfaces = yield from other_compute.interfaces() + this_compute_interfaces = await self.interfaces() + other_compute_interfaces = await other_compute.interfaces() # Sort interface to put the compute host in first position # we guess that if user specified this host it could have a reason (VMware Nat / Host only interface) diff --git a/gns3server/controller/drawing.py b/gns3server/controller/drawing.py index 47c09d0e..4ef324b4 100644 --- a/gns3server/controller/drawing.py +++ b/gns3server/controller/drawing.py @@ -37,7 +37,7 @@ class Drawing: text, images, rectangle... They are pure SVG elements. """ - def __init__(self, project, drawing_id=None, svg="", x=0, y=0, z=0, rotation=0): + def __init__(self, project, drawing_id=None, svg="", x=0, y=0, z=2, locked=False, rotation=0): self._project = project if drawing_id is None: self._id = str(uuid.uuid4()) @@ -49,13 +49,14 @@ class Drawing: self._y = y self._z = z self._rotation = rotation + self._locked = locked @property def id(self): return self._id @property - def ressource_filename(self): + def resource_filename(self): """ If the svg content has been dump to an external file return is name otherwise None """ @@ -157,6 +158,14 @@ class Drawing: def z(self, val): self._z = val + @property + def locked(self): + return self._locked + + @locked.setter + def locked(self, val): + self._locked = val + @property def rotation(self): return self._rotation @@ -165,8 +174,7 @@ class Drawing: def rotation(self, val): self._rotation = val - @asyncio.coroutine - def update(self, **kwargs): + async def update(self, **kwargs): """ Update the drawing @@ -186,7 +194,7 @@ class Drawing: data = self.__json__() if not svg_changed: del data["svg"] - self._project.controller.notification.emit("drawing.updated", data) + self._project.emit_notification("drawing.updated", data) self._project.dump() def __json__(self, topology_dump=False): @@ -199,6 +207,7 @@ class Drawing: "x": self._x, "y": self._y, "z": self._z, + "locked": self._locked, "rotation": self._rotation, "svg": self._svg } @@ -208,6 +217,7 @@ class Drawing: "x": self._x, "y": self._y, "z": self._z, + "locked": self._locked, "rotation": self._rotation, "svg": self.svg } diff --git a/gns3server/controller/export_project.py b/gns3server/controller/export_project.py index 7e43b894..6d8e4210 100644 --- a/gns3server/controller/export_project.py +++ b/gns3server/controller/export_project.py @@ -16,135 +16,166 @@ # along with this program. If not, see . import os +import sys import json import asyncio +import aiofiles import aiohttp import zipfile import tempfile -import zipstream +from datetime import datetime import logging log = logging.getLogger(__name__) +CHUNK_SIZE = 1024 * 8 # 8KB -@asyncio.coroutine -def export_project(project, temporary_dir, include_images=False, keep_compute_id=False, - allow_all_nodes=False, ignore_prefixes=None): + +async def export_project(zstream, project, temporary_dir, include_images=False, include_snapshots=False, keep_compute_id=False, allow_all_nodes=False, reset_mac_addresses=False): """ - Export the project as zip. It's a ZipStream object. - The file will be read chunk by chunk when you iterate on - the zip. + Export a project to a zip file. - It will ignore some files like snapshots and + The file will be read chunk by chunk when you iterate over the zip stream. + Some files like snapshots and packet captures are ignored. + :param zstream: ZipStream object + :param project: Project instance :param temporary_dir: A temporary dir where to store intermediate data - :param keep_compute_id: If false replace all compute id by local it's the standard behavior for .gns3project to make them portable - :param allow_all_nodes: Allow all nodes type to be include in the zip even if not portable default False - :returns: ZipStream object + :param include_images: save OS images to the zip file + :param include_snapshots: save snapshots to the zip file + :param keep_compute_id: If false replace all compute id by local (standard behavior for .gns3project to make it portable) + :param allow_all_nodes: Allow all nodes type to be include in the zip even if not portable + :param reset_mac_addresses: Reset MAC addresses for every nodes. """ - # To avoid issue with data not saved we disallow the export of a running topologie + # To avoid issue with data not saved we disallow the export of a running project if project.is_running(): - raise aiohttp.web.HTTPConflict(text="Running topology could not be exported") + raise aiohttp.web.HTTPConflict(text="Project must be stopped in order to export it") # Make sure we save the project project.dump() - z = zipstream.ZipFile(allowZip64=True) - if not os.path.exists(project._path): - raise aiohttp.web.HTTPNotFound(text="The project doesn't exist at location {}".format(project._path)) + raise aiohttp.web.HTTPNotFound(text="Project could not be found at '{}'".format(project._path)) # First we process the .gns3 in order to be sure we don't have an error for file in os.listdir(project._path): if file.endswith(".gns3"): - images = yield from _export_project_file(project, os.path.join(project._path, file), - z, include_images, keep_compute_id, allow_all_nodes, temporary_dir) + await _patch_project_file(project, os.path.join(project._path, file), zstream, include_images, keep_compute_id, allow_all_nodes, temporary_dir, reset_mac_addresses) - for root, dirs, files in os.walk(project._path, topdown=True): - files = [f for f in files if not _filter_files(os.path.join(root, f))] + # Export the local files + for root, dirs, files in os.walk(project._path, topdown=True, followlinks=False): + files = [f for f in files if _is_exportable(os.path.join(root, f), include_snapshots)] for file in files: path = os.path.join(root, file) - # Try open the file + # check if we can export the file try: open(path).close() except OSError as e: msg = "Could not export file {}: {}".format(path, e) - log.warn(msg) - project.controller.notification.emit("log.warning", {"message": msg}) + log.warning(msg) + project.emit_notification("log.warning", {"message": msg}) continue + # ignore the .gns3 file if file.endswith(".gns3"): - pass - else: - z.write(path, os.path.relpath(path, project._path), compress_type=zipfile.ZIP_DEFLATED) - - downloaded_files = set() + continue + _patch_mtime(path) + zstream.write(path, os.path.relpath(path, project._path)) + # Export files from remote computes for compute in project.computes: if compute.id != "local": - compute_files = yield from compute.list_files(project) + compute_files = await compute.list_files(project) for compute_file in compute_files: - if not _filter_files(compute_file["path"]): + if _is_exportable(compute_file["path"], include_snapshots): + log.debug("Downloading file '{}' from compute '{}'".format(compute_file["path"], compute.id)) + response = await compute.download_file(project, compute_file["path"]) + #if response.status != 200: + # raise aiohttp.web.HTTPConflict(text="Cannot export file from compute '{}'. Compute returned status code {}.".format(compute.id, response.status)) (fd, temp_path) = tempfile.mkstemp(dir=temporary_dir) - f = open(fd, "wb", closefd=True) - response = yield from compute.download_file(project, compute_file["path"]) - while True: - data = yield from response.content.read(512) - if not data: - break - f.write(data) + async with aiofiles.open(fd, 'wb') as f: + while True: + try: + data = await response.content.read(CHUNK_SIZE) + except asyncio.TimeoutError: + raise aiohttp.web.HTTPRequestTimeout(text="Timeout when downloading file '{}' from remote compute {}:{}".format(compute_file["path"], compute.host, compute.port)) + if not data: + break + await f.write(data) response.close() - f.close() - z.write(temp_path, arcname=compute_file["path"], compress_type=zipfile.ZIP_DEFLATED) - downloaded_files.add(compute_file['path']) - - return z + _patch_mtime(temp_path) + zstream.write(temp_path, arcname=compute_file["path"]) -def _filter_files(path): +def _patch_mtime(path): + """ + Patch the file mtime because ZIP does not support timestamps before 1980 + + :param path: file path + """ + + if sys.platform.startswith("win"): + # only UNIX type platforms + return + st = os.stat(path) + file_date = datetime.fromtimestamp(st.st_mtime) + if file_date.year < 1980: + new_mtime = file_date.replace(year=1980).timestamp() + os.utime(path, (st.st_atime, new_mtime)) + + +def _is_exportable(path, include_snapshots=False): """ :returns: True if file should not be included in the final archive """ - s = os.path.normpath(path).split(os.path.sep) - if path.endswith("snapshots"): - return True + # do not export snapshots by default + if include_snapshots is False and path.endswith("snapshots"): + return False - # filter directory of snapshots - if "{sep}snapshots{sep}".format(sep=os.path.sep) in path: - return True + # do not export symlinks + if os.path.islink(path): + return False + + # do not export directories of snapshots + if include_snapshots is False and "{sep}snapshots{sep}".format(sep=os.path.sep) in path: + return False try: + # do not export captures and other temporary directory + s = os.path.normpath(path).split(os.path.sep) i = s.index("project-files") - if s[i + 1] in ("tmp", "captures", "snapshots"): - return True + if include_snapshots is False and s[i + 1] == "snapshots": + return False + if s[i + 1] in ("tmp", "captures"): + return False except (ValueError, IndexError): pass - file_name = os.path.basename(path) - # Ignore log files and OS noises - if file_name.endswith('_log.txt') or file_name.endswith('.log') or file_name == '.DS_Store': - return True - - return False + # do not export log files and OS noise + filename = os.path.basename(path) + if filename.endswith('_log.txt') or filename.endswith('.log') or filename == '.DS_Store': + return False + return True -@asyncio.coroutine -def _export_project_file(project, path, z, include_images, keep_compute_id, allow_all_nodes, temporary_dir): +async def _patch_project_file(project, path, zstream, include_images, keep_compute_id, allow_all_nodes, temporary_dir, reset_mac_addresses): """ - Take a project file (.gns3) and patch it for the export + Patch a project file (.gns3) to export a project. + The .gns3 file is renamed to project.gns3 - We rename the .gns3 project.gns3 to avoid the task to the client to guess the file name - - :param path: Path of the .gns3 + :param path: path of the .gns3 file """ - # Image file that we need to include in the exported archive + # image files that we need to include in the exported archive images = [] - with open(path) as f: - topology = json.load(f) + try: + with open(path) as f: + topology = json.load(f) + except (OSError, ValueError) as e: + raise aiohttp.web.HTTPConflict(text="Project file '{}' cannot be read: {}".format(path, e)) if "topology" in topology: if "nodes" in topology["topology"]: @@ -152,9 +183,9 @@ def _export_project_file(project, path, z, include_images, keep_compute_id, allo compute_id = node.get('compute_id', 'local') if node["node_type"] == "virtualbox" and node.get("properties", {}).get("linked_clone"): - raise aiohttp.web.HTTPConflict(text="Topology with a linked {} clone could not be exported. Use qemu instead.".format(node["node_type"])) - if not allow_all_nodes and node["node_type"] in ["virtualbox", "vmware", "cloud"]: - raise aiohttp.web.HTTPConflict(text="Topology with a {} could not be exported".format(node["node_type"])) + raise aiohttp.web.HTTPConflict(text="Projects with a linked {} clone node cannot not be exported. Please use Qemu instead.".format(node["node_type"])) + if not allow_all_nodes and node["node_type"] in ["virtualbox", "vmware"]: + raise aiohttp.web.HTTPConflict(text="Projects with a {} node cannot be exported".format(node["node_type"])) if not keep_compute_id: node["compute_id"] = "local" # To make project portable all node by default run on local @@ -162,6 +193,10 @@ def _export_project_file(project, path, z, include_images, keep_compute_id, allo if "properties" in node and node["node_type"] != "docker": for prop, value in node["properties"].items(): + # reset the MAC address + if reset_mac_addresses and prop in ("mac_addr", "mac_address"): + node["properties"][prop] = None + if node["node_type"] == "iou": if not prop == "path": continue @@ -186,83 +221,73 @@ def _export_project_file(project, path, z, include_images, keep_compute_id, allo local_images = set([i['image'] for i in images if i['compute_id'] == 'local']) for image in local_images: - _export_local_images(project, image, z) + _export_local_image(image, zstream) remote_images = set([ (i['compute_id'], i['image_type'], i['image']) for i in images if i['compute_id'] != 'local']) for compute_id, image_type, image in remote_images: - yield from _export_remote_images(project, compute_id, image_type, image, z, temporary_dir) - - z.writestr("project.gns3", json.dumps(topology).encode()) + await _export_remote_images(project, compute_id, image_type, image, zstream, temporary_dir) + zstream.writestr("project.gns3", json.dumps(topology).encode()) return images -def _export_local_images(project, image, z): - """ - Take a project file (.gns3) and export images to the zip - :param image: Image path - :param z: Zipfile instance for the export +def _export_local_image(image, zstream): """ + Exports a local image to the zip file. + + :param image: image path + :param zstream: Zipfile instance for the export + """ + from ..compute import MODULES - for module in MODULES: try: - img_directory = module.instance().get_images_directory() + images_directory = module.instance().get_images_directory() except NotImplementedError: # Some modules don't have images continue - directory = os.path.split(img_directory)[-1:][0] + directory = os.path.split(images_directory)[-1:][0] if os.path.exists(image): path = image else: - path = os.path.join(img_directory, image) + path = os.path.join(images_directory, image) if os.path.exists(path): arcname = os.path.join("images", directory, os.path.basename(image)) - z.write(path, arcname) + _patch_mtime(path) + zstream.write(path, arcname) return -@asyncio.coroutine -def _export_remote_images(project, compute_id, image_type, image, project_zipfile, temporary_dir): +async def _export_remote_images(project, compute_id, image_type, image, project_zipfile, temporary_dir): """ - Export specific image from remote compute - :param project: - :param compute_id: - :param image_type: - :param image: - :param project_zipfile: - :return: + Export specific image from remote compute. """ - log.info("Obtaining image `{}` from `{}`".format(image, compute_id)) - + log.debug("Downloading image '{}' from compute '{}'".format(image, compute_id)) try: compute = [compute for compute in project.computes if compute.id == compute_id][0] except IndexError: - raise aiohttp.web.HTTPConflict( - text="Cannot export image from `{}` compute. Compute doesn't exist.".format(compute_id)) + raise aiohttp.web.HTTPConflict(text="Cannot export image from '{}' compute. Compute doesn't exist.".format(compute_id)) + + response = await compute.download_image(image_type, image) + if response.status != 200: + raise aiohttp.web.HTTPConflict(text="Cannot export image from compute '{}'. Compute returned status code {}.".format(compute_id, response.status)) (fd, temp_path) = tempfile.mkstemp(dir=temporary_dir) - f = open(fd, "wb", closefd=True) - response = yield from compute.download_image(image_type, image) - - if response.status != 200: - raise aiohttp.web.HTTPConflict( - text="Cannot export image from `{}` compute. Compute sent `{}` status.".format( - compute_id, response.status)) - - while True: - data = yield from response.content.read(512) - if not data: - break - f.write(data) + async with aiofiles.open(fd, 'wb') as f: + while True: + try: + data = await response.content.read(CHUNK_SIZE) + except asyncio.TimeoutError: + raise aiohttp.web.HTTPRequestTimeout(text="Timeout when downloading image '{}' from remote compute {}:{}".format(image, compute.host, compute.port)) + if not data: + break + await f.write(data) response.close() - f.close() arcname = os.path.join("images", image_type, image) - log.info("Saved {}".format(arcname)) project_zipfile.write(temp_path, arcname=arcname, compress_type=zipfile.ZIP_DEFLATED) diff --git a/gns3server/controller/gns3vm/__init__.py b/gns3server/controller/gns3vm/__init__.py index acd9f7c3..885916e1 100644 --- a/gns3server/controller/gns3vm/__init__.py +++ b/gns3server/controller/gns3vm/__init__.py @@ -21,9 +21,10 @@ import asyncio import aiohttp import ipaddress -from ...utils.asyncio import locked_coroutine +from ...utils.asyncio import locking from .vmware_gns3_vm import VMwareGNS3VM from .virtualbox_gns3_vm import VirtualBoxGNS3VM +from .hyperv_gns3_vm import HyperVGNS3VM from .remote_gns3_vm import RemoteGNS3VM from .gns3_vm_error import GNS3VMError from ...version import __version__ @@ -59,7 +60,7 @@ class GNS3VM: """ download_url = "https://github.com/GNS3/gns3-gui/releases/download/v{version}/GNS3.VM.VMware.Workstation.{version}.zip".format(version=__version__) - vmware_informations = { + vmware_info = { "engine_id": "vmware", "description": 'VMware is the recommended choice for best performances.
The GNS3 VM can be downloaded here.'.format(download_url), "support_when_exit": True, @@ -67,21 +68,30 @@ class GNS3VM: "support_ram": True } if sys.platform.startswith("darwin"): - vmware_informations["name"] = "VMware Fusion" + vmware_info["name"] = "VMware Fusion (recommended)" else: - vmware_informations["name"] = "VMware Workstation / Player" + vmware_info["name"] = "VMware Workstation / Player (recommended)" + + hyperv_info = { + "engine_id": "hyper-v", + "name": "Hyper-V", + "description": 'Hyper-V support (Windows 10/Server 2016 and above). Nested virtualization must be supported and enabled (Intel processor only)', + "support_when_exit": True, + "support_headless": False, + "support_ram": True + } download_url = "https://github.com/GNS3/gns3-gui/releases/download/v{version}/GNS3.VM.VirtualBox.{version}.zip".format(version=__version__) - virtualbox_informations = { + virtualbox_info = { "engine_id": "virtualbox", "name": "VirtualBox", - "description": 'VirtualBox doesn\'t support nested virtualization, this means running Qemu based VM could be very slow.
The GNS3 VM can be downloaded here'.format(download_url), + "description": 'VirtualBox doesn\'t support nested virtualization, this means Qemu based VMs will run extremely slowly.
The GNS3 VM can be downloaded here'.format(download_url), "support_when_exit": True, "support_headless": True, "support_ram": True } - remote_informations = { + remote_info = { "engine_id": "remote", "name": "Remote", "description": "Use a remote GNS3 server as the GNS3 VM.", @@ -90,17 +100,22 @@ class GNS3VM: "support_ram": False } - return [ - vmware_informations, - virtualbox_informations, - remote_informations - ] + engines = [vmware_info, + virtualbox_info, + remote_info] + + if sys.platform.startswith("win"): + engines.append(hyperv_info) + + return engines def current_engine(self): + return self._get_engine(self._settings["engine"]) @property def engine(self): + return self._settings["engine"] @property @@ -110,6 +125,7 @@ class GNS3VM: :returns: VM IP address """ + return self.current_engine().ip_address @property @@ -119,6 +135,7 @@ class GNS3VM: :returns: Boolean """ + return self.current_engine().running @property @@ -128,6 +145,7 @@ class GNS3VM: :returns: VM user """ + return self.current_engine().user @property @@ -137,6 +155,7 @@ class GNS3VM: :returns: VM password """ + return self.current_engine().password @property @@ -146,6 +165,7 @@ class GNS3VM: :returns: VM port """ + return self.current_engine().port @property @@ -155,6 +175,7 @@ class GNS3VM: :returns: VM protocol """ + return self.current_engine().protocol @property @@ -162,6 +183,7 @@ class GNS3VM: """ The GNSVM is activated """ + return self._settings.get("enable", False) @property @@ -169,44 +191,53 @@ class GNS3VM: """ What should be done when exit """ + return self._settings["when_exit"] @property def settings(self): + return self._settings @settings.setter def settings(self, val): + self._settings.update(val) - @asyncio.coroutine - def update_settings(self, settings): + async def update_settings(self, settings): """ Update settings and will restart the VM if require """ + new_settings = copy.copy(self._settings) new_settings.update(settings) if self.settings != new_settings: - yield from self._stop() - self._settings = settings - self._controller.save() + try: + await self._stop() + finally: + self._settings = settings + self._controller.save() if self.enable: - yield from self.start() + await self.start() else: # When user fix something on his system and try again if self.enable and not self.current_engine().running: - yield from self.start() + await self.start() def _get_engine(self, engine): """ Load an engine """ + if engine in self._engines: return self._engines[engine] if engine == "vmware": self._engines["vmware"] = VMwareGNS3VM(self._controller) return self._engines["vmware"] + elif engine == "hyper-v": + self._engines["hyper-v"] = HyperVGNS3VM(self._controller) + return self._engines["hyper-v"] elif engine == "virtualbox": self._engines["virtualbox"] = VirtualBoxGNS3VM(self._controller) return self._engines["virtualbox"] @@ -218,15 +249,15 @@ class GNS3VM: def __json__(self): return self._settings - @asyncio.coroutine - def list(self, engine): + async def list(self, engine): """ List VMS for an engine """ + engine = self._get_engine(engine) vms = [] try: - for vm in (yield from engine.list()): + for vm in (await engine.list()): vms.append({"vmname": vm["vmname"]}) except GNS3VMError as e: # We raise error only if user activated the GNS3 VM @@ -235,41 +266,44 @@ class GNS3VM: raise e return vms - @asyncio.coroutine - def auto_start_vm(self): + async def auto_start_vm(self): """ Auto start the GNS3 VM if require """ + if self.enable: try: - yield from self.start() + await self.start() except GNS3VMError as e: # User will receive the error later when they will try to use the node try: - yield from self._controller.add_compute(compute_id="vm", - name="GNS3 VM ({})".format(self.current_engine().vmname), - host=None, - force=True) + compute = await self._controller.add_compute(compute_id="vm", + name="GNS3 VM ({})".format(self.current_engine().vmname), + host=None, + force=True) + compute.set_last_error(str(e)) + except aiohttp.web.HTTPConflict: pass - log.error("Can't start the GNS3 VM: %s", str(e)) + log.error("Cannot start the GNS3 VM: {}".format(e)) + + async def exit_vm(self): - @asyncio.coroutine - def exit_vm(self): if self.enable: try: if self._settings["when_exit"] == "stop": - yield from self._stop() + await self._stop() elif self._settings["when_exit"] == "suspend": - yield from self._suspend() + await self._suspend() except GNS3VMError as e: - log.warn(str(e)) + log.warning(str(e)) - @locked_coroutine - def start(self): + @locking + async def start(self): """ Start the GNS3 VM """ + engine = self.current_engine() if not engine.running: if self._settings["vmname"] is None: @@ -279,21 +313,22 @@ class GNS3VM: engine.ram = self._settings["ram"] engine.vcpus = self._settings["vcpus"] engine.headless = self._settings["headless"] - compute = yield from self._controller.add_compute(compute_id="vm", - name="GNS3 VM is starting ({})".format(engine.vmname), - host=None, - force=True, - connect=False) + compute = await self._controller.add_compute(compute_id="vm", + name="GNS3 VM is starting ({})".format(engine.vmname), + host=None, + force=True, + connect=False) try: - yield from engine.start() + await engine.start() except Exception as e: - yield from self._controller.delete_compute("vm") - log.error("Can't start the GNS3 VM: {}".format(str(e))) - yield from compute.update(name="GNS3 VM ({})".format(engine.vmname)) + await self._controller.delete_compute("vm") + log.error("Cannot start the GNS3 VM: {}".format(str(e))) + await compute.update(name="GNS3 VM ({})".format(engine.vmname)) + compute.set_last_error(str(e)) raise e - yield from compute.connect() # we can connect now that the VM has started - yield from compute.update(name="GNS3 VM ({})".format(engine.vmname), + await compute.connect() # we can connect now that the VM has started + await compute.update(name="GNS3 VM ({})".format(engine.vmname), protocol=self.protocol, host=self.ip_address, port=self.port, @@ -302,16 +337,15 @@ class GNS3VM: # check if the VM is in the same subnet as the local server, start 10 seconds later to give # some time for the compute in the VM to be ready for requests - asyncio.get_event_loop().call_later(10, lambda: asyncio.async(self._check_network(compute))) + asyncio.get_event_loop().call_later(10, lambda: asyncio.ensure_future(self._check_network(compute))) - @asyncio.coroutine - def _check_network(self, compute): + async def _check_network(self, compute): """ Check that the VM is in the same subnet as the local server """ try: - vm_interfaces = yield from compute.interfaces() + vm_interfaces = await compute.interfaces() vm_interface_netmask = None for interface in vm_interfaces: if interface["ip_address"] == self.ip_address: @@ -322,7 +356,7 @@ class GNS3VM: for compute_id in self._controller.computes: if compute_id == "local": compute = self._controller.get_compute(compute_id) - interfaces = yield from compute.interfaces() + interfaces = await compute.interfaces() netmask = None for interface in interfaces: if interface["ip_address"] == compute.host_ip: @@ -331,32 +365,37 @@ class GNS3VM: if netmask: compute_network = ipaddress.ip_interface("{}/{}".format(compute.host_ip, netmask)).network if vm_network.compare_networks(compute_network) != 0: - msg = "The GNS3 VM ({}) is not on the same network as the {} server ({}), please make sure the local server binding is in the same network as the GNS3 VM".format( - vm_network, compute_id, compute_network) - self._controller.notification.emit("log.warning", {"message": msg}) + msg = "The GNS3 VM (IP={}, NETWORK={}) is not on the same network as the {} server (IP={}, NETWORK={}), please make sure the local server binding is in the same network as the GNS3 VM".format(self.ip_address, + vm_network, + compute_id, + compute.host_ip, + compute_network) + self._controller.notification.controller_emit("log.warning", {"message": msg}) except ComputeError as e: log.warning("Could not check the VM is in the same subnet as the local server: {}".format(e)) + except aiohttp.web.HTTPConflict as e: + log.warning("Could not check the VM is in the same subnet as the local server: {}".format(e.text)) - @locked_coroutine - def _suspend(self): + @locking + async def _suspend(self): """ Suspend the GNS3 VM """ engine = self.current_engine() if "vm" in self._controller.computes: - yield from self._controller.delete_compute("vm") + await self._controller.delete_compute("vm") if engine.running: log.info("Suspend the GNS3 VM") - yield from engine.suspend() + await engine.suspend() - @locked_coroutine - def _stop(self): + @locking + async def _stop(self): """ Stop the GNS3 VM """ engine = self.current_engine() if "vm" in self._controller.computes: - yield from self._controller.delete_compute("vm") + await self._controller.delete_compute("vm") if engine.running: log.info("Stop the GNS3 VM") - yield from engine.stop() + await engine.stop() diff --git a/gns3server/controller/gns3vm/base_gns3_vm.py b/gns3server/controller/gns3vm/base_gns3_vm.py index 67542e70..64305573 100644 --- a/gns3server/controller/gns3vm/base_gns3_vm.py +++ b/gns3server/controller/gns3vm/base_gns3_vm.py @@ -254,32 +254,28 @@ class BaseGNS3VM: return self._engine - @asyncio.coroutine - def list(self): + async def list(self): """ List all VMs """ raise NotImplementedError - @asyncio.coroutine - def start(self): + async def start(self): """ Starts the GNS3 VM. """ raise NotImplementedError - @asyncio.coroutine - def suspend(self): + async def suspend(self): """ Suspend the GNS3 VM. """ raise NotImplementedError - @asyncio.coroutine - def stop(self, force=False): + async def stop(self): """ Stops the GNS3 VM. """ diff --git a/gns3server/controller/gns3vm/hyperv_gns3_vm.py b/gns3server/controller/gns3vm/hyperv_gns3_vm.py new file mode 100644 index 00000000..a072e61d --- /dev/null +++ b/gns3server/controller/gns3vm/hyperv_gns3_vm.py @@ -0,0 +1,296 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 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 sys +import logging +import asyncio +import psutil +import ipaddress + +if sys.platform.startswith("win"): + import wmi + +from .base_gns3_vm import BaseGNS3VM +from .gns3_vm_error import GNS3VMError +log = logging.getLogger(__name__) + + +class HyperVGNS3VM(BaseGNS3VM): + + _HYPERV_VM_STATE_ENABLED = 2 + _HYPERV_VM_STATE_DISABLED = 3 + _HYPERV_VM_STATE_SHUTDOWN = 4 + _HYPERV_VM_STATE_PAUSED = 9 + + _WMI_JOB_STATUS_STARTED = 4096 + _WMI_JOB_STATE_RUNNING = 4 + _WMI_JOB_STATE_COMPLETED = 7 + + def __init__(self, controller): + + self._engine = "hyper-v" + super().__init__(controller) + self._conn = None + self._vm = None + self._management = None + + def _check_requirements(self): + """ + Checks if the GNS3 VM can run on Hyper-V. + """ + + if not sys.platform.startswith("win"): + raise GNS3VMError("Hyper-V is only supported on Windows") + + if sys.getwindowsversion().platform_version[0] < 10: + raise GNS3VMError("Windows 10/Windows Server 2016 or a later version is required to run Hyper-V with nested virtualization enabled (version {} detected)".format(sys.getwindowsversion().platform_version[0])) + + if sys.getwindowsversion().platform_version[0] == 10 and sys.getwindowsversion().platform_version[1] == 0: + if sys.getwindowsversion().platform_version[2] < 14393: + raise GNS3VMError("Hyper-V with nested virtualization is only supported on Windows 10 Anniversary Update (build 10.0.14393) or later") + + try: + conn = wmi.WMI() + except wmi.x_wmi as e: + raise GNS3VMError("Could not connect to WMI: {}".format(e)) + + if not conn.Win32_ComputerSystem()[0].HypervisorPresent: + raise GNS3VMError("Hyper-V is not installed or activated") + + if conn.Win32_Processor()[0].Manufacturer != "GenuineIntel": + raise GNS3VMError("An Intel processor is required by Hyper-V to support nested virtualization") + + # This is not reliable + #if not conn.Win32_Processor()[0].VirtualizationFirmwareEnabled: + # raise GNS3VMError("Nested Virtualization (VT-x) is not enabled on this system") + + def _connect(self): + """ + Connects to local host using WMI. + """ + + self._check_requirements() + + try: + self._conn = wmi.WMI(namespace=r"root\virtualization\v2") + except wmi.x_wmi as e: + raise GNS3VMError("Could not connect to WMI: {}".format(e)) + + if not self._conn.Msvm_VirtualSystemManagementService(): + raise GNS3VMError("The Windows account running GNS3 does not have the required permissions for Hyper-V") + + self._management = self._conn.Msvm_VirtualSystemManagementService()[0] + + def _find_vm(self, vm_name): + """ + Finds a Hyper-V VM. + """ + + if self._conn is None: + self._connect() + vms = self._conn.Msvm_ComputerSystem(ElementName=vm_name) + nb_vms = len(vms) + if nb_vms == 0: + return None + elif nb_vms > 1: + raise GNS3VMError("Duplicate VM name found for {}".format(vm_name)) + else: + return vms[0] + + def _is_running(self): + """ + Checks if the VM is running. + """ + + if self._vm is not None and self._vm.EnabledState == HyperVGNS3VM._HYPERV_VM_STATE_ENABLED: + return True + return False + + def _get_vm_setting_data(self, vm): + """ + Gets the VM settings. + + :param vm: VM instance + """ + + vm_settings = vm.associators(wmi_result_class='Msvm_VirtualSystemSettingData') + return [s for s in vm_settings if s.VirtualSystemType == 'Microsoft:Hyper-V:System:Realized'][0] + + def _get_vm_resources(self, vm, resource_class): + """ + Gets specific VM resource. + + :param vm: VM instance + :param resource_class: resource class name + """ + + setting_data = self._get_vm_setting_data(vm) + return setting_data.associators(wmi_result_class=resource_class) + + def _set_vcpus_ram(self, vcpus, ram): + """ + Set the number of vCPU cores and amount of RAM for the GNS3 VM. + + :param vcpus: number of vCPU cores + :param ram: amount of RAM + """ + + available_vcpus = psutil.cpu_count(logical=False) + if vcpus > available_vcpus: + raise GNS3VMError("You have allocated too many vCPUs for the GNS3 VM! (max available is {} vCPUs)".format(available_vcpus)) + + try: + mem_settings = self._get_vm_resources(self._vm, 'Msvm_MemorySettingData')[0] + cpu_settings = self._get_vm_resources(self._vm, 'Msvm_ProcessorSettingData')[0] + + mem_settings.VirtualQuantity = ram + mem_settings.Reservation = ram + mem_settings.Limit = ram + self._management.ModifyResourceSettings(ResourceSettings=[mem_settings.GetText_(1)]) + + cpu_settings.VirtualQuantity = vcpus + cpu_settings.Reservation = vcpus + cpu_settings.Limit = 100000 # use 100% of CPU + cpu_settings.ExposeVirtualizationExtensions = True # allow the VM to use nested virtualization + self._management.ModifyResourceSettings(ResourceSettings=[cpu_settings.GetText_(1)]) + + log.info("GNS3 VM vCPU count set to {} and RAM amount set to {}".format(vcpus, ram)) + except Exception as e: + raise GNS3VMError("Could not set to {} and RAM amount set to {}: {}".format(vcpus, ram, e)) + + async def list(self): + """ + List all Hyper-V VMs + """ + + if self._conn is None: + self._connect() + + vms = [] + try: + for vm in self._conn.Msvm_ComputerSystem(): + if vm.Caption == "Virtual Machine": + vms.append({"vmname": vm.ElementName}) + except wmi.x_wmi as e: + raise GNS3VMError("Could not list Hyper-V VMs: {}".format(e)) + return vms + + def _get_wmi_obj(self, path): + """ + Gets the WMI object. + """ + + return wmi.WMI(moniker=path.replace('\\', '/')) + + async def _set_state(self, state): + """ + Set the desired state of the VM + """ + + if not self._vm: + self._vm = self._find_vm(self.vmname) + if not self._vm: + raise GNS3VMError("Could not find Hyper-V VM {}".format(self.vmname)) + job_path, ret = self._vm.RequestStateChange(state) + if ret == HyperVGNS3VM._WMI_JOB_STATUS_STARTED: + job = self._get_wmi_obj(job_path) + while job.JobState == HyperVGNS3VM._WMI_JOB_STATE_RUNNING: + await asyncio.sleep(0.1) + job = self._get_wmi_obj(job_path) + if job.JobState != HyperVGNS3VM._WMI_JOB_STATE_COMPLETED: + raise GNS3VMError("Error while changing state: {}".format(job.ErrorSummaryDescription)) + elif ret != 0 or ret != 32775: + raise GNS3VMError("Failed to change state to {}".format(state)) + + async def start(self): + """ + Starts the GNS3 VM. + """ + + self._vm = self._find_vm(self.vmname) + if not self._vm: + raise GNS3VMError("Could not find Hyper-V VM {}".format(self.vmname)) + + if not self._is_running(): + + log.info("Update GNS3 VM settings") + # set the number of vCPUs and amount of RAM + self._set_vcpus_ram(self.vcpus, self.ram) + + # start the VM + try: + await self._set_state(HyperVGNS3VM._HYPERV_VM_STATE_ENABLED) + except GNS3VMError as e: + raise GNS3VMError("Failed to start the GNS3 VM: {}".format(e)) + log.info("GNS3 VM has been started") + + # Get the guest IP address + # LIS (Linux Integration Services) must be installed on the guest + # See https://oitibs.com/hyper-v-lis-on-ubuntu-18-04/ for details. + trial = 120 + guest_ip_address = "" + log.info("Waiting for GNS3 VM IP") + ports = self._get_vm_resources(self._vm, 'Msvm_EthernetPortAllocationSettingData') + vnics = self._get_vm_resources(self._vm, 'Msvm_SyntheticEthernetPortSettingData') + while True: + for port in ports: + vnic = [v for v in vnics if port.Parent == v.path_()][0] + config = vnic.associators(wmi_result_class='Msvm_GuestNetworkAdapterConfiguration') + ip_addresses = config[0].IPAddresses + for ip_address in ip_addresses: + # take the first valid IPv4 address + try: + ipaddress.IPv4Address(ip_address) + guest_ip_address = ip_address + except ipaddress.AddressValueError: + continue + if len(ip_addresses): + guest_ip_address = ip_addresses[0] + break + trial -= 1 + if guest_ip_address: + break + elif trial == 0: + raise GNS3VMError("Could not find guest IP address for {}".format(self.vmname)) + await asyncio.sleep(1) + self.ip_address = guest_ip_address + log.info("GNS3 VM IP address set to {}".format(guest_ip_address)) + self.running = True + + async def suspend(self): + """ + Suspends the GNS3 VM. + """ + + try: + await self._set_state(HyperVGNS3VM._HYPERV_VM_STATE_PAUSED) + except GNS3VMError as e: + raise GNS3VMError("Failed to suspend the GNS3 VM: {}".format(e)) + log.info("GNS3 VM has been suspended") + self.running = False + + async def stop(self): + """ + Stops the GNS3 VM. + """ + + try: + await self._set_state(HyperVGNS3VM._HYPERV_VM_STATE_SHUTDOWN) + except GNS3VMError as e: + raise GNS3VMError("Failed to stop the GNS3 VM: {}".format(e)) + log.info("GNS3 VM has been stopped") + self.running = False diff --git a/gns3server/controller/gns3vm/remote_gns3_vm.py b/gns3server/controller/gns3vm/remote_gns3_vm.py index 70d827a5..8ef533e4 100644 --- a/gns3server/controller/gns3vm/remote_gns3_vm.py +++ b/gns3server/controller/gns3vm/remote_gns3_vm.py @@ -32,8 +32,7 @@ class RemoteGNS3VM(BaseGNS3VM): self._engine = "remote" super().__init__(controller) - @asyncio.coroutine - def list(self): + async def list(self): """ List all VMs """ @@ -45,8 +44,7 @@ class RemoteGNS3VM(BaseGNS3VM): res.append({"vmname": compute.name}) return res - @asyncio.coroutine - def start(self): + async def start(self): """ Starts the GNS3 VM. """ @@ -65,15 +63,13 @@ class RemoteGNS3VM(BaseGNS3VM): return raise GNS3VMError("Can't start the GNS3 VM remote VM {} not found".format(self.vmname)) - @asyncio.coroutine - def suspend(self): + async def suspend(self): """ Suspend do nothing for remote server """ self.running = False - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops the GNS3 VM. """ diff --git a/gns3server/controller/gns3vm/virtualbox_gns3_vm.py b/gns3server/controller/gns3vm/virtualbox_gns3_vm.py index cad08b71..c1ee98e8 100644 --- a/gns3server/controller/gns3vm/virtualbox_gns3_vm.py +++ b/gns3server/controller/gns3vm/virtualbox_gns3_vm.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import sys import aiohttp import logging import asyncio @@ -39,24 +40,22 @@ class VirtualBoxGNS3VM(BaseGNS3VM): super().__init__(controller) self._virtualbox_manager = VirtualBox() - @asyncio.coroutine - def _execute(self, subcommand, args, timeout=60): + async def _execute(self, subcommand, args, timeout=60): try: - result = yield from self._virtualbox_manager.execute(subcommand, args, timeout) + result = await self._virtualbox_manager.execute(subcommand, args, timeout) return ("\n".join(result)) except VirtualBoxError as e: raise GNS3VMError("Error while executing VBoxManage command: {}".format(e)) - @asyncio.coroutine - def _get_state(self): + async def _get_state(self): """ Returns the VM state (e.g. running, paused etc.) :returns: state (string) """ - result = yield from self._execute("showvminfo", [self._vmname, "--machinereadable"]) + result = await self._execute("showvminfo", [self._vmname, "--machinereadable"]) for info in result.splitlines(): if '=' in info: name, value = info.split('=', 1) @@ -64,15 +63,14 @@ class VirtualBoxGNS3VM(BaseGNS3VM): return value.strip('"') return "unknown" - @asyncio.coroutine - def _look_for_interface(self, network_backend): + async def _look_for_interface(self, network_backend): """ Look for an interface with a specific network backend. :returns: interface number or -1 if none is found """ - result = yield from self._execute("showvminfo", [self._vmname, "--machinereadable"]) + result = await self._execute("showvminfo", [self._vmname, "--machinereadable"]) interface = -1 for info in result.splitlines(): if '=' in info: @@ -85,15 +83,14 @@ class VirtualBoxGNS3VM(BaseGNS3VM): continue return interface - @asyncio.coroutine - def _look_for_vboxnet(self, interface_number): + async def _look_for_vboxnet(self, interface_number): """ Look for the VirtualBox network name associated with a host only interface. :returns: None or vboxnet name """ - result = yield from self._execute("showvminfo", [self._vmname, "--machinereadable"]) + result = await self._execute("showvminfo", [self._vmname, "--machinereadable"]) for info in result.splitlines(): if '=' in info: name, value = info.split('=', 1) @@ -101,17 +98,15 @@ class VirtualBoxGNS3VM(BaseGNS3VM): return value.strip('"') return None - @asyncio.coroutine - def _check_dhcp_server(self, vboxnet): + async def _check_dhcp_server(self, vboxnet): """ Check if the DHCP server associated with a vboxnet is enabled. :param vboxnet: vboxnet name - :returns: boolean """ - properties = yield from self._execute("list", ["dhcpservers"]) + properties = await self._execute("list", ["dhcpservers"]) flag_dhcp_server_found = False for prop in properties.splitlines(): try: @@ -125,15 +120,47 @@ class VirtualBoxGNS3VM(BaseGNS3VM): return True return False - @asyncio.coroutine - def _check_vbox_port_forwarding(self): + async def _check_vboxnet_exists(self, vboxnet): + """ + Check if the vboxnet interface exists + + :param vboxnet: vboxnet name + :returns: boolean + """ + + properties = await self._execute("list", ["hostonlyifs"]) + for prop in properties.splitlines(): + try: + name, value = prop.split(':', 1) + except ValueError: + continue + if name.strip() == "Name" and value.strip() == vboxnet: + return True + return False + + async def _find_first_available_vboxnet(self): + """ + Find the first available vboxnet. + """ + + properties = await self._execute("list", ["hostonlyifs"]) + for prop in properties.splitlines(): + try: + name, value = prop.split(':', 1) + except ValueError: + continue + if name.strip() == "Name": + return value.strip() + return None + + async def _check_vbox_port_forwarding(self): """ Checks if the NAT port forwarding rule exists. :returns: boolean """ - result = yield from self._execute("showvminfo", [self._vmname, "--machinereadable"]) + result = await self._execute("showvminfo", [self._vmname, "--machinereadable"]) for info in result.splitlines(): if '=' in info: name, value = info.split('=', 1) @@ -141,78 +168,90 @@ class VirtualBoxGNS3VM(BaseGNS3VM): return True return False - @asyncio.coroutine - def list(self): + async def list(self): """ List all VirtualBox VMs """ - return (yield from self._virtualbox_manager.list_vms()) + return (await self._virtualbox_manager.list_vms()) - @asyncio.coroutine - def start(self): + async def start(self): """ Start the GNS3 VM. """ # get a NAT interface number - nat_interface_number = yield from self._look_for_interface("nat") + nat_interface_number = await self._look_for_interface("nat") if nat_interface_number < 0: - raise GNS3VMError("The GNS3 VM: {} must have a NAT interface configured in order to start".format(self.vmname)) + raise GNS3VMError('VM "{}" must have a NAT interface configured in order to start'.format(self.vmname)) - hostonly_interface_number = yield from self._look_for_interface("hostonly") + hostonly_interface_number = await self._look_for_interface("hostonly") if hostonly_interface_number < 0: - raise GNS3VMError("The GNS3 VM: {} must have a host only interface configured in order to start".format(self.vmname)) + raise GNS3VMError('VM "{}" must have a host-only interface configured in order to start'.format(self.vmname)) - vboxnet = yield from self._look_for_vboxnet(hostonly_interface_number) + vboxnet = await self._look_for_vboxnet(hostonly_interface_number) if vboxnet is None: - raise GNS3VMError("VirtualBox host-only network could not be found for interface {} on GNS3 VM".format(hostonly_interface_number)) + raise GNS3VMError('A VirtualBox host-only network could not be found on network adapter {} for "{}"'.format(hostonly_interface_number, self._vmname)) - if not (yield from self._check_dhcp_server(vboxnet)): - raise GNS3VMError("DHCP must be enabled on VirtualBox host-only network: {} for GNS3 VM".format(vboxnet)) + if not (await self._check_vboxnet_exists(vboxnet)): + if sys.platform.startswith("win") and vboxnet == "vboxnet0": + # The GNS3 VM is configured with vboxnet0 by default which is not available + # on Windows. Try to patch this with the first available vboxnet we find. + first_available_vboxnet = await self._find_first_available_vboxnet() + if first_available_vboxnet is None: + raise GNS3VMError('Please add a VirtualBox host-only network with DHCP enabled and attached it to network adapter {} for "{}"'.format(hostonly_interface_number, self._vmname)) + await self.set_hostonly_network(hostonly_interface_number, first_available_vboxnet) + vboxnet = first_available_vboxnet + else: + raise GNS3VMError('VirtualBox host-only network "{}" does not exist, please make the sure the network adapter {} configuration is valid for "{}"'.format(vboxnet, + hostonly_interface_number, + self._vmname)) - vm_state = yield from self._get_state() + if not (await self._check_dhcp_server(vboxnet)): + raise GNS3VMError('DHCP must be enabled on VirtualBox host-only network "{}"'.format(vboxnet)) + + vm_state = await self._get_state() log.info('"{}" state is {}'.format(self._vmname, vm_state)) if vm_state == "poweroff": - yield from self.set_vcpus(self.vcpus) - yield from self.set_ram(self.ram) + await self.set_vcpus(self.vcpus) + await self.set_ram(self.ram) if vm_state in ("poweroff", "saved"): # start the VM if it is not running args = [self._vmname] if self._headless: args.extend(["--type", "headless"]) - yield from self._execute("startvm", args) + await self._execute("startvm", args) elif vm_state == "paused": args = [self._vmname, "resume"] - yield from self._execute("controlvm", args) + await self._execute("controlvm", args) ip_address = "127.0.0.1" try: # get a random port on localhost with socket.socket() as s: + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((ip_address, 0)) api_port = s.getsockname()[1] except OSError as e: raise GNS3VMError("Error while getting random port: {}".format(e)) - if (yield from self._check_vbox_port_forwarding()): + if (await self._check_vbox_port_forwarding()): # delete the GNS3VM NAT port forwarding rule if it exists log.info("Removing GNS3VM NAT port forwarding rule from interface {}".format(nat_interface_number)) - yield from self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number), "delete", "GNS3VM"]) + await self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number), "delete", "GNS3VM"]) # add a GNS3VM NAT port forwarding rule to redirect 127.0.0.1 with random port to port 3080 in the VM log.info("Adding GNS3VM NAT port forwarding rule with port {} to interface {}".format(api_port, nat_interface_number)) - yield from self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number), + await self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number), "GNS3VM,tcp,{},{},,3080".format(ip_address, api_port)]) - self.ip_address = yield from self._get_ip(hostonly_interface_number, api_port) + self.ip_address = await self._get_ip(hostonly_interface_number, api_port) self.port = 3080 log.info("GNS3 VM has been started with IP {}".format(self.ip_address)) self.running = True - @asyncio.coroutine - def _get_ip(self, hostonly_interface_number, api_port): + async def _get_ip(self, hostonly_interface_number, api_port): """ Get the IP from VirtualBox. @@ -222,59 +261,50 @@ class VirtualBoxGNS3VM(BaseGNS3VM): """ remaining_try = 300 while remaining_try > 0: - json_data = None - session = aiohttp.ClientSession() - try: - resp = None - resp = yield from session.get('http://127.0.0.1:{}/v2/compute/network/interfaces'.format(api_port)) - except (OSError, aiohttp.ClientError, TimeoutError, asyncio.TimeoutError): - pass - - if resp: - if resp.status < 300: - try: - json_data = yield from resp.json() - except ValueError: - pass - resp.close() - - session.close() - - if json_data: - for interface in json_data: - if "name" in interface and interface["name"] == "eth{}".format(hostonly_interface_number - 1): - if "ip_address" in interface and len(interface["ip_address"]) > 0: - return interface["ip_address"] + async with aiohttp.ClientSession() as session: + try: + async with session.get('http://127.0.0.1:{}/v2/compute/network/interfaces'.format(api_port)) as resp: + if resp.status < 300: + try: + json_data = await resp.json() + if json_data: + for interface in json_data: + if "name" in interface and interface["name"] == "eth{}".format( + hostonly_interface_number - 1): + if "ip_address" in interface and len(interface["ip_address"]) > 0: + return interface["ip_address"] + except ValueError: + pass + except (OSError, aiohttp.ClientError, TimeoutError, asyncio.TimeoutError): + pass remaining_try -= 1 - yield from asyncio.sleep(1) + await asyncio.sleep(1) raise GNS3VMError("Could not get the GNS3 VM ip make sure the VM receive an IP from VirtualBox") - @asyncio.coroutine - def suspend(self): + async def suspend(self): """ Suspend the GNS3 VM. """ - yield from self._execute("controlvm", [self._vmname, "savestate"], timeout=3) + await self._execute("controlvm", [self._vmname, "savestate"], timeout=3) log.info("GNS3 VM has been suspend") self.running = False - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops the GNS3 VM. """ - vm_state = yield from self._get_state() + vm_state = await self._get_state() if vm_state == "poweroff": self.running = False return - yield from self._execute("controlvm", [self._vmname, "acpipowerbutton"], timeout=3) + await self._execute("controlvm", [self._vmname, "acpipowerbutton"], timeout=3) trial = 120 while True: try: - vm_state = yield from self._get_state() + vm_state = await self._get_state() # During a small amount of time the command will fail except GNS3VMError: vm_state = "running" @@ -282,31 +312,42 @@ class VirtualBoxGNS3VM(BaseGNS3VM): break trial -= 1 if trial == 0: - yield from self._execute("controlvm", [self._vmname, "poweroff"], timeout=3) + await self._execute("controlvm", [self._vmname, "poweroff"], timeout=3) break - yield from asyncio.sleep(1) + await asyncio.sleep(1) log.info("GNS3 VM has been stopped") self.running = False - @asyncio.coroutine - def set_vcpus(self, vcpus): + async def set_vcpus(self, vcpus): """ Set the number of vCPU cores for the GNS3 VM. :param vcpus: number of vCPU cores """ - yield from self._execute("modifyvm", [self._vmname, "--cpus", str(vcpus)], timeout=3) + await self._execute("modifyvm", [self._vmname, "--cpus", str(vcpus)], timeout=3) log.info("GNS3 VM vCPU count set to {}".format(vcpus)) - @asyncio.coroutine - def set_ram(self, ram): + async def set_ram(self, ram): """ Set the RAM amount for the GNS3 VM. :param ram: amount of memory """ - yield from self._execute("modifyvm", [self._vmname, "--memory", str(ram)], timeout=3) + await self._execute("modifyvm", [self._vmname, "--memory", str(ram)], timeout=3) log.info("GNS3 VM RAM amount set to {}".format(ram)) + + async def set_hostonly_network(self, adapter_number, hostonly_network_name): + """ + Set a VirtualBox host-only network on a network adapter for the GNS3 VM. + + :param adapter_number: network adapter number + :param hostonly_network_name: name of the VirtualBox host-only network + """ + + await self._execute("modifyvm", [self._vmname, "--hostonlyadapter{}".format(adapter_number), hostonly_network_name], timeout=3) + log.info('VirtualBox host-only network "{}" set on network adapter {} for "{}"'.format(hostonly_network_name, + adapter_number, + self._vmname)) diff --git a/gns3server/controller/gns3vm/vmware_gns3_vm.py b/gns3server/controller/gns3vm/vmware_gns3_vm.py index c14f0732..02b6afb9 100644 --- a/gns3server/controller/gns3vm/vmware_gns3_vm.py +++ b/gns3server/controller/gns3vm/vmware_gns3_vm.py @@ -43,24 +43,21 @@ class VMwareGNS3VM(BaseGNS3VM): def vmx_path(self): return self._vmx_path - @asyncio.coroutine - def _execute(self, subcommand, args, timeout=60, log_level=logging.INFO): + async def _execute(self, subcommand, args, timeout=60, log_level=logging.INFO): try: - result = yield from self._vmware_manager.execute(subcommand, args, timeout, log_level=log_level) + result = await self._vmware_manager.execute(subcommand, args, timeout, log_level=log_level) return (''.join(result)) except VMwareError as e: raise GNS3VMError("Error while executing VMware command: {}".format(e)) - @asyncio.coroutine - def _is_running(self): - result = yield from self._vmware_manager.execute("list", []) + async def _is_running(self): + result = await self._vmware_manager.execute("list", []) if self._vmx_path in result: return True return False - @asyncio.coroutine - def _set_vcpus_ram(self, vcpus, ram): + async def _set_vcpus_ram(self, vcpus, ram): """ Set the number of vCPU cores and amount of RAM for the GNS3 VM. @@ -72,21 +69,24 @@ class VMwareGNS3VM(BaseGNS3VM): if ram % 4 != 0: raise GNS3VMError("Allocated memory {} for the GNS3 VM must be a multiple of 4".format(ram)) - available_vcpus = psutil.cpu_count(logical=False) + available_vcpus = psutil.cpu_count(logical=True) if vcpus > available_vcpus: raise GNS3VMError("You have allocated too many vCPUs for the GNS3 VM! (max available is {} vCPUs)".format(available_vcpus)) try: pairs = VMware.parse_vmware_file(self._vmx_path) - pairs["numvcpus"] = str(vcpus) - pairs["memsize"] = str(ram) - VMware.write_vmx_file(self._vmx_path, pairs) + if vcpus > 1: + pairs["numvcpus"] = str(vcpus) + cores_per_sockets = int(vcpus / psutil.cpu_count(logical=False)) + if cores_per_sockets > 1: + pairs["cpuid.corespersocket"] = str(cores_per_sockets) + pairs["memsize"] = str(ram) + VMware.write_vmx_file(self._vmx_path, pairs) log.info("GNS3 VM vCPU count set to {} and RAM amount set to {}".format(vcpus, ram)) except OSError as e: raise GNS3VMError('Could not read/write VMware VMX file "{}": {}'.format(self._vmx_path, e)) - @asyncio.coroutine - def _set_extra_options(self): + async def _set_extra_options(self): try: """ Due to bug/change in VMWare 14 we're not able to pass Hardware Virtualization in GNS3VM. @@ -109,23 +109,21 @@ class VMwareGNS3VM(BaseGNS3VM): except OSError as e: raise GNS3VMError('Could not read/write VMware VMX file "{}": {}'.format(self._vmx_path, e)) - @asyncio.coroutine - def list(self): + async def list(self): """ List all VMware VMs """ try: - return (yield from self._vmware_manager.list_vms()) + return (await self._vmware_manager.list_vms()) except VMwareError as e: raise GNS3VMError("Could not list VMware VMs: {}".format(str(e))) - @asyncio.coroutine - def start(self): + async def start(self): """ Starts the GNS3 VM. """ - vms = yield from self.list() + vms = await self.list() for vm in vms: if vm["vmname"] == self.vmname: self._vmx_path = vm["vmx_path"] @@ -138,25 +136,25 @@ class VMwareGNS3VM(BaseGNS3VM): raise GNS3VMError("VMware VMX file {} doesn't exist".format(self._vmx_path)) # check if the VMware guest tools are installed - vmware_tools_state = yield from self._execute("checkToolsState", [self._vmx_path]) + vmware_tools_state = await self._execute("checkToolsState", [self._vmx_path]) if vmware_tools_state not in ("installed", "running"): raise GNS3VMError("VMware tools are not installed in {}".format(self.vmname)) try: - running = yield from self._is_running() + running = await self._is_running() except VMwareError as e: raise GNS3VMError("Could not list VMware VMs: {}".format(str(e))) if not running: log.info("Update GNS3 VM settings") # set the number of vCPUs and amount of RAM - yield from self._set_vcpus_ram(self.vcpus, self.ram) - yield from self._set_extra_options() + await self._set_vcpus_ram(self.vcpus, self.ram) + await self._set_extra_options() # start the VM args = [self._vmx_path] if self._headless: args.extend(["nogui"]) - yield from self._execute("start", args) + await self._execute("start", args) log.info("GNS3 VM has been started") # get the guest IP address (first adapter only) @@ -164,7 +162,7 @@ class VMwareGNS3VM(BaseGNS3VM): guest_ip_address = "" log.info("Waiting for GNS3 VM IP") while True: - guest_ip_address = yield from self._execute("readVariable", [self._vmx_path, "guestVar", "gns3.eth0"], timeout=120, log_level=logging.DEBUG) + guest_ip_address = await self._execute("readVariable", [self._vmx_path, "guestVar", "gns3.eth0"], timeout=120, log_level=logging.DEBUG) guest_ip_address = guest_ip_address.strip() if len(guest_ip_address) != 0: break @@ -172,15 +170,14 @@ class VMwareGNS3VM(BaseGNS3VM): # If ip not found fallback on old method if trial == 0: log.warning("No IP found for the VM via readVariable fallback to getGuestIPAddress") - guest_ip_address = yield from self._execute("getGuestIPAddress", [self._vmx_path, "-wait"], timeout=120) + guest_ip_address = await self._execute("getGuestIPAddress", [self._vmx_path, "-wait"], timeout=120) break - yield from asyncio.sleep(1) + await asyncio.sleep(1) self.ip_address = guest_ip_address log.info("GNS3 VM IP address set to {}".format(guest_ip_address)) self.running = True - @asyncio.coroutine - def suspend(self): + async def suspend(self): """ Suspend the GNS3 VM. """ @@ -188,14 +185,13 @@ class VMwareGNS3VM(BaseGNS3VM): if self._vmx_path is None: raise GNS3VMError("No VMX path configured, can't suspend the VM") try: - yield from self._execute("suspend", [self._vmx_path]) + await self._execute("suspend", [self._vmx_path]) except GNS3VMError as e: log.warning("Error when suspending the VM: {}".format(str(e))) log.info("GNS3 VM has been suspended") self.running = False - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stops the GNS3 VM. """ @@ -203,7 +199,7 @@ class VMwareGNS3VM(BaseGNS3VM): if self._vmx_path is None: raise GNS3VMError("No VMX path configured, can't stop the VM") try: - yield from self._execute("stop", [self._vmx_path, "soft"]) + await self._execute("stop", [self._vmx_path, "soft"]) except GNS3VMError as e: log.warning("Error when stopping the VM: {}".format(str(e))) log.info("GNS3 VM has been stopped") diff --git a/gns3server/controller/import_project.py b/gns3server/controller/import_project.py index 33329614..eb76ceb1 100644 --- a/gns3server/controller/import_project.py +++ b/gns3server/controller/import_project.py @@ -20,25 +20,26 @@ import sys import json import uuid import shutil -import asyncio import zipfile import aiohttp import itertools from .topology import load_topology +from ..utils.asyncio import wait_run_in_executor +import logging +log = logging.getLogger(__name__) """ Handle the import of project from a .gns3project """ -@asyncio.coroutine -def import_project(controller, project_id, stream, location=None, name=None, keep_compute_id=False): +async def import_project(controller, project_id, stream, location=None, name=None, keep_compute_id=False): """ Import a project contain in a zip file - You need to handle OSerror exceptions + You must handle OSError exceptions :param controller: GNS3 Controller :param project_id: ID of the project to import @@ -46,6 +47,7 @@ def import_project(controller, project_id, stream, location=None, name=None, kee :param location: Directory for the project if None put in the default directory :param name: Wanted project name, generate one from the .gns3 if None :param keep_compute_id: If true do not touch the compute id + :returns: Project """ @@ -53,115 +55,126 @@ def import_project(controller, project_id, stream, location=None, name=None, kee raise aiohttp.web.HTTPConflict(text="The destination path should not contain .gns3") try: - with zipfile.ZipFile(stream) as myzip: - - try: - topology = json.loads(myzip.read("project.gns3").decode()) - - # We import the project on top of an existing project (snapshots) - if topology["project_id"] == project_id: - project_name = topology["name"] - else: - # If the project name is already used we generate a new one - if name: - project_name = controller.get_free_project_name(name) - else: - project_name = controller.get_free_project_name(topology["name"]) - except KeyError: - raise aiohttp.web.HTTPConflict(text="Can't import topology the .gns3 is corrupted or missing") - - if location: - path = location - else: - projects_path = controller.projects_directory() - path = os.path.join(projects_path, project_id) - try: - os.makedirs(path, exist_ok=True) - except UnicodeEncodeError as e: - raise aiohttp.web.HTTPConflict(text="The project name contain non supported or invalid characters") - myzip.extractall(path) - - topology = load_topology(os.path.join(path, "project.gns3")) - topology["name"] = project_name - # To avoid unexpected behavior (project start without manual operations just after import) - topology["auto_start"] = False - topology["auto_open"] = False - topology["auto_close"] = True - - # Generate a new node id - node_old_to_new = {} - for node in topology["topology"]["nodes"]: - if "node_id" in node: - node_old_to_new[node["node_id"]] = str(uuid.uuid4()) - _move_node_file(path, node["node_id"], node_old_to_new[node["node_id"]]) - node["node_id"] = node_old_to_new[node["node_id"]] - else: - node["node_id"] = str(uuid.uuid4()) - - # Update link to use new id - for link in topology["topology"]["links"]: - link["link_id"] = str(uuid.uuid4()) - for node in link["nodes"]: - node["node_id"] = node_old_to_new[node["node_id"]] - - # Generate new drawings id - for drawing in topology["topology"]["drawings"]: - drawing["drawing_id"] = str(uuid.uuid4()) - - # Modify the compute id of the node depending of compute capacity - if not keep_compute_id: - # For some VM type we move them to the GNS3 VM if possible - # unless it's a linux host without GNS3 VM - if not sys.platform.startswith("linux") or controller.has_compute("vm"): - for node in topology["topology"]["nodes"]: - if node["node_type"] in ("docker", "qemu", "iou", "nat"): - node["compute_id"] = "vm" - else: - # Round-robin through available compute resources. - compute_nodes = itertools.cycle(controller.computes) - for node in topology["topology"]["nodes"]: - node["compute_id"] = next(compute_nodes) - - compute_created = set() - for node in topology["topology"]["nodes"]: - - if node["compute_id"] != "local": - # Project created on the remote GNS3 VM? - if node["compute_id"] not in compute_created: - compute = controller.get_compute(node["compute_id"]) - yield from compute.post("/projects", data={ - "name": project_name, - "project_id": project_id, - }) - compute_created.add(node["compute_id"]) - - yield from _move_files_to_compute(compute, project_id, path, os.path.join("project-files", node["node_type"], node["node_id"])) - - # And we dump the updated.gns3 - dot_gns3_path = os.path.join(path, project_name + ".gns3") - # We change the project_id to avoid erasing the project - topology["project_id"] = project_id - with open(dot_gns3_path, "w+") as f: - json.dump(topology, f, indent=4) - os.remove(os.path.join(path, "project.gns3")) - - if os.path.exists(os.path.join(path, "images")): - _import_images(controller, path) - - project = yield from controller.load_project(dot_gns3_path, load=False) - return project + with zipfile.ZipFile(stream) as zip_file: + project_file = zip_file.read("project.gns3").decode() except zipfile.BadZipFile: - raise aiohttp.web.HTTPConflict(text="Can't import topology the file is corrupted or not a GNS3 project (invalid zip)") + raise aiohttp.web.HTTPConflict(text="Cannot import project, not a GNS3 project (invalid zip)") + except KeyError: + raise aiohttp.web.HTTPConflict(text="Cannot import project, project.gns3 file could not be found") + + try: + topology = json.loads(project_file) + # We import the project on top of an existing project (snapshots) + if topology["project_id"] == project_id: + project_name = topology["name"] + else: + # If the project name is already used we generate a new one + if name: + project_name = controller.get_free_project_name(name) + else: + project_name = controller.get_free_project_name(topology["name"]) + except (ValueError, KeyError): + raise aiohttp.web.HTTPConflict(text="Cannot import project, the project.gns3 file is corrupted") + + if location: + path = location + else: + projects_path = controller.projects_directory() + path = os.path.join(projects_path, project_id) + try: + os.makedirs(path, exist_ok=True) + except UnicodeEncodeError: + raise aiohttp.web.HTTPConflict(text="The project name contain non supported or invalid characters") + + try: + with zipfile.ZipFile(stream) as zip_file: + await wait_run_in_executor(zip_file.extractall, path) + except zipfile.BadZipFile: + raise aiohttp.web.HTTPConflict(text="Cannot extract files from GNS3 project (invalid zip)") + + topology = load_topology(os.path.join(path, "project.gns3")) + topology["name"] = project_name + # To avoid unexpected behavior (project start without manual operations just after import) + topology["auto_start"] = False + topology["auto_open"] = False + topology["auto_close"] = True + + # Generate a new node id + node_old_to_new = {} + for node in topology["topology"]["nodes"]: + if "node_id" in node: + node_old_to_new[node["node_id"]] = str(uuid.uuid4()) + _move_node_file(path, node["node_id"], node_old_to_new[node["node_id"]]) + node["node_id"] = node_old_to_new[node["node_id"]] + else: + node["node_id"] = str(uuid.uuid4()) + + # Update link to use new id + for link in topology["topology"]["links"]: + link["link_id"] = str(uuid.uuid4()) + for node in link["nodes"]: + node["node_id"] = node_old_to_new[node["node_id"]] + + # Generate new drawings id + for drawing in topology["topology"]["drawings"]: + drawing["drawing_id"] = str(uuid.uuid4()) + + # Modify the compute id of the node depending of compute capacity + if not keep_compute_id: + # For some VM type we move them to the GNS3 VM if possible + # unless it's a linux host without GNS3 VM + if not sys.platform.startswith("linux") or controller.has_compute("vm"): + for node in topology["topology"]["nodes"]: + if node["node_type"] in ("docker", "qemu", "iou", "nat"): + node["compute_id"] = "vm" + else: + # Round-robin through available compute resources. + # computes = [] + # for compute_id in controller.computes: + # compute = controller.get_compute(compute_id) + # # only use the local compute or any connected compute + # if compute_id == "local" or compute.connected: + # computes.append(compute_id) + # else: + # log.warning(compute.name, "is not connected!") + compute_nodes = itertools.cycle(controller.computes) + for node in topology["topology"]["nodes"]: + node["compute_id"] = next(compute_nodes) + + compute_created = set() + for node in topology["topology"]["nodes"]: + if node["compute_id"] != "local": + # Project created on the remote GNS3 VM? + if node["compute_id"] not in compute_created: + compute = controller.get_compute(node["compute_id"]) + await compute.post("/projects", data={"name": project_name, "project_id": project_id,}) + compute_created.add(node["compute_id"]) + await _move_files_to_compute(compute, project_id, path, os.path.join("project-files", node["node_type"], node["node_id"])) + + # And we dump the updated.gns3 + dot_gns3_path = os.path.join(path, project_name + ".gns3") + # We change the project_id to avoid erasing the project + topology["project_id"] = project_id + with open(dot_gns3_path, "w+") as f: + json.dump(topology, f, indent=4) + os.remove(os.path.join(path, "project.gns3")) + + if os.path.exists(os.path.join(path, "images")): + _import_images(controller, path) + + project = await controller.load_project(dot_gns3_path, load=False) + return project def _move_node_file(path, old_id, new_id): """ - Move the files from a node when changing his id + Move a file from a node when changing its id :param path: Path of the project :param old_id: ID before change :param new_id: New node UUID """ + root = os.path.join(path, "project-files") if os.path.exists(root): for dirname in os.listdir(root): @@ -172,45 +185,48 @@ def _move_node_file(path, old_id, new_id): shutil.move(node_dir, os.path.join(module_dir, new_id)) -@asyncio.coroutine -def _move_files_to_compute(compute, project_id, directory, files_path): +async def _move_files_to_compute(compute, project_id, directory, files_path): """ - Move the files to a remote compute + Move files to a remote compute """ + location = os.path.join(directory, files_path) if os.path.exists(location): - for (dirpath, dirnames, filenames) in os.walk(location): + for (dirpath, dirnames, filenames) in os.walk(location, followlinks=False): for filename in filenames: path = os.path.join(dirpath, filename) + if os.path.islink(path): + continue dst = os.path.relpath(path, directory) - yield from _upload_file(compute, project_id, path, dst) - shutil.rmtree(os.path.join(directory, files_path)) + await _upload_file(compute, project_id, path, dst) + await wait_run_in_executor(shutil.rmtree, os.path.join(directory, files_path)) -@asyncio.coroutine -def _upload_file(compute, project_id, file_path, path): +async def _upload_file(compute, project_id, file_path, path): """ Upload a file to a remote project :param file_path: File path on the controller file system :param path: File path on the remote system relative to project directory """ + path = "/projects/{}/files/{}".format(project_id, path.replace("\\", "/")) with open(file_path, "rb") as f: - yield from compute.http_query("POST", path, f, timeout=None) + await compute.http_query("POST", path, f, timeout=None) def _import_images(controller, path): """ - Copy images to the images directory or delete them if they - already exists. + Copy images to the images directory or delete them if they already exists. """ - image_dir = controller.images_path() + image_dir = controller.images_path() root = os.path.join(path, "images") - for (dirpath, dirnames, filenames) in os.walk(root): + for (dirpath, dirnames, filenames) in os.walk(root, followlinks=False): for filename in filenames: path = os.path.join(dirpath, filename) + if os.path.islink(path): + continue dst = os.path.join(image_dir, os.path.relpath(path, root)) os.makedirs(os.path.dirname(dst), exist_ok=True) shutil.move(path, dst) diff --git a/gns3server/controller/link.py b/gns3server/controller/link.py index fc3febb4..60e19612 100644 --- a/gns3server/controller/link.py +++ b/gns3server/controller/link.py @@ -19,7 +19,6 @@ import os import re import uuid import html -import asyncio import aiohttp import logging @@ -118,11 +117,12 @@ class Link: self._nodes = [] self._project = project self._capturing = False + self._capture_node = None self._capture_file_name = None self._streaming_pcap = None self._created = False self._link_type = "ethernet" - self._suspend = False + self._suspended = False self._filters = {} @property @@ -139,17 +139,45 @@ class Link: """ return self._nodes + @property + def project(self): + """ + Get the project this link belongs to. + + :return: Project instance. + """ + return self._project + + @property + def capture_node(self): + """ + Get the capturing node + + :return: Node instance. + """ + return self._capture_node + + @property + def compute(self): + """ + Get the capturing node + + :return: Node instance. + """ + assert self.capture_node + return self.capture_node["node"].compute + def get_active_filters(self): """ Return the active filters. Filters are overridden if the link is suspended. """ - if self._suspend: + if self._suspended: + # this is to allow all node types to support suspend link return {"frequency_drop": [-1]} return self._filters - @asyncio.coroutine - def update_filters(self, filters): + async def update_filters(self, filters): """ Modify the filters list. @@ -170,16 +198,15 @@ class Link: if new_filters != self.filters: self._filters = new_filters if self._created: - yield from self.update() - self._project.controller.notification.emit("link.updated", self.__json__()) + await self.update() + self._project.emit_notification("link.updated", self.__json__()) self._project.dump() - @asyncio.coroutine - def update_suspend(self, value): - if value != self._suspend: - self._suspend = value - yield from self.update() - self._project.controller.notification.emit("link.updated", self.__json__()) + async def update_suspend(self, value): + if value != self._suspended: + self._suspended = value + await self.update() + self._project.emit_notification("link.updated", self.__json__()) self._project.dump() @property @@ -189,8 +216,7 @@ class Link: """ return self._created - @asyncio.coroutine - def add_node(self, node, adapter_number, port_number, label=None, dump=True): + async def add_node(self, node, adapter_number, port_number, label=None, dump=True): """ Add a node to the link @@ -211,14 +237,14 @@ class Link: if node.node_type in ["nat", "cloud"]: if other_node["node"].node_type in ["nat", "cloud"]: - raise aiohttp.web.HTTPConflict(text="It's not allowed to connect a {} to a {}".format(other_node["node"].node_type, node.node_type)) + raise aiohttp.web.HTTPConflict(text="Connecting a {} to a {} is not allowed".format(other_node["node"].node_type, node.node_type)) # Check if user is not connecting serial => ethernet other_port = other_node["node"].get_port(other_node["adapter_number"], other_node["port_number"]) if other_port is None: raise aiohttp.web.HTTPNotFound(text="Port {}/{} for {} not found".format(other_node["adapter_number"], other_node["port_number"], other_node["node"].name)) if port.link_type != other_port.link_type: - raise aiohttp.web.HTTPConflict(text="It's not allowed to connect a {} to a {}".format(other_port.link_type, port.link_type)) + raise aiohttp.web.HTTPConflict(text="Connecting a {} interface to a {} interface is not allowed".format(other_port.link_type, port.link_type)) if label is None: label = { @@ -238,18 +264,17 @@ class Link: }) if len(self._nodes) == 2: - yield from self.create() + await self.create() for n in self._nodes: n["node"].add_link(self) n["port"].link = self self._created = True - self._project.controller.notification.emit("link.created", self.__json__()) + self._project.emit_notification("link.created", self.__json__()) if dump: self._project.dump() - @asyncio.coroutine - def update_nodes(self, nodes): + async def update_nodes(self, nodes): for node_data in nodes: node = self._project.get_node(node_data["node_id"]) for port in self._nodes: @@ -257,26 +282,23 @@ class Link: label = node_data.get("label") if label: port["label"] = label - self._project.controller.notification.emit("link.updated", self.__json__()) + self._project.emit_notification("link.updated", self.__json__()) self._project.dump() - @asyncio.coroutine - def create(self): + async def create(self): """ Create the link """ raise NotImplementedError - @asyncio.coroutine - def update(self): + async def update(self): """ Update a link """ raise NotImplementedError - @asyncio.coroutine - def delete(self): + async def delete(self): """ Delete the link """ @@ -286,8 +308,7 @@ class Link: n["port"].link = None n["node"].remove_link(self) - @asyncio.coroutine - def start_capture(self, data_link_type="DLT_EN10MB", capture_file_name=None): + async def start_capture(self, data_link_type="DLT_EN10MB", capture_file_name=None): """ Start capture on the link @@ -296,64 +317,38 @@ class Link: self._capturing = True self._capture_file_name = capture_file_name - self._streaming_pcap = asyncio.async(self._start_streaming_pcap()) - self._project.controller.notification.emit("link.updated", self.__json__()) + self._project.emit_notification("link.updated", self.__json__()) - @asyncio.coroutine - def _start_streaming_pcap(self): - """ - Dump a pcap file on disk - """ - - if os.path.exists(self.capture_file_path): - try: - os.remove(self.capture_file_path) - except OSError as e: - raise aiohttp.web.HTTPConflict(text="Could not delete old capture file '{}': {}".format(self.capture_file_path, e)) - - try: - stream_content = yield from self.read_pcap_from_source() - except aiohttp.web.HTTPException as e: - error_msg = "Could not stream PCAP file: error {}: {}".format(e.status, e.text) - log.error(error_msg) - self._capturing = False - self._project.notification.emit("log.error", {"message": error_msg}) - self._project.controller.notification.emit("link.updated", self.__json__()) - - with stream_content as stream: - try: - with open(self.capture_file_path, "wb") as f: - while self._capturing: - # We read 1 bytes by 1 otherwise the remaining data is not read if the traffic stops - data = yield from stream.read(1) - if data: - f.write(data) - # Flush to disk otherwise the live is not really live - f.flush() - else: - break - except OSError as e: - raise aiohttp.web.HTTPConflict(text="Could not write capture file '{}': {}".format(self.capture_file_path, e)) - - @asyncio.coroutine - def stop_capture(self): + async def stop_capture(self): """ Stop capture on the link """ self._capturing = False - self._project.controller.notification.emit("link.updated", self.__json__()) + self._project.emit_notification("link.updated", self.__json__()) - @asyncio.coroutine - def _read_pcap_from_source(self): + def pcap_streaming_url(self): """ - Return a FileStream of the Pcap from the compute server + Get the PCAP streaming URL on compute + + :returns: URL """ - raise NotImplementedError + assert self.capture_node + compute = self.capture_node["node"].compute + node_type = self.capture_node["node"].node_type + node_id = self.capture_node["node"].id + adapter_number = self.capture_node["adapter_number"] + port_number = self.capture_node["port_number"] + url = "/projects/{project_id}/{node_type}/nodes/{node_id}/adapters/{adapter_number}/ports/{port_number}/pcap".format(project_id=self.project.id, + node_type=node_type, + node_id=node_id, + adapter_number=adapter_number, + port_number=port_number) - @asyncio.coroutine - def node_updated(self, node): + return compute._getUrl(url) + + async def node_updated(self, node): """ Called when a node member of the link is updated """ @@ -370,7 +365,7 @@ class Link: self._nodes[1]["node"].name, self._nodes[1]["adapter_number"], self._nodes[1]["port_number"]) - return re.sub("[^0-9A-Za-z_-]", "", capture_file_name) + ".pcap" + return re.sub(r"[^0-9A-Za-z_-]", "", capture_file_name) + ".pcap" @property def id(self): @@ -395,6 +390,17 @@ class Link: else: return None + @property + def capture_compute_id(self): + """ + Get the capture compute ID. + """ + + if self._capture_node: + return self.capture_node["node"].compute.id + else: + return None + def available_filters(self): """ Return the list of filters compatible with this link @@ -414,6 +420,7 @@ class Link: """ for node in self._nodes: if node["node"].node_type in ('vpcs', + 'traceng', 'vmware', 'dynamips', 'qemu', @@ -450,7 +457,7 @@ class Link: "nodes": res, "link_id": self._id, "filters": self._filters, - "suspend": self._suspend + "suspend": self._suspended } return { "nodes": res, @@ -459,7 +466,8 @@ class Link: "capturing": self._capturing, "capture_file_name": self._capture_file_name, "capture_file_path": self.capture_file_path, + "capture_compute_id": self.capture_compute_id, "link_type": self._link_type, "filters": self._filters, - "suspend": self._suspend + "suspend": self._suspended } diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py index f960a8cf..4d8e81d9 100644 --- a/gns3server/controller/node.py +++ b/gns3server/controller/node.py @@ -22,7 +22,6 @@ import copy import uuid import os - from .compute import ComputeConflict, ComputeError from .ports.port_factory import PortFactory, StandardPortFactory, DynamipsPortFactory from ..utils.images import images_directories @@ -35,17 +34,18 @@ log = logging.getLogger(__name__) class Node: # This properties are used only on controller and are not forwarded to the compute - CONTROLLER_ONLY_PROPERTIES = ["x", "y", "z", "width", "height", "symbol", "label", "console_host", + CONTROLLER_ONLY_PROPERTIES = ["x", "y", "z", "locked", "width", "height", "symbol", "label", "console_host", "port_name_format", "first_port_name", "port_segment_size", "ports", - "category"] + "category", "console_auto_start"] - def __init__(self, project, compute, name, node_id=None, node_type=None, **kwargs): + def __init__(self, project, compute, name, node_id=None, node_type=None, template_id=None, **kwargs): """ :param project: Project of the node - :param compute: Compute server where the server will run + :param compute: Compute where the server will run :param name: Node name :param node_id: UUID of the node (integer) :param node_type: Type of emulator + :param template_id: Template ID used to create this node :param kwargs: Node properties """ @@ -70,11 +70,14 @@ class Node: self._command_line = None self._node_directory = None self._status = "stopped" + self._template_id = template_id self._x = 0 self._y = 0 - self._z = 0 + self._z = 1 # default z value is 1 + self._locked = False self._ports = None self._symbol = None + self._custom_adapters = [] if node_type == "iou": self._port_name_format = "Ethernet{segment0}/{port0}" self._port_by_adapter = 4 @@ -84,6 +87,7 @@ class Node: self._port_by_adapter = 1 self._port_segment_size = 0 self._first_port_name = None + self._console_auto_start = False # This properties will be recompute ignore_properties = ("width", "height", "hover_symbol") @@ -91,12 +95,12 @@ class Node: # Update node properties with additional elements for prop in kwargs: - if prop not in ignore_properties: + if prop and prop not in ignore_properties: if hasattr(self, prop): try: setattr(self, prop, kwargs[prop]) except AttributeError as e: - log.critical("Can't set attribute %s", prop) + log.critical("Cannot set attribute '%s'".format(prop)) raise e else: if prop not in self.CONTROLLER_ONLY_PROPERTIES and kwargs[prop] is not None and kwargs[prop] != "": @@ -121,7 +125,7 @@ class Node: return self.node_type not in ( "qemu", "docker", "dynamips", "vpcs", "vmware", "virtualbox", - "iou") + "iou", "traceng") @property def id(self): @@ -163,6 +167,14 @@ class Node: def console_type(self, val): self._console_type = val + @property + def console_auto_start(self): + return self._console_auto_start + + @console_auto_start.setter + def console_auto_start(self, val): + self._console_auto_start = val + @property def properties(self): return self._properties @@ -175,9 +187,9 @@ class Node: if not os.path.isabs(path): path = os.path.join(self.project.controller.configs_path(), path) try: - with open(path) as f: + with open(path, encoding="utf-8") as f: return f.read() - except (PermissionError, OSError): + except OSError: return None @property @@ -225,6 +237,14 @@ class Node: def z(self, val): self._z = val + @property + def locked(self): + return self._locked + + @locked.setter + def locked(self, val): + self._locked = val + @property def width(self): return self._width @@ -239,6 +259,7 @@ class Node: @symbol.setter def symbol(self, val): + if val is None: val = ":/symbols/computer.svg" @@ -252,23 +273,24 @@ class Node: self._symbol = val try: self._width, self._height, filetype = self._project.controller.symbols.get_size(val) - # If symbol is invalid we replace it by default - except (ValueError, OSError): + except (ValueError, OSError) as e: + log.error("Could not set symbol: {}".format(e)) + # If symbol is invalid we replace it by the default self.symbol = ":/symbols/computer.svg" if self._label is None: # Apply to label user style or default try: - style = qt_font_to_style( - self._project.controller.settings["GraphicsView"]["default_label_font"], - self._project.controller.settings["GraphicsView"]["default_label_color"]) + style = None # FIXME: allow configuration of default label font & color on controller + #style = qt_font_to_style(self._project.controller.settings["GraphicsView"]["default_label_font"], + # self._project.controller.settings["GraphicsView"]["default_label_color"]) except KeyError: - style = "font-size: 10;font-familly: Verdana" + style = "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;" self._label = { "y": round(self._height / 2 + 10) * -1, "text": html.escape(self._name), - "style": style, - "x": None, # None: mean the client should center it + "style": style, # None: means the client will apply its default style + "x": None, # None: means the client should center it "rotation": 0 } @@ -306,6 +328,14 @@ class Node: def first_port_name(self, val): self._first_port_name = val + @property + def custom_adapters(self): + return self._custom_adapters + + @custom_adapters.setter + def custom_adapters(self, val): + self._custom_adapters = val + def add_link(self, link): """ A link is connected to the node @@ -319,40 +349,39 @@ class Node: self._links.remove(link) @property - def link(self): + def links(self): return self._links - @asyncio.coroutine - def create(self): + async def create(self): """ - Create the node on the compute server + Create the node on the compute """ data = self._node_data() data["node_id"] = self._id if self._node_type == "docker": timeout = None + else: timeout = 1200 trial = 0 while trial != 6: try: - response = yield from self._compute.post("/projects/{}/{}/nodes".format(self._project.id, self._node_type), data=data, timeout=timeout) + response = await self._compute.post("/projects/{}/{}/nodes".format(self._project.id, self._node_type), data=data, timeout=timeout) except ComputeConflict as e: if e.response.get("exception") == "ImageMissingError": - res = yield from self._upload_missing_image(self._node_type, e.response["image"]) + res = await self._upload_missing_image(self._node_type, e.response["image"]) if not res: raise e else: raise e else: - yield from self.parse_node_response(response.json) + await self.parse_node_response(response.json) return True trial += 1 - @asyncio.coroutine - def update(self, **kwargs): + async def update(self, **kwargs): """ - Update the node on the compute server + Update the node on the compute :param kwargs: Node properties """ @@ -369,27 +398,30 @@ class Node: if prop not in self.CONTROLLER_ONLY_PROPERTIES: update_compute = True - # We update properties on the compute and wait for the anwser from the compute node + # We update properties on the compute and wait for the answer from the compute node if prop == "properties": compute_properties = kwargs[prop] else: setattr(self, prop, kwargs[prop]) + if compute_properties and "custom_adapters" in compute_properties: + # we need to check custom adapters to update the custom port names + self.custom_adapters = compute_properties["custom_adapters"] self._list_ports() - # We send notif only if object has changed - if old_json != self.__json__(): - self.project.controller.notification.emit("node.updated", self.__json__()) if update_compute: data = self._node_data(properties=compute_properties) - response = yield from self.put(None, data=data) - yield from self.parse_node_response(response.json) + response = await self.put(None, data=data) + await self.parse_node_response(response.json) + elif old_json != self.__json__(): + # We send notif only if object has changed + self.project.emit_notification("node.updated", self.__json__()) self.project.dump() - @asyncio.coroutine - def parse_node_response(self, response): + async def parse_node_response(self, response): """ Update the object with the remote node object """ + for key, value in response.items(): if key == "console": self._console = value @@ -413,7 +445,7 @@ class Node: self._properties[key] = value self._list_ports() for link in self._links: - yield from link.node_updated(self) + await link.node_updated(self) def _node_data(self, properties=None): """ @@ -442,6 +474,8 @@ class Node: data["console"] = self._console if self._console_type: data["console_type"] = self._console_type + if self.custom_adapters: + data["custom_adapters"] = self.custom_adapters # None properties are not be send. Because it can mean the emulator doesn't support it for key in list(data.keys()): @@ -449,73 +483,66 @@ class Node: del data[key] return data - @asyncio.coroutine - def destroy(self): - yield from self.delete() + async def destroy(self): + await self.delete() - @asyncio.coroutine - def start(self): + async def start(self, data=None): """ Start a node """ try: # For IOU we need to send the licence everytime if self.node_type == "iou": - try: - licence = self._project.controller.settings["IOU"]["iourc_content"] - except KeyError: - raise aiohttp.web.HTTPConflict(text="IOU licence is not configured") - yield from self.post("/start", timeout=240, data={"iourc_content": licence}) + license_check = self._project.controller.iou_license.get("license_check", True) + iourc_content = self._project.controller.iou_license.get("iourc_content", None) + #if license_check and not iourc_content: + # raise aiohttp.web.HTTPConflict(text="IOU licence is not configured") + await self.post("/start", timeout=240, data={"license_check": license_check, "iourc_content": iourc_content}) else: - yield from self.post("/start", timeout=240) + await self.post("/start", data=data, timeout=240) except asyncio.TimeoutError: raise aiohttp.web.HTTPRequestTimeout(text="Timeout when starting {}".format(self._name)) - @asyncio.coroutine - def stop(self): + async def stop(self): """ Stop a node """ try: - yield from self.post("/stop", timeout=240, dont_connect=True) + await self.post("/stop", timeout=240, dont_connect=True) # We don't care if a node is down at this step except (ComputeError, aiohttp.ClientError, aiohttp.web.HTTPError): pass except asyncio.TimeoutError: raise aiohttp.web.HTTPRequestTimeout(text="Timeout when stopping {}".format(self._name)) - @asyncio.coroutine - def suspend(self): + async def suspend(self): """ Suspend a node """ try: - yield from self.post("/suspend", timeout=240) + await self.post("/suspend", timeout=240) except asyncio.TimeoutError: raise aiohttp.web.HTTPRequestTimeout(text="Timeout when reloading {}".format(self._name)) - @asyncio.coroutine - def reload(self): + async def reload(self): """ Suspend a node """ try: - yield from self.post("/reload", timeout=240) + await self.post("/reload", timeout=240) except asyncio.TimeoutError: raise aiohttp.web.HTTPRequestTimeout(text="Timeout when reloading {}".format(self._name)) - @asyncio.coroutine - def post(self, path, data=None, **kwargs): + async def post(self, path, data=None, **kwargs): """ HTTP post on the node """ if data: - return (yield from self._compute.post("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path), data=data, **kwargs)) + return (await self._compute.post("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path), data=data, **kwargs)) else: - return (yield from self._compute.post("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path), **kwargs)) + return (await self._compute.post("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path), **kwargs)) - @asyncio.coroutine - def put(self, path, data=None, **kwargs): + async def put(self, path, data=None, **kwargs): """ HTTP post on the node """ @@ -524,22 +551,20 @@ class Node: else: path = "/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path) if data: - return (yield from self._compute.put(path, data=data, **kwargs)) + return (await self._compute.put(path, data=data, **kwargs)) else: - return (yield from self._compute.put(path, **kwargs)) + return (await self._compute.put(path, **kwargs)) - @asyncio.coroutine - def delete(self, path=None, **kwargs): + async def delete(self, path=None, **kwargs): """ HTTP post on the node """ if path is None: - return (yield from self._compute.delete("/projects/{}/{}/nodes/{}".format(self._project.id, self._node_type, self._id), **kwargs)) + return (await self._compute.delete("/projects/{}/{}/nodes/{}".format(self._project.id, self._node_type, self._id), **kwargs)) else: - return (yield from self._compute.delete("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path), **kwargs)) + return (await self._compute.delete("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path), **kwargs)) - @asyncio.coroutine - def _upload_missing_image(self, type, img): + async def _upload_missing_image(self, type, img): """ Search an image on local computer and upload it to remote compute if the image exists @@ -547,29 +572,27 @@ class Node: for directory in images_directories(type): image = os.path.join(directory, img) if os.path.exists(image): - self.project.controller.notification.emit("log.info", {"message": "Uploading missing image {}".format(img)}) + self.project.emit_notification("log.info", {"message": "Uploading missing image {}".format(img)}) try: with open(image, 'rb') as f: - yield from self._compute.post("/{}/images/{}".format(self._node_type, os.path.basename(img)), data=f, timeout=None) + await self._compute.post("/{}/images/{}".format(self._node_type, os.path.basename(img)), data=f, timeout=None) except OSError as e: raise aiohttp.web.HTTPConflict(text="Can't upload {}: {}".format(image, str(e))) - self.project.controller.notification.emit("log.info", {"message": "Upload finished for {}".format(img)}) + self.project.emit_notification("log.info", {"message": "Upload finished for {}".format(img)}) return True return False - @asyncio.coroutine - def dynamips_auto_idlepc(self): + async def dynamips_auto_idlepc(self): """ Compute the idle PC for a dynamips node """ - return (yield from self._compute.get("/projects/{}/{}/nodes/{}/auto_idlepc".format(self._project.id, self._node_type, self._id), timeout=240)).json + return (await self._compute.get("/projects/{}/{}/nodes/{}/auto_idlepc".format(self._project.id, self._node_type, self._id), timeout=240)).json - @asyncio.coroutine - def dynamips_idlepc_proposals(self): + async def dynamips_idlepc_proposals(self): """ Compute a list of potential idle PC """ - return (yield from self._compute.get("/projects/{}/{}/nodes/{}/idlepc_proposals".format(self._project.id, self._node_type, self._id), timeout=240)).json + return (await self._compute.get("/projects/{}/{}/nodes/{}/idlepc_proposals".format(self._project.id, self._node_type, self._id), timeout=240)).json def get_port(self, adapter_number, port_number): """ @@ -585,7 +608,7 @@ class Node: """ Generate the list of port display in the client if the compute has sent a list we return it (use by - node where you can not personnalize the port naming). + node where you can not personalize the port naming). """ self._ports = [] # Some special cases @@ -615,14 +638,21 @@ class Node: return elif self._node_type == "docker": for adapter_number in range(0, self._properties["adapters"]): - self._ports.append(PortFactory("eth{}".format(adapter_number), 0, adapter_number, 0, "ethernet", short_name="eth{}".format(adapter_number))) + custom_adapter_settings = {} + for custom_adapter in self.custom_adapters: + if custom_adapter["adapter_number"] == adapter_number: + custom_adapter_settings = custom_adapter + break + port_name = "eth{}".format(adapter_number) + port_name = custom_adapter_settings.get("port_name", port_name) + self._ports.append(PortFactory(port_name, 0, adapter_number, 0, "ethernet", short_name=port_name)) elif self._node_type in ("ethernet_switch", "ethernet_hub"): # Basic node we don't want to have adapter number port_number = 0 for port in self._properties["ports_mapping"]: self._ports.append(PortFactory(port["name"], 0, 0, port_number, "ethernet", short_name="e{}".format(port_number))) port_number += 1 - elif self._node_type in ("vpcs"): + elif self._node_type in ("vpcs", "traceng"): self._ports.append(PortFactory("Ethernet0", 0, 0, 0, "ethernet", short_name="e0")) elif self._node_type in ("cloud", "nat"): port_number = 0 @@ -630,7 +660,7 @@ class Node: self._ports.append(PortFactory(port["name"], 0, 0, port_number, "ethernet", short_name=port["name"])) port_number += 1 else: - self._ports = StandardPortFactory(self._properties, self._port_by_adapter, self._first_port_name, self._port_name_format, self._port_segment_size) + self._ports = StandardPortFactory(self._properties, self._port_by_adapter, self._first_port_name, self._port_name_format, self._port_segment_size, self._custom_adapters) def __repr__(self): return "".format(self._node_type, self._name) @@ -644,36 +674,43 @@ class Node: """ :param topology_dump: Filter to keep only properties require for saving on disk """ + if topology_dump: return { "compute_id": str(self._compute.id), "node_id": self._id, "node_type": self._node_type, + "template_id": self._template_id, "name": self._name, "console": self._console, "console_type": self._console_type, + "console_auto_start": self._console_auto_start, "properties": self._properties, "label": self._label, "x": self._x, "y": self._y, "z": self._z, + "locked": self._locked, "width": self._width, "height": self._height, "symbol": self._symbol, "port_name_format": self._port_name_format, "port_segment_size": self._port_segment_size, - "first_port_name": self._first_port_name + "first_port_name": self._first_port_name, + "custom_adapters": self._custom_adapters } return { "compute_id": str(self._compute.id), "project_id": self._project.id, "node_id": self._id, + "template_id": self._template_id, "node_type": self._node_type, "node_directory": self._node_directory, "name": self._name, "console": self._console, "console_host": str(self._compute.console_host), "console_type": self._console_type, + "console_auto_start": self._console_auto_start, "command_line": self._command_line, "properties": self._properties, "status": self._status, @@ -681,11 +718,13 @@ class Node: "x": self._x, "y": self._y, "z": self._z, + "locked": self._locked, "width": self._width, "height": self._height, "symbol": self._symbol, "port_name_format": self._port_name_format, "port_segment_size": self._port_segment_size, "first_port_name": self._first_port_name, + "custom_adapters": self._custom_adapters, "ports": [port.__json__() for port in self.ports] } diff --git a/gns3server/controller/notification.py b/gns3server/controller/notification.py index a3eec16a..53790b8b 100644 --- a/gns3server/controller/notification.py +++ b/gns3server/controller/notification.py @@ -17,7 +17,6 @@ import os import aiohttp -import asyncio from contextlib import contextmanager from ..notification_queue import NotificationQueue @@ -30,30 +29,69 @@ class Notification: def __init__(self, controller): self._controller = controller - self._listeners = {} + self._project_listeners = {} + self._controller_listeners = [] @contextmanager - def queue(self, project): + def project_queue(self, project_id): """ Get a queue of notifications Use it with Python with """ queue = NotificationQueue() - self._listeners.setdefault(project.id, set()) - self._listeners[project.id].add(queue) - yield queue - self._listeners[project.id].remove(queue) + self._project_listeners.setdefault(project_id, set()) + self._project_listeners[project_id].add(queue) + try: + yield queue + finally: + self._project_listeners[project_id].remove(queue) - def project_has_listeners(self, project): + @contextmanager + def controller_queue(self): + """ + Get a queue of notifications + + Use it with Python with + """ + queue = NotificationQueue() + self._controller_listeners.append(queue) + try: + yield queue + finally: + self._controller_listeners.remove(queue) + + def controller_emit(self, action, event): + """ + Send a notification to clients connected to the controller stream + + :param action: Action name + :param event: Event to send + """ + + # If use in tests for documentation we save a sample + if os.environ.get("PYTEST_BUILD_DOCUMENTATION") == "1": + os.makedirs("docs/api/notifications", exist_ok=True) + try: + import json + data = json.dumps(event, indent=4, sort_keys=True) + if "MagicMock" not in data: + with open(os.path.join("docs/api/notifications", action + ".json"), 'w+') as f: + f.write(data) + except TypeError: # If we receive a mock as an event it will raise TypeError when using json dump + pass + + for controller_listener in self._controller_listeners: + controller_listener.put_nowait((action, event, {})) + + def project_has_listeners(self, project_id): """ :param project_id: Project object :returns: True if client listen this project """ - return project.id in self._listeners and len(self._listeners[project.id]) > 0 + return project_id in self._project_listeners and len(self._project_listeners[project_id]) > 0 - @asyncio.coroutine - def dispatch(self, action, event, compute_id): + async def dispatch(self, action, event, project_id, compute_id): """ Notification received from compute node. Send it directly to clients or process it @@ -67,18 +105,18 @@ class Notification: # Update controller node data and send the event node.updated project = self._controller.get_project(event["project_id"]) node = project.get_node(event["node_id"]) - yield from node.parse_node_response(event) + await node.parse_node_response(event) - self.emit("node.updated", node.__json__()) + self.project_emit("node.updated", node.__json__()) except (aiohttp.web.HTTPNotFound, aiohttp.web.HTTPForbidden): # Project closing return elif action == "ping": - event["compute_id"] = compute_id - self.emit(action, event) + event["compute_id"] = compute_id + self.project_emit(action, event) else: - self.emit(action, event) + self.project_emit(action, event, project_id) - def emit(self, action, event): + def project_emit(self, action, event, project_id=None): """ Send a notification to clients scoped by projects @@ -98,10 +136,10 @@ class Notification: except TypeError: # If we receive a mock as an event it will raise TypeError when using json dump pass - if "project_id" in event: - self._send_event_to_project(event["project_id"], action, event) + if "project_id" in event or project_id: + self._send_event_to_project(event.get("project_id", project_id), action, event) else: - self._send_event_to_all(action, event) + self._send_event_to_all_projects(action, event) def _send_event_to_project(self, project_id, action, event): """ @@ -113,13 +151,13 @@ class Notification: :param event: Event to send """ try: - project_listeners = self._listeners[project_id] + project_listeners = self._project_listeners[project_id] except KeyError: return for listener in project_listeners: listener.put_nowait((action, event, {})) - def _send_event_to_all(self, action, event): + def _send_event_to_all_projects(self, action, event): """ Send an event to all the client listening for notifications on all projects @@ -127,6 +165,6 @@ class Notification: :param action: Action name :param event: Event to send """ - for project_listeners in self._listeners.values(): + for project_listeners in self._project_listeners.values(): for listener in project_listeners: listener.put_nowait((action, event, {})) diff --git a/gns3server/controller/ports/atm_port.py b/gns3server/controller/ports/atm_port.py index 51da8d86..f63b9e4b 100644 --- a/gns3server/controller/ports/atm_port.py +++ b/gns3server/controller/ports/atm_port.py @@ -33,8 +33,8 @@ class ATMPort(SerialPort): """ return "ATM" - @property - def short_name_type(self): + @staticmethod + def short_name_type(): """ Returns the short name type for this port. @@ -42,10 +42,6 @@ class ATMPort(SerialPort): """ return "a" - @property - def short_name(self): - return "{}".format(self._port_number) - @property def data_link_types(self): """ diff --git a/gns3server/controller/ports/ethernet_port.py b/gns3server/controller/ports/ethernet_port.py index 6847998b..ae3f7e73 100644 --- a/gns3server/controller/ports/ethernet_port.py +++ b/gns3server/controller/ports/ethernet_port.py @@ -39,8 +39,8 @@ class EthernetPort(Port): return "Ethernet" - @property - def short_name_type(self): + @staticmethod + def short_name_type(): """ Returns the short name type for this port. diff --git a/gns3server/controller/ports/fastethernet_port.py b/gns3server/controller/ports/fastethernet_port.py index a8f98780..2a01e14a 100644 --- a/gns3server/controller/ports/fastethernet_port.py +++ b/gns3server/controller/ports/fastethernet_port.py @@ -34,8 +34,8 @@ class FastEthernetPort(Port): return "FastEthernet" - @property - def short_name_type(self): + @staticmethod + def short_name_type(): """ Returns the short name type for this port. diff --git a/gns3server/controller/ports/frame_relay_port.py b/gns3server/controller/ports/frame_relay_port.py index 356c13bd..87049917 100644 --- a/gns3server/controller/ports/frame_relay_port.py +++ b/gns3server/controller/ports/frame_relay_port.py @@ -34,10 +34,6 @@ class FrameRelayPort(SerialPort): return "FrameRelay" - @property - def short_name(self): - return "{}".format(self._port_number) - @property def data_link_types(self): """ diff --git a/gns3server/controller/ports/gigabitethernet_port.py b/gns3server/controller/ports/gigabitethernet_port.py index c96b820f..bcf7b143 100644 --- a/gns3server/controller/ports/gigabitethernet_port.py +++ b/gns3server/controller/ports/gigabitethernet_port.py @@ -34,8 +34,8 @@ class GigabitEthernetPort(Port): return "GigabitEthernet" - @property - def short_name_type(self): + @staticmethod + def short_name_type(): """ Returns the short name type for this port. diff --git a/gns3server/controller/ports/port.py b/gns3server/controller/ports/port.py index 886973e5..601e8024 100644 --- a/gns3server/controller/ports/port.py +++ b/gns3server/controller/ports/port.py @@ -27,6 +27,8 @@ class Port: self._port_number = port_number self._name = name self._short_name = short_name + self._adapter_type = None + self._mac_address = None self._link = None @property @@ -48,6 +50,22 @@ class Port: def port_number(self): return self._port_number + @property + def adapter_type(self): + return self._adapter_type + + @adapter_type.setter + def adapter_type(self, val): + self._adapter_type = val + + @property + def mac_address(self): + return self._mac_address + + @mac_address.setter + def mac_address(self, val): + self._mac_address = val + @property def data_link_types(self): """ @@ -63,19 +81,21 @@ class Port: @property def short_name(self): - # If port name format has change we use the port name as the short name (1.X behavior) + # If port name format has changed we use the port name as the short name (1.X behavior) if self._short_name: return self._short_name - elif not self._name.startswith("{}{}".format(self.long_name_type(), self._interface_number)): - return self._name - return self.short_name_type + "{}/{}".format(self._interface_number, self._port_number) + elif '/' in self._name: + return self._name.replace(self.long_name_type(), self.short_name_type()) + elif self._name.startswith("{}{}".format(self.long_name_type(), self._interface_number)): + return self.short_name_type() + "{}".format(self._interface_number) + return self._name @short_name.setter def short_name(self, val): self._short_name = val def __json__(self): - return { + info = { "name": self._name, "short_name": self.short_name, "data_link_types": self.data_link_types, @@ -83,3 +103,8 @@ class Port: "adapter_number": self._adapter_number, "link_type": self.link_type } + if self._adapter_type: + info["adapter_type"] = self._adapter_type + if self._mac_address: + info["mac_address"] = self._mac_address + return info diff --git a/gns3server/controller/ports/port_factory.py b/gns3server/controller/ports/port_factory.py index 39dac69c..3b7547ae 100644 --- a/gns3server/controller/ports/port_factory.py +++ b/gns3server/controller/ports/port_factory.py @@ -17,6 +17,7 @@ import aiohttp +from gns3server.utils import macaddress_to_int, int_to_macaddress from .atm_port import ATMPort from .frame_relay_port import FrameRelayPort from .gigabitethernet_port import GigabitEthernetPort @@ -51,7 +52,7 @@ class StandardPortFactory: """ Create ports for standard device """ - def __new__(cls, properties, port_by_adapter, first_port_name, port_name_format, port_segment_size): + def __new__(cls, properties, port_by_adapter, first_port_name, port_name_format, port_segment_size, custom_adapters): ports = [] adapter_number = interface_number = segment_number = 0 @@ -61,10 +62,17 @@ class StandardPortFactory: ethernet_adapters = properties.get("adapters", 1) for adapter_number in range(adapter_number, ethernet_adapters + adapter_number): + + custom_adapter_settings = {} + for custom_adapter in custom_adapters: + if custom_adapter["adapter_number"] == adapter_number: + custom_adapter_settings = custom_adapter + break + for port_number in range(0, port_by_adapter): if first_port_name and adapter_number == 0: - port_name = first_port_name - port = PortFactory(port_name, segment_number, adapter_number, port_number, "ethernet") + port_name = custom_adapter_settings.get("port_name", first_port_name) + port = PortFactory(port_name, segment_number, adapter_number, port_number, "ethernet", short_name=port_name) else: try: port_name = port_name_format.format( @@ -72,8 +80,10 @@ class StandardPortFactory: segment_number, adapter=adapter_number, **cls._generate_replacement(interface_number, segment_number)) - except (ValueError, KeyError) as e: + except (IndexError, ValueError, KeyError) as e: raise aiohttp.web.HTTPConflict(text="Invalid port name format {}: {}".format(port_name_format, str(e))) + + port_name = custom_adapter_settings.get("port_name", port_name) port = PortFactory(port_name, segment_number, adapter_number, port_number, "ethernet") interface_number += 1 if port_segment_size: @@ -83,6 +93,11 @@ class StandardPortFactory: else: segment_number += 1 + port.adapter_type = custom_adapter_settings.get("adapter_type", properties.get("adapter_type", None)) + mac_address = custom_adapter_settings.get("mac_address") + if not mac_address and "mac_address" in properties: + mac_address = int_to_macaddress(macaddress_to_int(properties["mac_address"]) + adapter_number) + port.mac_address = mac_address ports.append(port) if len(ports): @@ -103,6 +118,7 @@ class StandardPortFactory: {port0} => {port9} {segment0} => {segment9} """ + replacements = {} for i in range(0, 9): replacements["port" + str(i)] = interface_number + i @@ -114,6 +130,7 @@ class DynamipsPortFactory: """ Create port for dynamips devices """ + ADAPTER_MATRIX = { "C1700-MB-1FE": {"nb_ports": 1, "port": FastEthernetPort}, @@ -178,6 +195,7 @@ class DynamipsPortFactory: } def __new__(cls, properties): + ports = [] adapter_number = 0 @@ -190,7 +208,9 @@ class DynamipsPortFactory: if port_class: for port_number in range(0, cls.ADAPTER_MATRIX[properties[name]]["nb_ports"]): name = "{}{}/{}".format(port_class.long_name_type(), adapter_number, port_number) - ports.append(port_class(name, adapter_number, adapter_number, port_number)) + port = port_class(name, adapter_number, adapter_number, port_number) + port.short_name = "{}{}/{}".format(port_class.short_name_type(), adapter_number, port_number) + ports.append(port) adapter_number += 1 elif name.startswith("wic") and properties[name]: port_class = cls.WIC_MATRIX[properties[name]]["port"] @@ -198,7 +218,7 @@ class DynamipsPortFactory: for port_number in range(0, cls.WIC_MATRIX[properties[name]]["nb_ports"]): name = "{}{}/{}".format(port_class.long_name_type(), 0, display_wic_port_number) port = port_class(name, 0, 0, wic_port_number) - port.short_name = "{}{}/{}".format(port.short_name_type, 0, display_wic_port_number) + port.short_name = "{}{}/{}".format(port_class.short_name_type(), 0, display_wic_port_number) ports.append(port) display_wic_port_number += 1 wic_port_number += 1 diff --git a/gns3server/controller/ports/pos_port.py b/gns3server/controller/ports/pos_port.py index 152e1f62..bd6a508e 100644 --- a/gns3server/controller/ports/pos_port.py +++ b/gns3server/controller/ports/pos_port.py @@ -33,8 +33,8 @@ class POSPort(SerialPort): """ return "POS" - @property - def short_name_type(self): + @staticmethod + def short_name_type(): """ Returns the short name type for this port. diff --git a/gns3server/controller/ports/serial_port.py b/gns3server/controller/ports/serial_port.py index 090f3a47..37fb4ebc 100644 --- a/gns3server/controller/ports/serial_port.py +++ b/gns3server/controller/ports/serial_port.py @@ -34,8 +34,8 @@ class SerialPort(Port): return "Serial" - @property - def short_name_type(self): + @staticmethod + def short_name_type(): """ Returns the short name type for this port. diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index 46348083..0c0093ab 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -21,9 +21,12 @@ import json import uuid import copy import shutil +import time import asyncio import aiohttp +import aiofiles import tempfile +import zipfile from uuid import UUID, uuid4 @@ -36,7 +39,8 @@ from .udp_link import UDPLink from ..config import Config from ..utils.path import check_path_allowed, get_default_project_directory from ..utils.asyncio.pool import Pool -from ..utils.asyncio import locked_coroutine +from ..utils.asyncio import locking +from ..utils.asyncio import aiozipstream from .export_project import export_project from .import_project import import_project @@ -68,7 +72,7 @@ class Project: def __init__(self, name=None, project_id=None, path=None, controller=None, status="opened", filename=None, auto_start=False, auto_open=False, auto_close=True, scene_height=1000, scene_width=2000, zoom=100, show_layers=False, snap_to_grid=False, show_grid=False, - show_interface_labels=False): + grid_size=75, drawing_grid_size=25, show_interface_labels=False, variables=None, supplier=None): self._controller = controller assert name is not None @@ -83,8 +87,14 @@ class Project: self._show_layers = show_layers self._snap_to_grid = snap_to_grid self._show_grid = show_grid + self._grid_size = grid_size + self._drawing_grid_size = drawing_grid_size self._show_interface_labels = show_interface_labels + self._variables = variables + self._supplier = supplier + self._loading = False + self._closing = False # Disallow overwrite of existing project if project_id is None and path is not None: @@ -111,12 +121,22 @@ class Project: self.reset() - # At project creation we write an empty .gns3 + # At project creation we write an empty .gns3 with the meta if not os.path.exists(self._topology_file()): + assert self._status != "closed" self.dump() - @asyncio.coroutine - def update(self, **kwargs): + def emit_notification(self, action, event): + """ + Emit a notification to all clients using this project. + + :param action: Action name + :param event: Event to send + """ + + self.controller.notification.project_emit(action, event, project_id=self.id) + + async def update(self, **kwargs): """ Update the project :param kwargs: Project properties @@ -129,9 +149,17 @@ class Project: # We send notif only if object has changed if old_json != self.__json__(): - self.controller.notification.emit("project.updated", self.__json__()) + self.emit_notification("project.updated", self.__json__()) self.dump() + # update on computes + for compute in list(self._project_created_on_compute): + await compute.put( + "/projects/{}".format(self._id), { + "variables": self.variables + } + ) + def reset(self): """ Called when open/close a project. Cleanup internal stuff @@ -235,6 +263,36 @@ class Project: """ self._show_grid = show_grid + @property + def grid_size(self): + """ + Grid size + :return: integer + """ + return self._grid_size + + @grid_size.setter + def grid_size(self, grid_size): + """ + Setter for grid size + """ + self._grid_size = grid_size + + @property + def drawing_grid_size(self): + """ + Grid size + :return: integer + """ + return self._drawing_grid_size + + @drawing_grid_size.setter + def drawing_grid_size(self, grid_size): + """ + Setter for grid size + """ + self._drawing_grid_size = grid_size + @property def show_interface_labels(self): """ @@ -250,6 +308,36 @@ class Project: """ self._show_interface_labels = show_interface_labels + @property + def variables(self): + """ + Variables applied to the project + :return: list + """ + return self._variables + + @variables.setter + def variables(self, variables): + """ + Setter for variables applied to the project + """ + self._variables = variables + + @property + def supplier(self): + """ + Supplier of the project + :return: dict + """ + return self._supplier + + @supplier.setter + def supplier(self, supplier): + """ + Setter for supplier of the project + """ + self._supplier = supplier + @property def auto_start(self): """ @@ -264,7 +352,7 @@ class Project: @property def auto_close(self): """ - Should project automaticaly closed when client + Should project automatically closed when client stop listening for notification """ return self._auto_close @@ -402,31 +490,30 @@ class Project: return new_name @open_required - @asyncio.coroutine - def add_node_from_appliance(self, appliance_id, x=0, y=0, compute_id=None): + async def add_node_from_template(self, template_id, x=0, y=0, compute_id=None): """ - Create a node from an appliance + Create a node from a template. """ try: - template = self.controller.appliances[appliance_id].data + template = copy.deepcopy(self.controller.template_manager.templates[template_id].settings) except KeyError: - msg = "Appliance {} doesn't exist".format(appliance_id) + msg = "Template {} doesn't exist".format(template_id) log.error(msg) raise aiohttp.web.HTTPNotFound(text=msg) template["x"] = x template["y"] = y - node_type = template.pop("node_type") - compute = self.controller.get_compute(template.pop("server", compute_id)) + node_type = template.pop("template_type") + compute = self.controller.get_compute(template.pop("compute_id", compute_id)) name = template.pop("name") default_name_format = template.pop("default_name_format", "{name}-{0}") name = default_name_format.replace("{name}", name) node_id = str(uuid.uuid4()) - node = yield from self.add_node(compute, name, node_id, node_type=node_type, **template) + template.pop("builtin") # not needed to add a node + node = await self.add_node(compute, name, node_id, node_type=node_type, **template) return node @open_required - @asyncio.coroutine - def add_node(self, compute, name, node_id, dump=True, node_type=None, **kwargs): + async def add_node(self, compute, name, node_id, dump=True, node_type=None, **kwargs): """ Create a node or return an existing node @@ -441,27 +528,32 @@ class Project: if compute not in self._project_created_on_compute: # For a local server we send the project path if compute.id == "local": - yield from compute.post("/projects", data={ + data = { "name": self._name, "project_id": self._id, "path": self._path - }) + } else: - yield from compute.post("/projects", data={ + data = { "name": self._name, - "project_id": self._id, - }) + "project_id": self._id + } + + if self._variables: + data["variables"] = self._variables + + await compute.post("/projects", data=data) self._project_created_on_compute.add(compute) - yield from node.create() + await node.create() self._nodes[node.id] = node - self.controller.notification.emit("node.created", node.__json__()) + self.emit_notification("node.created", node.__json__()) if dump: self.dump() return node - @locked_coroutine - def __delete_node_links(self, node): + @locking + async def __delete_node_links(self, node): """ Delete all link connected to this node. @@ -470,18 +562,19 @@ class Project: """ for link in list(self._links.values()): if node in link.nodes: - yield from self.delete_link(link.id, force_delete=True) + await self.delete_link(link.id, force_delete=True) @open_required - @asyncio.coroutine - def delete_node(self, node_id): + async def delete_node(self, node_id): node = self.get_node(node_id) - yield from self.__delete_node_links(node) + if node.locked: + raise aiohttp.web.HTTPConflict(text="Node {} cannot be deleted because it is locked".format(node.name)) + await self.__delete_node_links(node) self.remove_allocated_node_name(node.name) del self._nodes[node.id] - yield from node.destroy() + await node.destroy() self.dump() - self.controller.notification.emit("node.deleted", node.__json__()) + self.emit_notification("node.deleted", node.__json__()) @open_required def get_node(self, node_id): @@ -493,11 +586,37 @@ class Project: except KeyError: raise aiohttp.web.HTTPNotFound(text="Node ID {} doesn't exist".format(node_id)) + def _get_closed_data(self, section, id_key): + """ + Get the data for a project from the .gns3 when + the project is close + + :param section: The section name in the .gns3 + :param id_key: The key for the element unique id + """ + + try: + path = self._topology_file() + with open(path, "r") as f: + topology = json.load(f) + except OSError as e: + raise aiohttp.web.HTTPInternalServerError(text="Could not load topology: {}".format(e)) + + try: + data = {} + for elem in topology["topology"][section]: + data[elem[id_key]] = elem + return data + except KeyError: + raise aiohttp.web.HTTPNotFound(text="Section {} not found in the topology".format(section)) + @property def nodes(self): """ :returns: Dictionary of the nodes """ + if self._status == "closed": + return self._get_closed_data("nodes", "node_id") return self._nodes @property @@ -505,11 +624,12 @@ class Project: """ :returns: Dictionary of the drawings """ + if self._status == "closed": + return self._get_closed_data("drawings", "drawing_id") return self._drawings @open_required - @asyncio.coroutine - def add_drawing(self, drawing_id=None, dump=True, **kwargs): + async def add_drawing(self, drawing_id=None, dump=True, **kwargs): """ Create an drawing or return an existing drawing @@ -519,7 +639,7 @@ class Project: if drawing_id not in self._drawings: drawing = Drawing(self, drawing_id=drawing_id, **kwargs) self._drawings[drawing.id] = drawing - self.controller.notification.emit("drawing.created", drawing.__json__()) + self.emit_notification("drawing.created", drawing.__json__()) if dump: self.dump() return drawing @@ -536,16 +656,14 @@ class Project: raise aiohttp.web.HTTPNotFound(text="Drawing ID {} doesn't exist".format(drawing_id)) @open_required - @asyncio.coroutine - def delete_drawing(self, drawing_id): + async def delete_drawing(self, drawing_id): drawing = self.get_drawing(drawing_id) del self._drawings[drawing.id] self.dump() - self.controller.notification.emit("drawing.deleted", drawing.__json__()) + self.emit_notification("drawing.deleted", drawing.__json__()) @open_required - @asyncio.coroutine - def add_link(self, link_id=None, dump=True): + async def add_link(self, link_id=None, dump=True): """ Create a link. By default the link is empty @@ -560,17 +678,16 @@ class Project: return link @open_required - @asyncio.coroutine - def delete_link(self, link_id, force_delete=False): + async def delete_link(self, link_id, force_delete=False): link = self.get_link(link_id) del self._links[link.id] try: - yield from link.delete() + await link.delete() except Exception: if force_delete is False: raise self.dump() - self.controller.notification.emit("link.deleted", link.__json__()) + self.emit_notification("link.deleted", link.__json__()) @open_required def get_link(self, link_id): @@ -587,6 +704,8 @@ class Project: """ :returns: Dictionary of the Links """ + if self._status == "closed": + return self._get_closed_data("links", "link_id") return self._links @property @@ -607,104 +726,103 @@ class Project: raise aiohttp.web.HTTPNotFound(text="Snapshot ID {} doesn't exist".format(snapshot_id)) @open_required - @asyncio.coroutine - def snapshot(self, name): + async def snapshot(self, name): """ Snapshot the project :param name: Name of the snapshot """ - if name in [snap.name for snap in self.snapshots.values()]: - raise aiohttp.web_exceptions.HTTPConflict(text="The snapshot {} already exist".format(name)) - + if name in [snap.name for snap in self._snapshots.values()]: + raise aiohttp.web.HTTPConflict(text="The snapshot name {} already exists".format(name)) snapshot = Snapshot(self, name=name) - try: - if os.path.exists(snapshot.path): - raise aiohttp.web_exceptions.HTTPConflict(text="The snapshot {} already exist".format(name)) - - os.makedirs(os.path.join(self.path, "snapshots"), exist_ok=True) - - with tempfile.TemporaryDirectory() as tmpdir: - zipstream = yield from export_project(self, tmpdir, keep_compute_id=True, allow_all_nodes=True) - try: - with open(snapshot.path, "wb") as f: - for data in zipstream: - f.write(data) - except OSError as e: - raise aiohttp.web.HTTPConflict(text="Could not write snapshot file '{}': {}".format(snapshot.path, e)) - except OSError as e: - raise aiohttp.web.HTTPInternalServerError(text="Could not create project directory: {}".format(e)) - + await snapshot.create() self._snapshots[snapshot.id] = snapshot return snapshot @open_required - @asyncio.coroutine - def delete_snapshot(self, snapshot_id): + async def delete_snapshot(self, snapshot_id): snapshot = self.get_snapshot(snapshot_id) del self._snapshots[snapshot.id] os.remove(snapshot.path) - @asyncio.coroutine - def close(self, ignore_notification=False): - yield from self.stop_all() + @locking + async def close(self, ignore_notification=False): + if self._status == "closed" or self._closing: + return + if self._loading: + log.warning("Closing project '{}' ignored because it is being loaded".format(self.name)) + return + self._closing = True + await self.stop_all() for compute in list(self._project_created_on_compute): try: - yield from compute.post("/projects/{}/close".format(self._id), dont_connect=True) + await compute.post("/projects/{}/close".format(self._id), dont_connect=True) # We don't care if a compute is down at this step except (ComputeError, aiohttp.web.HTTPError, aiohttp.ClientResponseError, TimeoutError): pass - self._cleanPictures() + self._clean_pictures() self._status = "closed" if not ignore_notification: - self.controller.notification.emit("project.closed", self.__json__()) + self.emit_notification("project.closed", self.__json__()) + self.reset() + self._closing = False - def _cleanPictures(self): + def _clean_pictures(self): """ - Delete unused images + Delete unused pictures. """ - # Project have been deleted - if not os.path.exists(self.path): + # Project have been deleted or is loading or is not opened + if not os.path.exists(self.path) or self._loading or self._status != "opened": return try: pictures = set(os.listdir(self.pictures_directory)) for drawing in self._drawings.values(): try: - pictures.remove(drawing.ressource_filename) + resource_filename = drawing.resource_filename + if resource_filename: + pictures.remove(resource_filename) except KeyError: pass - for pict in pictures: - os.remove(os.path.join(self.pictures_directory, pict)) - except OSError as e: - log.warning(str(e)) + # don't remove supplier's logo + if self.supplier: + try: + logo = self.supplier['logo'] + pictures.remove(logo) + except KeyError: + pass - @asyncio.coroutine - def delete(self): + for pic_filename in pictures: + path = os.path.join(self.pictures_directory, pic_filename) + log.info("Deleting unused picture '{}'".format(path)) + os.remove(path) + except OSError as e: + log.warning("Could not delete unused pictures: {}".format(e)) + + async def delete(self): if self._status != "opened": try: - yield from self.open() + await self.open() except aiohttp.web.HTTPConflict as e: # ignore missing images or other conflicts when deleting a project log.warning("Conflict while deleting project: {}".format(e.text)) - yield from self.delete_on_computes() - yield from self.close() + await self.delete_on_computes() + await self.close() try: shutil.rmtree(self.path) except OSError as e: raise aiohttp.web.HTTPConflict(text="Can not delete project directory {}: {}".format(self.path, str(e))) - @asyncio.coroutine - def delete_on_computes(self): + async def delete_on_computes(self): """ Delete the project on computes but not on controller """ for compute in list(self._project_created_on_compute): if compute.id != "local": - yield from compute.delete("/projects/{}".format(self._id)) + await compute.delete("/projects/{}".format(self._id)) self._project_created_on_compute.remove(compute) @classmethod @@ -726,11 +844,15 @@ class Project: def _topology_file(self): return os.path.join(self.path, self._filename) - @locked_coroutine - def open(self): + @locking + async def open(self): """ Load topology elements """ + + if self._closing is True: + raise aiohttp.web.HTTPConflict(text="Project is closing, please try again in a few seconds...") + if self._status == "opened": return @@ -760,6 +882,8 @@ class Project: "show_layers", "snap_to_grid", "show_grid", + "grid_size", + "drawing_grid_size", "show_interface_labels" ] @@ -770,20 +894,20 @@ class Project: topology = project_data["topology"] for compute in topology.get("computes", []): - yield from self.controller.add_compute(**compute) + await self.controller.add_compute(**compute) for node in topology.get("nodes", []): compute = self.controller.get_compute(node.pop("compute_id")) name = node.pop("name") node_id = node.pop("node_id", str(uuid.uuid4())) - yield from self.add_node(compute, name, node_id, dump=False, **node) + await self.add_node(compute, name, node_id, dump=False, **node) for link_data in topology.get("links", []): if 'link_id' not in link_data.keys(): # skip the link continue - link = yield from self.add_link(link_id=link_data["link_id"]) + link = await self.add_link(link_id=link_data["link_id"]) if "filters" in link_data: - yield from link.update_filters(link_data["filters"]) - for node_link in link_data["nodes"]: + await link.update_filters(link_data["filters"]) + for node_link in link_data.get("nodes", []): node = self.get_node(node_link["node_id"]) port = node.get_port(node_link["adapter_number"], node_link["port_number"]) if port is None: @@ -792,26 +916,26 @@ class Project: if port.link is not None: log.warning("Port {}/{} is already connected to link ID {}".format(node_link["adapter_number"], node_link["port_number"], port.link.id)) continue - yield from link.add_node(node, node_link["adapter_number"], node_link["port_number"], label=node_link.get("label"), dump=False) + await link.add_node(node, node_link["adapter_number"], node_link["port_number"], label=node_link.get("label"), dump=False) if len(link.nodes) != 2: # a link should have 2 attached nodes, this can happen with corrupted projects - yield from self.delete_link(link.id, force_delete=True) + await self.delete_link(link.id, force_delete=True) for drawing_data in topology.get("drawings", []): - yield from self.add_drawing(dump=False, **drawing_data) + await self.add_drawing(dump=False, **drawing_data) self.dump() # We catch all error to be able to rollback the .gns3 to the previous state except Exception as e: for compute in list(self._project_created_on_compute): try: - yield from compute.post("/projects/{}/close".format(self._id)) + await compute.post("/projects/{}/close".format(self._id)) # We don't care if a compute is down at this step except (ComputeError, aiohttp.web.HTTPNotFound, aiohttp.web.HTTPConflict, aiohttp.ServerDisconnectedError): pass try: if os.path.exists(path + ".backup"): shutil.copy(path + ".backup", path) - except (PermissionError, OSError): + except OSError: pass self._status = "closed" self._loading = False @@ -830,18 +954,16 @@ class Project: # Start all in the background without waiting for completion # we ignore errors because we want to let the user open # their project and fix it - asyncio.async(self.start_all()) + asyncio.ensure_future(self.start_all()) - @asyncio.coroutine - def wait_loaded(self): + async def wait_loaded(self): """ Wait until the project finish loading """ while self._loading: - yield from asyncio.sleep(0.5) + await asyncio.sleep(0.5) - @asyncio.coroutine - def duplicate(self, name=None, location=None): + async def duplicate(self, name=None, location=None): """ Duplicate a project @@ -855,22 +977,34 @@ class Project: # If the project was not open we open it temporary previous_status = self._status if self._status == "closed": - yield from self.open() + await self.open() self.dump() + assert self._status != "closed" try: + begin = time.time() with tempfile.TemporaryDirectory() as tmpdir: - zipstream = yield from export_project(self, tmpdir, keep_compute_id=True, allow_all_nodes=True) - with open(os.path.join(tmpdir, "project.gns3p"), "wb") as f: - for data in zipstream: - f.write(data) - with open(os.path.join(tmpdir, "project.gns3p"), "rb") as f: - project = yield from import_project(self._controller, str(uuid.uuid4()), f, location=location, name=name, keep_compute_id=True) - except (OSError, UnicodeEncodeError) as e: - raise aiohttp.web.HTTPConflict(text="Can not duplicate project: {}".format(str(e))) + # Do not compress the exported project when duplicating + with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream: + await export_project(zstream, self, tmpdir, keep_compute_id=True, allow_all_nodes=True, reset_mac_addresses=True) + + # export the project to a temporary location + project_path = os.path.join(tmpdir, "project.gns3p") + log.info("Exporting project to '{}'".format(project_path)) + async with aiofiles.open(project_path, 'wb') as f: + async for chunk in zstream: + await f.write(chunk) + + # import the temporary project + with open(project_path, "rb") as f: + project = await import_project(self._controller, str(uuid.uuid4()), f, location=location, name=name, keep_compute_id=True) + + log.info("Project '{}' duplicated in {:.4f} seconds".format(project.name, time.time() - begin)) + except (ValueError, OSError, UnicodeEncodeError) as e: + raise aiohttp.web.HTTPConflict(text="Cannot duplicate project: {}".format(str(e))) if previous_status == "closed": - yield from self.close() + await self.close() return project @@ -898,38 +1032,34 @@ class Project: except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not write topology: {}".format(e)) - @asyncio.coroutine - def start_all(self): + async def start_all(self): """ Start all nodes """ pool = Pool(concurrency=3) for node in self.nodes.values(): pool.append(node.start) - yield from pool.join() + await pool.join() - @asyncio.coroutine - def stop_all(self): + async def stop_all(self): """ Stop all nodes """ pool = Pool(concurrency=3) for node in self.nodes.values(): pool.append(node.stop) - yield from pool.join() + await pool.join() - @asyncio.coroutine - def suspend_all(self): + async def suspend_all(self): """ Suspend all nodes """ pool = Pool(concurrency=3) for node in self.nodes.values(): pool.append(node.suspend) - yield from pool.join() + await pool.join() - @asyncio.coroutine - def duplicate_node(self, node, x, y, z): + async def duplicate_node(self, node, x, y, z): """ Duplicate a node @@ -959,25 +1089,35 @@ class Project: data['x'] = x data['y'] = y data['z'] = z + data['locked'] = False # duplicated node must not be locked new_node_uuid = str(uuid.uuid4()) - new_node = yield from self.add_node( + new_node = await self.add_node( node.compute, node.name, new_node_uuid, node_type=node_type, **data) try: - yield from node.post("/duplicate", timeout=None, data={ + await node.post("/duplicate", timeout=None, data={ "destination_node_id": new_node_uuid }) except aiohttp.web.HTTPNotFound as e: - yield from self.delete_node(new_node_uuid) + await self.delete_node(new_node_uuid) raise aiohttp.web.HTTPConflict(text="This node type cannot be duplicated") except aiohttp.web.HTTPConflict as e: - yield from self.delete_node(new_node_uuid) + await self.delete_node(new_node_uuid) raise e return new_node + def stats(self): + + return { + "nodes": len(self._nodes), + "links": len(self._links), + "drawings": len(self._drawings), + "snapshots": len(self._snapshots) + } + def __json__(self): return { "name": self._name, @@ -994,7 +1134,11 @@ class Project: "show_layers": self._show_layers, "snap_to_grid": self._snap_to_grid, "show_grid": self._show_grid, - "show_interface_labels": self._show_interface_labels + "grid_size": self._grid_size, + "drawing_grid_size": self._drawing_grid_size, + "show_interface_labels": self._show_interface_labels, + "supplier": self._supplier, + "variables": self._variables } def __repr__(self): diff --git a/gns3server/controller/snapshot.py b/gns3server/controller/snapshot.py index 4163a6b1..72be81fd 100644 --- a/gns3server/controller/snapshot.py +++ b/gns3server/controller/snapshot.py @@ -19,13 +19,21 @@ import os import uuid import shutil -import asyncio +import tempfile +import aiofiles +import zipfile +import time import aiohttp.web from datetime import datetime, timezone - +from ..utils.asyncio import wait_run_in_executor +from ..utils.asyncio import aiozipstream +from .export_project import export_project from .import_project import import_project +import logging +log = logging.getLogger(__name__) + # The string use to extract the date from the filename FILENAME_TIME_FORMAT = "%d%m%y_%H%M%S" @@ -71,25 +79,54 @@ class Snapshot: def created_at(self): return int(self._created_at) - @asyncio.coroutine - def restore(self): + async def create(self): + """ + Create the snapshot + """ + + if os.path.exists(self.path): + raise aiohttp.web.HTTPConflict(text="The snapshot file '{}' already exists".format(self.name)) + + snapshot_directory = os.path.join(self._project.path, "snapshots") + try: + os.makedirs(snapshot_directory, exist_ok=True) + except OSError as e: + raise aiohttp.web.HTTPInternalServerError(text="Could not create the snapshot directory '{}': {}".format(snapshot_directory, e)) + + try: + begin = time.time() + with tempfile.TemporaryDirectory() as tmpdir: + # Do not compress the snapshots + with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream: + await export_project(zstream, self._project, tmpdir, keep_compute_id=True, allow_all_nodes=True) + async with aiofiles.open(self.path, 'wb') as f: + async for chunk in zstream: + await f.write(chunk) + log.info("Snapshot '{}' created in {:.4f} seconds".format(self.name, time.time() - begin)) + except (ValueError, OSError, RuntimeError) as e: + raise aiohttp.web.HTTPConflict(text="Could not create snapshot file '{}': {}".format(self.path, e)) + + async def restore(self): """ Restore the snapshot """ - yield from self._project.delete_on_computes() - # We don't send close notif to clients because the close / open dance is purely internal - yield from self._project.close(ignore_notification=True) - self._project.controller.notification.emit("snapshot.restored", self.__json__()) + await self._project.delete_on_computes() + # We don't send close notification to clients because the close / open dance is purely internal + await self._project.close(ignore_notification=True) + try: - if os.path.exists(os.path.join(self._project.path, "project-files")): - shutil.rmtree(os.path.join(self._project.path, "project-files")) + # delete the current project files + project_files_path = os.path.join(self._project.path, "project-files") + if os.path.exists(project_files_path): + await wait_run_in_executor(shutil.rmtree, project_files_path) with open(self._path, "rb") as f: - project = yield from import_project(self._project.controller, self._project.id, f, location=self._project.path) + project = await import_project(self._project.controller, self._project.id, f, location=self._project.path) except (OSError, PermissionError) as e: raise aiohttp.web.HTTPConflict(text=str(e)) - yield from project.open() - return project + await project.open() + self._project.emit_notification("snapshot.restored", self.__json__()) + return self._project def __json__(self): return { diff --git a/gns3server/controller/symbol_themes.py b/gns3server/controller/symbol_themes.py new file mode 100644 index 00000000..68937ce6 --- /dev/null +++ b/gns3server/controller/symbol_themes.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 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 . + + +CLASSIC_SYMBOL_THEME = {"cloud": ":/symbols/classic/cloud.svg", + "ethernet_switch": ":/symbols/classic/ethernet_switch.svg", + "ethernet_hub": ":/symbols/classic/hub.svg", + "frame_relay_switch": ":/symbols/classic/frame_relay_switch.svg", + "atm_switch": ":/symbols/classic/atm_switch.svg", + "router": ":/symbols/classic/router.svg", + "multilayer_switch": ":/symbols/classic/multilayer_switch.svg", + "firewall": ":/symbols/classic/firewall.svg", + "computer": ":/symbols/classic/computer.svg", + "vpcs_guest": ":/symbols/classic/vpcs_guest.svg", + "qemu_guest": ":/symbols/classic/qemu_guest.svg", + "vbox_guest": ":/symbols/classic/vbox_guest.svg", + "vmware_guest": ":/symbols/classic/vmware_guest.svg", + "docker_guest": ":/symbols/classic/docker_guest.svg"} + +AFFINITY_SQUARE_BLUE_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/blue/cloud.svg", + "ethernet_switch": ":/symbols/affinity/square/blue/switch.svg", + "ethernet_hub": ":/symbols/affinity/square/blue/hub.svg", + "frame_relay_switch.svg": ":/symbols/affinity/square/blue/isdn.svg", + "atm_switch": ":/symbols/affinity/square/blue/atm.svg", + "router": ":/symbols/affinity/square/blue/router.svg", + "multilayer_switch": ":/symbols/affinity/square/blue/switch_multilayer.svg", + "firewall": ":/symbols/affinity/square/blue/firewall3.svg", + "computer": ":/symbols/affinity/square/blue/client.svg", + "vpcs_guest": ":/symbols/affinity/square/blue/client.svg", + "qemu_guest": ":/symbols/affinity/square/blue/client_vm.svg", + "vbox_guest": ":/symbols/affinity/square/blue/virtualbox.svg", + "vmware_guest": ":/symbols/affinity/square/blue/vmware.svg", + "docker_guest": ":/symbols/affinity/square/blue/docker.svg"} + +AFFINITY_SQUARE_RED_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/red/cloud.svg", + "ethernet_switch": ":/symbols/affinity/square/red/switch.svg", + "ethernet_hub": ":/symbols/affinity/square/red/hub.svg", + "frame_relay_switch": ":/symbols/affinity/square/red/isdn.svg", + "atm_switch": ":/symbols/affinity/square/red/atm.svg", + "router": ":/symbols/affinity/square/red/router.svg", + "multilayer_switch": ":/symbols/affinity/square/red/switch_multilayer.svg", + "firewall": ":/symbols/affinity/square/red/firewall3.svg", + "computer": ":/symbols/affinity/square/red/client.svg", + "vpcs_guest": ":/symbols/affinity/square/red/client.svg", + "qemu_guest": ":/symbols/affinity/square/red/client_vm.svg", + "vbox_guest": ":/symbols/affinity/square/red/virtualbox.svg", + "vmware_guest": ":/symbols/affinity/square/red/vmware.svg", + "docker_guest": ":/symbols/affinity/square/red/docker.svg"} + +AFFINITY_SQUARE_GRAY_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/gray/cloud.svg", + "ethernet_switch": ":/symbols/affinity/square/gray/switch.svg", + "ethernet_hub": ":/symbols/affinity/square/gray/hub.svg", + "frame_relay_switch": ":/symbols/affinity/square/gray/isdn.svg", + "atm_switch": ":/symbols/affinity/square/gray/atm.svg", + "router": ":/symbols/affinity/square/gray/router.svg", + "multilayer_switch": ":/symbols/affinity/square/gray/switch_multilayer.svg", + "firewall": ":/symbols/affinity/square/gray/firewall3.svg", + "computer": ":/symbols/affinity/square/gray/client.svg", + "vpcs_guest": ":/symbols/affinity/square/gray/client.svg", + "qemu_guest": ":/symbols/affinity/square/gray/client_vm.svg", + "vbox_guest": ":/symbols/affinity/square/gray/virtualbox.svg", + "vmware_guest": ":/symbols/affinity/square/gray/vmware.svg", + "docker_guest": ":/symbols/affinity/square/gray/docker.svg"} + +AFFINITY_CIRCLE_BLUE_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/blue/cloud.svg", + "ethernet_switch": ":/symbols/affinity/circle/blue/switch.svg", + "ethernet_hub": ":/symbols/affinity/circle/blue/hub.svg", + "frame_relay_switch": ":/symbols/affinity/circle/blue/isdn.svg", + "atm_switch": ":/symbols/affinity/circle/blue/atm.svg", + "router": ":/symbols/affinity/circle/blue/router.svg", + "multilayer_switch": ":/symbols/affinity/circle/blue/switch_multilayer.svg", + "firewall": ":/symbols/affinity/circle/blue/firewall3.svg", + "computer": ":/symbols/affinity/circle/blue/client.svg", + "vpcs_guest": ":/symbols/affinity/circle/blue/client.svg", + "qemu_guest": ":/symbols/affinity/circle/blue/client_vm.svg", + "vbox_guest": ":/symbols/affinity/circle/blue/virtualbox.svg", + "vmware_guest": ":/symbols/affinity/circle/blue/vmware.svg", + "docker_guest": ":/symbols/affinity/circle/blue/docker.svg"} + +AFFINITY_CIRCLE_RED_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/red/cloud.svg", + "ethernet_switch": ":/symbols/affinity/circle/red/switch.svg", + "ethernet_hub": ":/symbols/affinity/circle/red/hub.svg", + "frame_relay_switch": ":/symbols/affinity/circle/red/isdn.svg", + "atm_switch": ":/symbols/affinity/circle/red/atm.svg", + "router": ":/symbols/affinity/circle/red/router.svg", + "multilayer_switch": ":/symbols/affinity/circle/red/switch_multilayer.svg", + "firewall": ":/symbols/affinity/circle/red/firewall3.svg", + "computer": ":/symbols/affinity/circle/red/client.svg", + "vpcs_guest": ":/symbols/affinity/circle/red/client.svg", + "qemu_guest": ":/symbols/affinity/circle/red/client_vm.svg", + "vbox_guest": ":/symbols/affinity/circle/red/virtualbox.svg", + "vmware_guest": ":/symbols/affinity/circle/red/vmware.svg", + "docker_guest": ":/symbols/affinity/circle/red/docker.svg"} + +AFFINITY_CIRCLE_GRAY_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/gray/cloud.svg", + "ethernet_switch": ":/symbols/affinity/circle/gray/switch.svg", + "ethernet_hub": ":/symbols/affinity/circle/gray/hub.svg", + "frame_relay_switch": ":/symbols/affinity/circle/gray/isdn.svg", + "atm_switch": ":/symbols/affinity/circle/gray/atm.svg", + "router": ":/symbols/affinity/circle/gray/router.svg", + "multilayer_switch": ":/symbols/affinity/circle/gray/switch_multilayer.svg", + "firewall": ":/symbols/affinity/circle/gray/firewall3.svg", + "computer": ":/symbols/affinity/circle/gray/client.svg", + "vpcs_guest": ":/symbols/affinity/circle/gray/client.svg", + "qemu_guest": ":/symbols/affinity/circle/gray/client_vm.svg", + "vbox_guest": ":/symbols/affinity/circle/gray/virtualbox.svg", + "vmware_guest": ":/symbols/affinity/circle/gray/vmware.svg", + "docker_guest": ":/symbols/affinity/circle/gray/docker.svg"} + +BUILTIN_SYMBOL_THEMES = {"Classic": CLASSIC_SYMBOL_THEME, + "Affinity-square-blue": AFFINITY_SQUARE_BLUE_SYMBOL_THEME, + "Affinity-square-red": AFFINITY_SQUARE_RED_SYMBOL_THEME, + "Affinity-square-gray": AFFINITY_SQUARE_GRAY_SYMBOL_THEME, + "Affinity-circle-blue": AFFINITY_CIRCLE_BLUE_SYMBOL_THEME, + "Affinity-circle-red": AFFINITY_CIRCLE_RED_SYMBOL_THEME, + "Affinity-circle-gray": AFFINITY_CIRCLE_GRAY_SYMBOL_THEME} diff --git a/gns3server/controller/symbols.py b/gns3server/controller/symbols.py index 63da9225..bd89dea2 100644 --- a/gns3server/controller/symbols.py +++ b/gns3server/controller/symbols.py @@ -16,12 +16,17 @@ # along with this program. If not, see . import os +import aiohttp +import posixpath - +from .symbol_themes import BUILTIN_SYMBOL_THEMES from ..utils.get_resource import get_resource from ..utils.picture import get_size from ..config import Config +import logging +log = logging.getLogger(__name__) + class Symbols: """ @@ -29,62 +34,106 @@ class Symbols: """ def __init__(self): + try: self.list() - except OSError: # The error will be raised and forward later + except OSError: # The error will be raised and forwarded later pass + # Keep a cache of symbols size self._symbol_size_cache = {} + self._current_theme = "Classic" + self._themes = BUILTIN_SYMBOL_THEMES + + @property + def theme(self): + + return self._current_theme + + @theme.setter + def theme(self, theme): + + if not self._themes.get(theme): + raise aiohttp.web.HTTPNotFound(text="Could not find symbol theme '{}'".format(theme)) + self._current_theme = theme + + def default_symbols(self): + + return BUILTIN_SYMBOL_THEMES + + def get_default_symbol(self, symbol, symbol_theme): + + theme = self._themes.get(symbol_theme, None) + if not theme: + raise aiohttp.web.HTTPNotFound(text="Could not find symbol theme '{}'".format(symbol_theme)) + symbol_path = theme.get(symbol) + if symbol_path not in self._symbols_path: + log.warning("Default symbol {} was not found".format(symbol_path)) + return None + return symbol_path def list(self): + self._symbols_path = {} symbols = [] if get_resource("symbols"): - for file in os.listdir(get_resource("symbols")): - if file.startswith('.'): - continue - symbol_id = ':/symbols/' + file - symbols.append({ - 'symbol_id': symbol_id, - 'filename': file, - 'builtin': True, - }) - self._symbols_path[symbol_id] = os.path.join(get_resource("symbols"), file) + for root, _, files in os.walk(get_resource("symbols")): + for filename in files: + if filename.startswith('.'): + continue + symbol_file = posixpath.normpath(os.path.relpath(os.path.join(root, filename), get_resource("symbols"))).replace('\\', '/') + theme = posixpath.dirname(symbol_file).replace('/', '-').capitalize() + if not theme: + continue + symbol_id = ':/symbols/' + symbol_file + symbols.append({'symbol_id': symbol_id, + 'filename': filename, + 'theme': theme, + 'builtin': True}) + self._symbols_path[symbol_id] = os.path.join(root, filename) + directory = self.symbols_path() if directory: - for file in os.listdir(directory): - if file.startswith('.'): - continue - if not os.path.isfile(os.path.join(directory, file)): - continue - symbol_id = file - symbols.append({ - 'symbol_id': symbol_id, - 'filename': file, - 'builtin': False, - }) - self._symbols_path[symbol_id] = os.path.join(directory, file) + for root, _, files in os.walk(directory): + for filename in files: + if filename.startswith('.'): + continue + symbol_file = posixpath.normpath(os.path.relpath(os.path.join(root, filename), directory)).replace('\\', '/') + symbols.append({'symbol_id': symbol_file, + 'filename': filename, + 'builtin': False, + 'theme': "Custom symbols"}) + self._symbols_path[symbol_file] = os.path.join(root, filename) symbols.sort(key=lambda x: x["filename"]) - return symbols def symbols_path(self): directory = os.path.expanduser(Config.instance().get_section_config("Server").get("symbols_path", "~/GNS3/symbols")) if directory: - os.makedirs(directory, exist_ok=True) + try: + os.makedirs(directory, exist_ok=True) + except OSError as e: + log.error("Could not create symbol directory '{}': {}".format(directory, e)) + return None return directory def get_path(self, symbol_id): try: return self._symbols_path[symbol_id] - # Symbol not found refresh cache except KeyError: - self.list() try: + self.list() return self._symbols_path[symbol_id] - except KeyError: - return self._symbols_path[":/symbols/computer.svg"] + except (OSError, KeyError): + # try to return a symbol with the same name from the classic theme + symbol = self._symbols_path.get(":/symbols/classic/{}".format(os.path.basename(symbol_id))) + if symbol: + return symbol + else: + # return the default computer symbol + log.warning("Could not retrieve symbol '{}'".format(symbol_id)) + return self._symbols_path[":/symbols/classic/computer.svg"] def get_size(self, symbol_id): try: diff --git a/gns3server/controller/template.py b/gns3server/controller/template.py new file mode 100644 index 00000000..9d2b6bd8 --- /dev/null +++ b/gns3server/controller/template.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 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 copy +import uuid +import json +import jsonschema + +from gns3server.schemas.cloud_template import CLOUD_TEMPLATE_OBJECT_SCHEMA +from gns3server.schemas.ethernet_switch_template import ETHERNET_SWITCH_TEMPLATE_OBJECT_SCHEMA +from gns3server.schemas.ethernet_hub_template import ETHERNET_HUB_TEMPLATE_OBJECT_SCHEMA +from gns3server.schemas.docker_template import DOCKER_TEMPLATE_OBJECT_SCHEMA +from gns3server.schemas.vpcs_template import VPCS_TEMPLATE_OBJECT_SCHEMA +from gns3server.schemas.traceng_template import TRACENG_TEMPLATE_OBJECT_SCHEMA +from gns3server.schemas.virtualbox_template import VIRTUALBOX_TEMPLATE_OBJECT_SCHEMA +from gns3server.schemas.vmware_template import VMWARE_TEMPLATE_OBJECT_SCHEMA +from gns3server.schemas.iou_template import IOU_TEMPLATE_OBJECT_SCHEMA +from gns3server.schemas.qemu_template import QEMU_TEMPLATE_OBJECT_SCHEMA + +from gns3server.schemas.dynamips_template import ( + DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + C7200_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + C3745_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + C3725_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + C3600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + C2691_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + C2600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + C1700_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA +) + +import logging +log = logging.getLogger(__name__) + + +# Add default values for missing entries in a request, largely taken from jsonschema documentation example +# https://python-jsonschema.readthedocs.io/en/latest/faq/#why-doesn-t-my-schema-s-default-property-set-the-default-on-my-instance +def extend_with_default(validator_class): + + validate_properties = validator_class.VALIDATORS["properties"] + def set_defaults(validator, properties, instance, schema): + if jsonschema.Draft4Validator(schema).is_valid(instance): + # only add default for the matching sub-schema (e.g. when using 'oneOf') + for property, subschema in properties.items(): + if "default" in subschema: + instance.setdefault(property, subschema["default"]) + + for error in validate_properties(validator, properties, instance, schema,): + yield error + + return jsonschema.validators.extend( + validator_class, {"properties" : set_defaults}, + ) + + +ValidatorWithDefaults = extend_with_default(jsonschema.Draft4Validator) + +ID_TO_CATEGORY = { + 3: "firewall", + 2: "guest", + 1: "switch", + 0: "router" +} + +TEMPLATE_TYPE_TO_SHEMA = { + "cloud": CLOUD_TEMPLATE_OBJECT_SCHEMA, + "ethernet_hub": ETHERNET_HUB_TEMPLATE_OBJECT_SCHEMA, + "ethernet_switch": ETHERNET_SWITCH_TEMPLATE_OBJECT_SCHEMA, + "docker": DOCKER_TEMPLATE_OBJECT_SCHEMA, + "dynamips": DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + "vpcs": VPCS_TEMPLATE_OBJECT_SCHEMA, + "traceng": TRACENG_TEMPLATE_OBJECT_SCHEMA, + "virtualbox": VIRTUALBOX_TEMPLATE_OBJECT_SCHEMA, + "vmware": VMWARE_TEMPLATE_OBJECT_SCHEMA, + "iou": IOU_TEMPLATE_OBJECT_SCHEMA, + "qemu": QEMU_TEMPLATE_OBJECT_SCHEMA +} + +DYNAMIPS_PLATFORM_TO_SHEMA = { + "c7200": C7200_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + "c3745": C3745_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + "c3725": C3725_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + "c3600": C3600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + "c2691": C2691_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + "c2600": C2600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA, + "c1700": C1700_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA +} + + +class Template: + + def __init__(self, template_id, settings, builtin=False): + + if template_id is None: + self._id = str(uuid.uuid4()) + elif isinstance(template_id, uuid.UUID): + self._id = str(template_id) + else: + self._id = template_id + + self._settings = copy.deepcopy(settings) + + # Version of the gui before 2.1 use linked_base + # and the server linked_clone + if "linked_base" in self.settings: + linked_base = self._settings.pop("linked_base") + if "linked_clone" not in self._settings: + self._settings["linked_clone"] = linked_base + + # Convert old GUI category to text category + try: + self._settings["category"] = ID_TO_CATEGORY[self._settings["category"]] + except KeyError: + pass + + # The "server" setting has been replaced by "compute_id" setting in version 2.2 + if "server" in self._settings: + self._settings["compute_id"] = self._settings.pop("server") + + # The "node_type" setting has been replaced by "template_type" setting in version 2.2 + if "node_type" in self._settings: + self._settings["template_type"] = self._settings.pop("node_type") + + # Remove an old IOU setting + if self._settings["template_type"] == "iou" and "image" in self._settings: + del self._settings["image"] + + self._builtin = builtin + + if builtin is False: + self.validate_and_apply_defaults(TEMPLATE_TYPE_TO_SHEMA[self.template_type]) + + if self.template_type == "dynamips": + # special case for Dynamips to cover all platform types that contain specific settings + self.validate_and_apply_defaults(DYNAMIPS_PLATFORM_TO_SHEMA[self._settings["platform"]]) + + @property + def id(self): + return self._id + + @property + def settings(self): + return self._settings + + @settings.setter + def settings(self, settings): + self._settings.update(settings) + + @property + def name(self): + return self._settings["name"] + + @property + def compute_id(self): + return self._settings["compute_id"] + + @property + def template_type(self): + return self._settings["template_type"] + + @property + def builtin(self): + return self._builtin + + def update(self, **kwargs): + + self._settings.update(kwargs) + from gns3server.controller import Controller + controller = Controller.instance() + controller.notification.controller_emit("template.updated", self.__json__()) + controller.save() + + def validate_and_apply_defaults(self, schema): + + validator = ValidatorWithDefaults(schema) + try: + validator.validate(self.__json__()) + except jsonschema.ValidationError as e: + message = "JSON schema error {}".format(e.message) + log.error(message) + log.debug("Input schema: {}".format(json.dumps(schema))) + raise + + def __json__(self): + """ + Template settings. + """ + + settings = self._settings + settings.update({"template_id": self._id, + "builtin": self.builtin}) + + if not self.builtin: + settings["compute_id"] = self.compute_id + + return settings diff --git a/gns3server/controller/template_manager.py b/gns3server/controller/template_manager.py new file mode 100644 index 00000000..63239fde --- /dev/null +++ b/gns3server/controller/template_manager.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 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 copy +import uuid +import aiohttp +import jsonschema + +from .template import Template + +import logging +log = logging.getLogger(__name__) + + +class TemplateManager: + """ + Manages templates. + """ + + def __init__(self): + + self._templates = {} + + @property + def templates(self): + """ + :returns: The dictionary of templates managed by GNS3 + """ + + return self._templates + + def load_templates(self, template_settings=None): + """ + Loads templates from controller settings. + """ + + if template_settings: + for template_settings in template_settings: + try: + template = Template(template_settings.get("template_id"), template_settings) + self._templates[template.id] = template + except jsonschema.ValidationError as e: + message = "Cannot load template with JSON data '{}': {}".format(template_settings, e.message) + log.warning(message) + continue + + # Add builtins + builtins = [] + builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "cloud"), {"template_type": "cloud", "name": "Cloud", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True)) + builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "nat"), {"template_type": "nat", "name": "NAT", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True)) + builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "vpcs"), {"template_type": "vpcs", "name": "VPCS", "default_name_format": "PC-{0}", "category": 2, "symbol": ":/symbols/vpcs_guest.svg", "properties": {"base_script_file": "vpcs_base_config.txt"}}, builtin=True)) + builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_switch"), {"template_type": "ethernet_switch", "console_type": "none", "name": "Ethernet switch", "category": 1, "symbol": ":/symbols/ethernet_switch.svg"}, builtin=True)) + builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_hub"), {"template_type": "ethernet_hub", "name": "Ethernet hub", "category": 1, "symbol": ":/symbols/hub.svg"}, builtin=True)) + builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "frame_relay_switch"), {"template_type": "frame_relay_switch", "name": "Frame Relay switch", "category": 1, "symbol": ":/symbols/frame_relay_switch.svg"}, builtin=True)) + builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "atm_switch"), {"template_type": "atm_switch", "name": "ATM switch", "category": 1, "symbol": ":/symbols/atm_switch.svg"}, builtin=True)) + + #FIXME: disable TraceNG + #if sys.platform.startswith("win"): + # builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "traceng"), {"template_type": "traceng", "name": "TraceNG", "default_name_format": "TraceNG-{0}", "category": 2, "symbol": ":/symbols/traceng.svg", "properties": {}}, builtin=True)) + for b in builtins: + self._templates[b.id] = b + + def add_template(self, settings): + """ + Adds a new template. + + :param settings: template settings + + :returns: Template object + """ + + template_id = settings.get("template_id", "") + if template_id in self._templates: + raise aiohttp.web.HTTPConflict(text="Template ID '{}' already exists".format(template_id)) + else: + template_id = settings.setdefault("template_id", str(uuid.uuid4())) + try: + template = Template(template_id, settings) + except jsonschema.ValidationError as e: + message = "JSON schema error adding template with JSON data '{}': {}".format(settings, e.message) + raise aiohttp.web.HTTPBadRequest(text=message) + self._templates[template.id] = template + from . import Controller + Controller.instance().save() + Controller.instance().notification.controller_emit("template.created", template.__json__()) + return template + + def get_template(self, template_id): + """ + Gets a template. + + :param template_id: template identifier + + :returns: Template object + """ + + template = self._templates.get(template_id) + if not template: + raise aiohttp.web.HTTPNotFound(text="Template ID {} doesn't exist".format(template_id)) + return template + + def delete_template(self, template_id): + """ + Deletes a template. + + :param template_id: template identifier + """ + + template = self.get_template(template_id) + if template.builtin: + raise aiohttp.web.HTTPConflict(text="Template ID {} cannot be deleted because it is a builtin".format(template_id)) + self._templates.pop(template_id) + from . import Controller + Controller.instance().save() + Controller.instance().notification.controller_emit("template.deleted", template.__json__()) + + def duplicate_template(self, template_id): + """ + Duplicates a template. + + :param template_id: template identifier + """ + + template = self.get_template(template_id) + if template.builtin: + raise aiohttp.web.HTTPConflict(text="Template ID {} cannot be duplicated because it is a builtin".format(template_id)) + template_settings = copy.deepcopy(template.settings) + del template_settings["template_id"] + return self.add_template(template_settings) + + diff --git a/gns3server/controller/topology.py b/gns3server/controller/topology.py index d88db985..4e7326e6 100644 --- a/gns3server/controller/topology.py +++ b/gns3server/controller/topology.py @@ -37,7 +37,7 @@ import logging log = logging.getLogger(__name__) -GNS3_FILE_FORMAT_REVISION = 8 +GNS3_FILE_FORMAT_REVISION = 9 def _check_topology_schema(topo): @@ -83,7 +83,11 @@ def project_to_topology(project): "show_layers": project.show_layers, "snap_to_grid": project.snap_to_grid, "show_grid": project.show_grid, + "grid_size": project.grid_size, + "drawing_grid_size": project.drawing_grid_size, "show_interface_labels": project.show_interface_labels, + "variables": project.variables, + "supplier": project.supplier, "topology": { "nodes": [], "links": [], @@ -151,6 +155,18 @@ def load_topology(path): if topo["revision"] < 8: topo = _convert_2_0_0(topo, path) + # Version before GNS3 2.1 + if topo["revision"] < 9: + topo = _convert_2_1_0(topo, path) + + # Version GNS3 2.2 dev (for project created with 2.2dev). + # Appliance ID has been replaced by Template ID + if topo["revision"] == 9: + for node in topo.get("topology", {}).get("nodes", []): + if "appliance_id" in node: + node["template_id"] = node["appliance_id"] + del node["appliance_id"] + try: _check_topology_schema(topo) except aiohttp.web.HTTPConflict as e: @@ -161,11 +177,39 @@ def load_topology(path): try: with open(path, "w+", encoding="utf-8") as f: json.dump(topo, f, indent=4, sort_keys=True) - except (OSError) as e: + except OSError as e: raise aiohttp.web.HTTPConflict(text="Can't write the topology {}: {}".format(path, str(e))) return topo +def _convert_2_1_0(topo, topo_path): + """ + Convert topologies from GNS3 2.1.x to 2.2 + + Changes: + * Removed acpi_shutdown option from Qemu, VMware and VirtualBox + """ + topo["revision"] = 9 + + if "grid_size" in topo: + # drawing_grid_size should be the same size as grid_size + # to avoid overlapping grids + topo["drawing_grid_size"] = topo["grid_size"] + + for node in topo.get("topology", {}).get("nodes", []): + if "properties" in node: + if node["node_type"] in ("qemu", "vmware", "virtualbox"): + if "acpi_shutdown" in node["properties"]: + if node["properties"]["acpi_shutdown"] is True: + node["properties"]["on_close"] = "save_vm_sate" + else: + node["properties"]["on_close"] = "power_off" + del node["properties"]["acpi_shutdown"] + if "save_vm_state" in node["properties"]: + del node["properties"]["save_vm_state"] + return topo + + def _convert_2_0_0(topo, topo_path): """ Convert topologies from GNS3 2.0.0 to 2.1 @@ -406,7 +450,7 @@ def _convert_1_3_later(topo, topo_path): symbol = old_node.get("symbol", ":/symbols/computer.svg") old_node["ports"] = _create_cloud(node, old_node, symbol) else: - raise NotImplementedError("Conversion of {} is not supported".format(old_node["type"])) + raise aiohttp.web.HTTPConflict(text="Conversion of {} is not supported".format(old_node["type"])) for prop in old_node.get("properties", {}): if prop not in ["console", "name", "console_type", "console_host", "use_ubridge"]: @@ -605,13 +649,13 @@ def _create_cloud(node, old_node, icon): elif old_port["name"].startswith("nio_nat"): continue else: - raise NotImplementedError("The conversion of cloud with {} is not supported".format(old_port["name"])) + raise aiohttp.web.HTTPConflict(text="The conversion of cloud with {} is not supported".format(old_port["name"])) if port_type == "udp": try: _, lport, rhost, rport = old_port["name"].split(":") except ValueError: - raise NotImplementedError("UDP tunnel using IPV6 is not supported in cloud") + raise aiohttp.web.HTTPConflict(text="UDP tunnel using IPV6 is not supported in cloud") port = { "name": "UDP tunnel {}".format(len(ports) + 1), "port_number": len(ports) + 1, @@ -642,7 +686,7 @@ def _convert_snapshots(topo_dir): old_snapshots_dir = os.path.join(topo_dir, "project-files", "snapshots") if os.path.exists(old_snapshots_dir): new_snapshots_dir = os.path.join(topo_dir, "snapshots") - os.makedirs(new_snapshots_dir) + os.makedirs(new_snapshots_dir, exist_ok=True) for snapshot in os.listdir(old_snapshots_dir): snapshot_dir = os.path.join(old_snapshots_dir, snapshot) diff --git a/gns3server/controller/udp_link.py b/gns3server/controller/udp_link.py index 479d66b5..97d4b916 100644 --- a/gns3server/controller/udp_link.py +++ b/gns3server/controller/udp_link.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import asyncio + import aiohttp @@ -26,7 +26,6 @@ class UDPLink(Link): def __init__(self, project, link_id=None): super().__init__(project, link_id=link_id) - self._capture_node = None self._created = False self._link_data = [] @@ -37,8 +36,7 @@ class UDPLink(Link): """ return self._link_data - @asyncio.coroutine - def create(self): + async def create(self): """ Create the link on the nodes """ @@ -52,14 +50,14 @@ class UDPLink(Link): # Get an IP allowing communication between both host try: - (node1_host, node2_host) = yield from node1.compute.get_ip_on_same_subnet(node2.compute) + (node1_host, node2_host) = await node1.compute.get_ip_on_same_subnet(node2.compute) except ValueError as e: - raise aiohttp.web.HTTPConflict(text=str(e)) + raise aiohttp.web.HTTPConflict(text="Cannot get an IP address on same subnet: {}".format(e)) # Reserve a UDP port on both side - response = yield from node1.compute.post("/projects/{}/ports/udp".format(self._project.id)) + response = await node1.compute.post("/projects/{}/ports/udp".format(self._project.id)) self._node1_port = response.json["udp_port"] - response = yield from node2.compute.post("/projects/{}/ports/udp".format(self._project.id)) + response = await node2.compute.post("/projects/{}/ports/udp".format(self._project.id)) self._node2_port = response.json["udp_port"] node1_filters = {} @@ -76,46 +74,60 @@ class UDPLink(Link): "rhost": node2_host, "rport": self._node2_port, "type": "nio_udp", - "filters": node1_filters + "filters": node1_filters, + "suspend": self._suspended }) - yield from node1.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=self._link_data[0], timeout=120) + await node1.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=self._link_data[0], timeout=120) self._link_data.append({ "lport": self._node2_port, "rhost": node1_host, "rport": self._node1_port, "type": "nio_udp", - "filters": node2_filters + "filters": node2_filters, + "suspend": self._suspended }) try: - yield from node2.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=self._link_data[1], timeout=120) + await node2.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=self._link_data[1], timeout=120) except Exception as e: # We clean the first NIO - yield from node1.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), timeout=120) + await node1.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), timeout=120) raise e self._created = True - @asyncio.coroutine - def update(self): + async def update(self): + """ + Update the link on the nodes + """ + if len(self._link_data) == 0: return node1 = self._nodes[0]["node"] node2 = self._nodes[1]["node"] + + node1_filters = {} + node2_filters = {} filter_node = self._get_filter_node() + if filter_node == node1: + node1_filters = self.get_active_filters() + elif filter_node == node2: + node2_filters = self.get_active_filters() - if node1 == filter_node: - adapter_number1 = self._nodes[0]["adapter_number"] - port_number1 = self._nodes[0]["port_number"] - self._link_data[0]["filters"] = self.get_active_filters() - yield from node1.put("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=self._link_data[0], timeout=120) - elif node2 == filter_node: - adapter_number2 = self._nodes[1]["adapter_number"] - port_number2 = self._nodes[1]["port_number"] - self._link_data[1]["filters"] = self.get_active_filters() - yield from node2.put("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=self._link_data[1], timeout=221) + adapter_number1 = self._nodes[0]["adapter_number"] + port_number1 = self._nodes[0]["port_number"] + self._link_data[0]["filters"] = node1_filters + self._link_data[0]["suspend"] = self._suspended + if node1.node_type not in ("ethernet_switch", "ethernet_hub"): + await node1.put("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=self._link_data[0], timeout=120) - @asyncio.coroutine - def delete(self): + adapter_number2 = self._nodes[1]["adapter_number"] + port_number2 = self._nodes[1]["port_number"] + self._link_data[1]["filters"] = node2_filters + self._link_data[1]["suspend"] = self._suspended + if node2.node_type not in ("ethernet_switch", "ethernet_hub"): + await node2.put("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=self._link_data[1], timeout=221) + + async def delete(self): """ Delete the link and free the resources """ @@ -128,7 +140,7 @@ class UDPLink(Link): except IndexError: return try: - yield from node1.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), timeout=120) + await node1.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), timeout=120) # If the node is already delete (user selected multiple element and delete all in the same time) except aiohttp.web.HTTPNotFound: pass @@ -140,36 +152,32 @@ class UDPLink(Link): except IndexError: return try: - yield from node2.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), timeout=120) + await node2.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), timeout=120) # If the node is already delete (user selected multiple element and delete all in the same time) except aiohttp.web.HTTPNotFound: pass - yield from super().delete() + await super().delete() - @asyncio.coroutine - def start_capture(self, data_link_type="DLT_EN10MB", capture_file_name=None): + async def start_capture(self, data_link_type="DLT_EN10MB", capture_file_name=None): """ Start capture on a link """ if not capture_file_name: capture_file_name = self.default_capture_file_name() self._capture_node = self._choose_capture_side() - data = { - "capture_file_name": capture_file_name, - "data_link_type": data_link_type - } - yield from self._capture_node["node"].post("/adapters/{adapter_number}/ports/{port_number}/start_capture".format(adapter_number=self._capture_node["adapter_number"], port_number=self._capture_node["port_number"]), data=data) - yield from super().start_capture(data_link_type=data_link_type, capture_file_name=capture_file_name) + data = {"capture_file_name": capture_file_name, + "data_link_type": data_link_type} + await self._capture_node["node"].post("/adapters/{adapter_number}/ports/{port_number}/start_capture".format(adapter_number=self._capture_node["adapter_number"], port_number=self._capture_node["port_number"]), data=data) + await super().start_capture(data_link_type=data_link_type, capture_file_name=capture_file_name) - @asyncio.coroutine - def stop_capture(self): + async def stop_capture(self): """ Stop capture on a link """ if self._capture_node: - yield from self._capture_node["node"].post("/adapters/{adapter_number}/ports/{port_number}/stop_capture".format(adapter_number=self._capture_node["adapter_number"], port_number=self._capture_node["port_number"])) + await self._capture_node["node"].post("/adapters/{adapter_number}/ports/{port_number}/stop_capture".format(adapter_number=self._capture_node["adapter_number"], port_number=self._capture_node["port_number"])) self._capture_node = None - yield from super().stop_capture() + await super().stop_capture() def _choose_capture_side(self): """ @@ -201,19 +209,9 @@ class UDPLink(Link): raise aiohttp.web.HTTPConflict(text="Cannot capture because there is no running device on this link") - @asyncio.coroutine - def read_pcap_from_source(self): - """ - Return a FileStream of the Pcap from the compute node - """ - if self._capture_node: - compute = self._capture_node["node"].compute - return compute.stream_file(self._project, "tmp/captures/" + self._capture_file_name) - - @asyncio.coroutine - def node_updated(self, node): + async def node_updated(self, node): """ Called when a node member of the link is updated """ if self._capture_node and node == self._capture_node["node"] and node.status != "started": - yield from self.stop_capture() + await self.stop_capture() diff --git a/gns3server/crash_report.py b/gns3server/crash_report.py index 8303eb05..320dcbe4 100644 --- a/gns3server/crash_report.py +++ b/gns3server/crash_report.py @@ -20,7 +20,8 @@ import sys import struct import aiohttp import platform - +import locale +import distro try: import raven @@ -57,7 +58,7 @@ class CrashReport: Report crash to a third party service """ - DSN = "sync+https://6b6c2ce19b8545278f7ee00c333175a6:be17229ec8da460e9a126d02b82de5dc@sentry.io/38482" + DSN = "https://6b4544f8cc1b42f798941c844ca6dfa6:885563130aca4d8e87ba097d098229a3@sentry.io/38482" if hasattr(sys, "frozen"): cacert = get_resource("cacert.pem") if cacert is not None and os.path.isfile(cacert): @@ -92,12 +93,13 @@ class CrashReport: "url": request.path, "data": request.json, }) - self._client.tags_context({ + + context = { "os:name": platform.system(), "os:release": platform.release(), "os:win_32": " ".join(platform.win32_ver()), "os:mac": "{} {}".format(platform.mac_ver()[0], platform.mac_ver()[2]), - "os:linux": " ".join(platform.linux_distribution()), + "os:linux": " ".join(distro.linux_distribution()), "aiohttp:version": aiohttp.__version__, "python:version": "{}.{}.{}".format(sys.version_info[0], sys.version_info[1], @@ -105,7 +107,28 @@ class CrashReport: "python:bit": struct.calcsize("P") * 8, "python:encoding": sys.getdefaultencoding(), "python:frozen": "{}".format(hasattr(sys, "frozen")) - }) + } + + if sys.platform.startswith("linux") and not hasattr(sys, "frozen"): + # add locale information + try: + language, encoding = locale.getlocale() + context["locale:language"] = language + context["locale:encoding"] = encoding + except ValueError: + pass + + # add GNS3 VM version if it exists + home = os.path.expanduser("~") + gns3vm_version = os.path.join(home, ".config", "GNS3", "gns3vm_version") + if os.path.isfile(gns3vm_version): + try: + with open(gns3vm_version) as fd: + context["gns3vm:version"] = fd.readline().strip() + except OSError: + pass + + self._client.tags_context(context) try: report = self._client.captureException() except Exception as e: diff --git a/gns3server/handlers/api/compute/__init__.py b/gns3server/handlers/api/compute/__init__.py index e255769a..dc2cc695 100644 --- a/gns3server/handlers/api/compute/__init__.py +++ b/gns3server/handlers/api/compute/__init__.py @@ -34,9 +34,10 @@ from .ethernet_hub_handler import EthernetHubHandler from .ethernet_switch_handler import EthernetSwitchHandler from .frame_relay_switch_handler import FrameRelaySwitchHandler from .atm_switch_handler import ATMSwitchHandler +from .traceng_handler import TraceNGHandler if sys.platform.startswith("linux") or hasattr(sys, "_called_from_test") or os.environ.get("PYTEST_BUILD_DOCUMENTATION") == "1": - # IOU runs only on Linux but test suite works on UNIX platform + # IOU & Docker only runs on Linux but test suite works on UNIX platform if not sys.platform.startswith("win"): from .iou_handler import IOUHandler from .docker_handler import DockerHandler diff --git a/gns3server/handlers/api/compute/atm_switch_handler.py b/gns3server/handlers/api/compute/atm_switch_handler.py index b57dbf42..193fe574 100644 --- a/gns3server/handlers/api/compute/atm_switch_handler.py +++ b/gns3server/handlers/api/compute/atm_switch_handler.py @@ -48,11 +48,11 @@ class ATMSwitchHandler: description="Create a new ATM switch instance", input=ATM_SWITCH_CREATE_SCHEMA, output=ATM_SWITCH_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): # Use the Dynamips ATM switch to simulate this node dynamips_manager = Dynamips.instance() - node = yield from dynamips_manager.create_node(request.json.pop("name"), + node = await dynamips_manager.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), node_type="atm_switch", @@ -90,9 +90,9 @@ class ATMSwitchHandler: 404: "Instance doesn't exist" }, description="Duplicate an atm switch instance") - def duplicate(request, response): + async def duplicate(request, response): - new_node = yield from Dynamips.instance().duplicate_node( + new_node = await Dynamips.instance().duplicate_node( request.match_info["node_id"], request.json["destination_node_id"] ) @@ -114,12 +114,12 @@ class ATMSwitchHandler: description="Update an ATM switch instance", input=ATM_SWITCH_UPDATE_SCHEMA, output=ATM_SWITCH_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) if "name" in request.json and node.name != request.json["name"]: - yield from node.set_name(request.json["name"]) + await node.set_name(request.json["name"]) if "mappings" in request.json: node.mappings = request.json["mappings"] node.updated() @@ -137,10 +137,10 @@ class ATMSwitchHandler: 404: "Instance doesn't exist" }, description="Delete an ATM switch instance") - def delete(request, response): + async def delete(request, response): dynamips_manager = Dynamips.instance() - yield from dynamips_manager.delete_node(request.match_info["node_id"]) + await dynamips_manager.delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -210,13 +210,13 @@ class ATMSwitchHandler: description="Add a NIO to an ATM switch instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = yield from dynamips_manager.create_nio(node, request.json) + nio = await dynamips_manager.create_nio(node, request.json) port_number = int(request.match_info["port_number"]) - yield from node.add_nio(nio, port_number) + await node.add_nio(nio, port_number) response.set_status(201) response.json(nio) @@ -234,13 +234,13 @@ class ATMSwitchHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from an ATM switch instance") - def delete_nio(request, response): + async def delete_nio(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - nio = yield from node.remove_nio(port_number) - yield from nio.delete() + nio = await node.remove_nio(port_number) + await nio.delete() response.set_status(204) @Route.post( @@ -258,13 +258,13 @@ class ATMSwitchHandler: }, description="Start a packet capture on an ATM switch instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) pcap_file_path = os.path.join(node.project.capture_working_directory(), request.json["capture_file_name"]) - yield from node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) + await node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -281,10 +281,32 @@ class ATMSwitchHandler: 404: "Instance doesn't exist" }, description="Stop a packet capture on an ATM switch instance") - def stop_capture(request, response): + async def stop_capture(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - yield from node.stop_capture(port_number) + await node.stop_capture(port_number) response.set_status(204) + + @Route.get( + r"/projects/{project_id}/atm_relay_switch/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture (always 0)", + "port_number": "Port on the switch" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + dynamips_manager = Dynamips.instance() + node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + nio = node.get_nio(port_number) + await dynamips_manager.stream_pcap_file(nio, node.project.id, request, response) diff --git a/gns3server/handlers/api/compute/capabilities_handler.py b/gns3server/handlers/api/compute/capabilities_handler.py index e5f28c9c..e183d6aa 100644 --- a/gns3server/handlers/api/compute/capabilities_handler.py +++ b/gns3server/handlers/api/compute/capabilities_handler.py @@ -18,11 +18,9 @@ import sys from gns3server.web.route import Route -from gns3server.config import Config from gns3server.schemas.capabilities import CAPABILITIES_SCHEMA from gns3server.version import __version__ from gns3server.compute import MODULES -from aiohttp.web import HTTPConflict class CapabilitiesHandler: diff --git a/gns3server/handlers/api/compute/cloud_handler.py b/gns3server/handlers/api/compute/cloud_handler.py index d29a4eeb..b735e866 100644 --- a/gns3server/handlers/api/compute/cloud_handler.py +++ b/gns3server/handlers/api/compute/cloud_handler.py @@ -49,14 +49,21 @@ class CloudHandler: description="Create a new cloud instance", input=CLOUD_CREATE_SCHEMA, output=CLOUD_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): builtin_manager = Builtin.instance() - node = yield from builtin_manager.create_node(request.json.pop("name"), + node = await builtin_manager.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), node_type="cloud", ports=request.json.get("ports_mapping")) + + # add the remote console settings + node.remote_console_host = request.json.get("remote_console_host", node.remote_console_host) + node.remote_console_port = request.json.get("remote_console_port", node.remote_console_port) + node.remote_console_type = request.json.get("remote_console_type", node.remote_console_type) + node.remote_console_http_path = request.json.get("remote_console_http_path", node.remote_console_http_path) + response.set_status(201) response.json(node) @@ -116,10 +123,10 @@ class CloudHandler: 404: "Instance doesn't exist" }, description="Delete a cloud instance") - def delete(request, response): + async def delete(request, response): builtin_manager = Builtin.instance() - yield from builtin_manager.delete_node(request.match_info["node_id"]) + await builtin_manager.delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -134,10 +141,10 @@ class CloudHandler: 404: "Instance doesn't exist" }, description="Start a cloud") - def start(request, response): + async def start(request, response): node = Builtin.instance().get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from node.start() + await node.start() response.set_status(204) @Route.post( @@ -190,13 +197,13 @@ class CloudHandler: description="Add a NIO to a cloud instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) nio = builtin_manager.create_nio(request.json) port_number = int(request.match_info["port_number"]) - yield from node.add_nio(nio, port_number) + await node.add_nio(nio, port_number) response.set_status(201) response.json(nio) @@ -215,21 +222,16 @@ class CloudHandler: }, input=NIO_SCHEMA, output=NIO_SCHEMA, - description="Update a NIO from a Cloud instance") - def update_nio(request, response): + description="Update a NIO on a Cloud instance") + async def update_nio(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - adapter_number = int(request.match_info["adapter_number"]) - - try: - nio = node.nios[adapter_number] - except KeyError: - raise HTTPConflict(text="NIO `{}` doesn't exist".format(adapter_number)) - - if "filters" in request.json and nio: + port_number = int(request.match_info["port_number"]) + nio = node.get_nio(port_number) + if "filters" in request.json: nio.filters = request.json["filters"] - yield from node.update_nio(int(request.match_info["port_number"]), nio) + await node.update_nio(port_number, nio) response.set_status(201) response.json(request.json) @@ -247,12 +249,12 @@ class CloudHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a cloud instance") - def delete_nio(request, response): + async def delete_nio(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - yield from node.remove_nio(port_number) + await node.remove_nio(port_number) response.set_status(204) @Route.post( @@ -270,13 +272,13 @@ class CloudHandler: }, description="Start a packet capture on a cloud instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) pcap_file_path = os.path.join(node.project.capture_working_directory(), request.json["capture_file_name"]) - yield from node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) + await node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -293,10 +295,32 @@ class CloudHandler: 404: "Instance doesn't exist" }, description="Stop a packet capture on a cloud instance") - def stop_capture(request, response): + async def stop_capture(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - yield from node.stop_capture(port_number) + await node.stop_capture(port_number) response.set_status(204) + + @Route.get( + r"/projects/{project_id}/cloud/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture (always 0)", + "port_number": "Port on the cloud" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + builtin_manager = Builtin.instance() + node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + nio = node.get_nio(port_number) + await builtin_manager.stream_pcap_file(nio, node.project.id, request, response) diff --git a/gns3server/handlers/api/compute/docker_handler.py b/gns3server/handlers/api/compute/docker_handler.py index 139cd241..83a5dd0d 100644 --- a/gns3server/handlers/api/compute/docker_handler.py +++ b/gns3server/handlers/api/compute/docker_handler.py @@ -46,9 +46,9 @@ class DockerHandler: description="Create a new Docker container", input=DOCKER_CREATE_SCHEMA, output=DOCKER_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): docker_manager = Docker.instance() - container = yield from docker_manager.create_node(request.json.pop("name"), + container = await docker_manager.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), image=request.json.pop("image"), @@ -60,7 +60,9 @@ class DockerHandler: console_resolution=request.json.get("console_resolution", "1024x768"), console_http_port=request.json.get("console_http_port", 80), console_http_path=request.json.get("console_http_path", "/"), - aux=request.json.get("aux")) + aux=request.json.get("aux"), + extra_hosts=request.json.get("extra_hosts"), + extra_volumes=request.json.get("extra_volumes")) for name, value in request.json.items(): if name != "node_id": if hasattr(container, name) and getattr(container, name) != value: @@ -81,10 +83,10 @@ class DockerHandler: 404: "Instance doesn't exist" }, description="Start a Docker container") - def start(request, response): + async def start(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from container.start() + await container.start() response.set_status(204) @Route.post( @@ -99,10 +101,10 @@ class DockerHandler: 404: "Instance doesn't exist" }, description="Stop a Docker container") - def stop(request, response): + async def stop(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from container.stop() + await container.stop() response.set_status(204) @Route.post( @@ -117,10 +119,10 @@ class DockerHandler: 404: "Instance doesn't exist" }, description="Suspend a Docker container") - def suspend(request, response): + async def suspend(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from container.pause() + await container.pause() response.set_status(204) @Route.post( @@ -135,10 +137,10 @@ class DockerHandler: 404: "Instance doesn't exist" }, description="Restart a Docker container") - def reload(request, response): + async def reload(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from container.restart() + await container.restart() response.set_status(204) @Route.delete( @@ -153,10 +155,10 @@ class DockerHandler: 404: "Instance doesn't exist" }, description="Delete a Docker container") - def delete(request, response): + async def delete(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from container.delete() + await container.delete() response.set_status(204) @Route.post( @@ -170,9 +172,9 @@ class DockerHandler: 404: "Instance doesn't exist" }, description="Duplicate a Docker instance") - def duplicate(request, response): + async def duplicate(request, response): - new_node = yield from Docker.instance().duplicate_node( + new_node = await Docker.instance().duplicate_node( request.match_info["node_id"], request.json["destination_node_id"] ) @@ -191,10 +193,10 @@ class DockerHandler: 404: "Instance doesn't exist" }, description="Pause a Docker container") - def pause(request, response): + async def pause(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from container.pause() + await container.pause() response.set_status(204) @Route.post( @@ -209,10 +211,10 @@ class DockerHandler: 404: "Instance doesn't exist" }, description="Unpause a Docker container") - def unpause(request, response): + async def unpause(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from container.unpause() + await container.unpause() response.set_status(204) @Route.post( @@ -221,7 +223,7 @@ class DockerHandler: "project_id": "Project UUID", "node_id": "Node UUID", "adapter_number": "Adapter where the nio should be added", - "port_number": "Port on the adapter" + "port_number": "Port on the adapter (always 0)" }, status_codes={ 201: "NIO created", @@ -231,14 +233,15 @@ class DockerHandler: description="Add a NIO to a Docker container", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) nio_type = request.json["type"] if nio_type != "nio_udp": raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) + adapter_number = int(request.match_info["adapter_number"]) nio = docker_manager.create_nio(request.json) - yield from container.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio) + await container.adapter_add_nio_binding(adapter_number, nio) response.set_status(201) response.json(nio) @@ -248,7 +251,7 @@ class DockerHandler: "project_id": "Project UUID", "node_id": "Node UUID", "adapter_number": "Network adapter where the nio is located", - "port_number": "Port from where the nio should be updated" + "port_number": "Port from where the nio should be updated (always 0)" }, status_codes={ 201: "NIO updated", @@ -257,15 +260,16 @@ class DockerHandler: }, input=NIO_SCHEMA, output=NIO_SCHEMA, - description="Update a NIO from a Docker instance") - def update_nio(request, response): + description="Update a NIO on a Docker instance") + async def update_nio(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = container.ethernet_adapters[int(request.match_info["adapter_number"])].get_nio(0) + adapter_number = int(request.match_info["adapter_number"]) + nio = container.get_nio(adapter_number) if "filters" in request.json and nio: nio.filters = request.json["filters"] - yield from container.adapter_update_nio_binding(int(request.match_info["port_number"]), nio) + await container.adapter_update_nio_binding(adapter_number, nio) response.set_status(201) response.json(request.json) @@ -275,7 +279,7 @@ class DockerHandler: "project_id": "Project UUID", "node_id": "Node UUID", "adapter_number": "Adapter where the nio should be added", - "port_number": "Port on the adapter" + "port_number": "Port on the adapter (always 0)" }, status_codes={ 204: "NIO deleted", @@ -283,10 +287,11 @@ class DockerHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a Docker container") - def delete_nio(request, response): + async def delete_nio(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from container.adapter_remove_nio_binding(int(request.match_info["adapter_number"])) + adapter_number = int(request.match_info["adapter_number"]) + await container.adapter_remove_nio_binding(adapter_number) response.set_status(204) @Route.put( @@ -304,7 +309,7 @@ class DockerHandler: description="Update a Docker instance", input=DOCKER_OBJECT_SCHEMA, output=DOCKER_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -312,7 +317,7 @@ class DockerHandler: props = [ "name", "console", "aux", "console_type", "console_resolution", "console_http_port", "console_http_path", "start_command", - "environment", "adapters" + "environment", "adapters", "extra_hosts", "extra_volumes" ] changed = False @@ -322,7 +327,7 @@ class DockerHandler: changed = True # We don't call container.update for nothing because it will restart the container if changed: - yield from container.update() + await container.update() container.updated() response.json(container) @@ -332,7 +337,7 @@ class DockerHandler: "project_id": "Project UUID", "node_id": "Node UUID", "adapter_number": "Adapter to start a packet capture", - "port_number": "Port on the adapter" + "port_number": "Port on the adapter (always 0)" }, status_codes={ 200: "Capture started", @@ -342,14 +347,13 @@ class DockerHandler: }, description="Start a packet capture on a Docker container instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) pcap_file_path = os.path.join(container.project.capture_working_directory(), request.json["capture_file_name"]) - - yield from container.start_capture(adapter_number, pcap_file_path) + await container.start_capture(adapter_number, pcap_file_path) response.json({"pcap_file_path": str(pcap_file_path)}) @Route.post( @@ -367,15 +371,36 @@ class DockerHandler: 409: "Container not started" }, description="Stop a packet capture on a Docker container instance") - def stop_capture(request, response): + async def stop_capture(request, response): docker_manager = Docker.instance() container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - adapter_number = int(request.match_info["adapter_number"]) - yield from container.stop_capture(adapter_number) + await container.stop_capture(adapter_number) response.set_status(204) + @Route.get( + r"/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture", + "port_number": "Port on the adapter (always 0)" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + docker_manager = Docker.instance() + container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + adapter_number = int(request.match_info["adapter_number"]) + nio = container.get_nio(adapter_number) + await docker_manager.stream_pcap_file(nio, container.project.id, request, response) + @Route.get( r"/docker/images", status_codes={ @@ -383,7 +408,7 @@ class DockerHandler: }, output=DOCKER_LIST_IMAGES_SCHEMA, description="Get all available Docker images") - def show(request, response): + async def show(request, response): docker_manager = Docker.instance() - images = yield from docker_manager.list_images() + images = await docker_manager.list_images() response.json(images) diff --git a/gns3server/handlers/api/compute/dynamips_vm_handler.py b/gns3server/handlers/api/compute/dynamips_vm_handler.py index 1f425365..88bb1a9d 100644 --- a/gns3server/handlers/api/compute/dynamips_vm_handler.py +++ b/gns3server/handlers/api/compute/dynamips_vm_handler.py @@ -62,23 +62,24 @@ class DynamipsVMHandler: description="Create a new Dynamips VM instance", input=VM_CREATE_SCHEMA, output=VM_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): dynamips_manager = Dynamips.instance() platform = request.json.pop("platform") default_chassis = None if platform in DEFAULT_CHASSIS: default_chassis = DEFAULT_CHASSIS[platform] - vm = yield from dynamips_manager.create_node(request.json.pop("name"), - request.match_info["project_id"], - request.json.get("node_id"), - dynamips_id=request.json.get("dynamips_id"), - platform=platform, - console=request.json.get("console"), - aux=request.json.get("aux"), - chassis=request.json.pop("chassis", default_chassis), - node_type="dynamips") - yield from dynamips_manager.update_vm_settings(vm, request.json) + vm = await dynamips_manager.create_node(request.json.pop("name"), + request.match_info["project_id"], + request.json.get("node_id"), + dynamips_id=request.json.get("dynamips_id"), + platform=platform, + console=request.json.get("console"), + console_type=request.json.get("console_type", "telnet"), + aux=request.json.get("aux"), + chassis=request.json.pop("chassis", default_chassis), + node_type="dynamips") + await dynamips_manager.update_vm_settings(vm, request.json) response.set_status(201) response.json(vm) @@ -116,11 +117,11 @@ class DynamipsVMHandler: description="Update a Dynamips VM instance", input=VM_UPDATE_SCHEMA, output=VM_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from dynamips_manager.update_vm_settings(vm, request.json) + await dynamips_manager.update_vm_settings(vm, request.json) vm.updated() response.json(vm) @@ -136,11 +137,11 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Delete a Dynamips VM instance") - def delete(request, response): + async def delete(request, response): # check the project_id exists ProjectManager.instance().get_project(request.match_info["project_id"]) - yield from Dynamips.instance().delete_node(request.match_info["node_id"]) + await Dynamips.instance().delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -155,15 +156,15 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Start a Dynamips VM instance") - def start(request, response): + async def start(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) try: - yield from dynamips_manager.ghost_ios_support(vm) + await dynamips_manager.ghost_ios_support(vm) except GeneratorExit: pass - yield from vm.start() + await vm.start() response.set_status(204) @Route.post( @@ -178,11 +179,11 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Stop a Dynamips VM instance") - def stop(request, response): + async def stop(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.stop() + await vm.stop() response.set_status(204) @Route.post( @@ -197,11 +198,11 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Suspend a Dynamips VM instance") - def suspend(request, response): + async def suspend(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.suspend() + await vm.suspend() response.set_status(204) @Route.post( @@ -216,11 +217,11 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Resume a suspended Dynamips VM instance") - def resume(request, response): + async def resume(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.resume() + await vm.resume() response.set_status(204) @Route.post( @@ -235,11 +236,11 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Reload a Dynamips VM instance") - def reload(request, response): + async def reload(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.reload() + await vm.reload() response.set_status(204) @Route.post( @@ -258,14 +259,14 @@ class DynamipsVMHandler: description="Add a NIO to a Dynamips VM instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = yield from dynamips_manager.create_nio(vm, request.json) + nio = await dynamips_manager.create_nio(vm, request.json) slot_number = int(request.match_info["adapter_number"]) port_number = int(request.match_info["port_number"]) - yield from vm.slot_add_nio_binding(slot_number, port_number, nio) + await vm.slot_add_nio_binding(slot_number, port_number, nio) response.set_status(201) response.json(nio) @@ -284,17 +285,17 @@ class DynamipsVMHandler: }, input=NIO_SCHEMA, output=NIO_SCHEMA, - description="Update a NIO from a Dynamips instance") - def update_nio(request, response): + description="Update a NIO on a Dynamips instance") + async def update_nio(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) slot_number = int(request.match_info["adapter_number"]) port_number = int(request.match_info["port_number"]) - nio = vm.slots[slot_number].get_nio(port_number) - if "filters" in request.json and nio: + nio = vm.get_nio(slot_number, port_number) + if "filters" in request.json: nio.filters = request.json["filters"] - yield from vm.slot_update_nio_binding(slot_number, port_number, nio) + await vm.slot_update_nio_binding(slot_number, port_number, nio) response.set_status(201) response.json(request.json) @@ -312,14 +313,14 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a Dynamips VM instance") - def delete_nio(request, response): + async def delete_nio(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) slot_number = int(request.match_info["adapter_number"]) port_number = int(request.match_info["port_number"]) - nio = yield from vm.slot_remove_nio_binding(slot_number, port_number) - yield from nio.delete() + nio = await vm.slot_remove_nio_binding(slot_number, port_number) + await nio.delete() response.set_status(204) @Route.post( @@ -337,7 +338,7 @@ class DynamipsVMHandler: }, description="Start a packet capture on a Dynamips VM instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -352,7 +353,7 @@ class DynamipsVMHandler: except UnicodeEncodeError: raise DynamipsError('The capture file path "{}" must only contain ASCII (English) characters'.format(pcap_file_path)) - yield from vm.start_capture(slot_number, port_number, pcap_file_path, request.json["data_link_type"]) + await vm.start_capture(slot_number, port_number, pcap_file_path, request.json["data_link_type"]) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -369,15 +370,38 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Stop a packet capture on a Dynamips VM instance") - def stop_capture(request, response): + async def stop_capture(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) slot_number = int(request.match_info["adapter_number"]) port_number = int(request.match_info["port_number"]) - yield from vm.stop_capture(slot_number, port_number) + await vm.stop_capture(slot_number, port_number) response.set_status(204) + @Route.get( + r"/projects/{project_id}/dynamips/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture", + "port_number": "Port on the adapter (always 0)" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + dynamips_manager = Dynamips.instance() + vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + slot_number = int(request.match_info["adapter_number"]) + port_number = int(request.match_info["port_number"]) + nio = vm.get_nio(slot_number, port_number) + await dynamips_manager.stream_pcap_file(nio, vm.project.id, request, response) + @Route.get( r"/projects/{project_id}/dynamips/nodes/{node_id}/idlepc_proposals", parameters={ @@ -390,12 +414,12 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Retrieve the idlepc proposals") - def get_idlepcs(request, response): + async def get_idlepcs(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.set_idlepc("0x0") - idlepcs = yield from vm.get_idle_pc_prop() + await vm.set_idlepc("0x0") + idlepcs = await vm.get_idle_pc_prop() response.set_status(200) response.json(idlepcs) @@ -411,11 +435,11 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Retrieve the idlepc proposals") - def get_auto_idlepc(request, response): + async def get_auto_idlepc(request, response): dynamips_manager = Dynamips.instance() vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - idlepc = yield from dynamips_manager.auto_idlepc(vm) + idlepc = await dynamips_manager.auto_idlepc(vm) response.set_status(200) response.json({"idlepc": idlepc}) @@ -426,10 +450,10 @@ class DynamipsVMHandler: }, description="Retrieve the list of Dynamips IOS images", output=NODE_LIST_IMAGES_SCHEMA) - def list_images(request, response): + async def list_images(request, response): dynamips_manager = Dynamips.instance() - images = yield from dynamips_manager.list_images() + images = await dynamips_manager.list_images() response.set_status(200) response.json(images) @@ -443,10 +467,10 @@ class DynamipsVMHandler: }, raw=True, description="Upload a Dynamips IOS image") - def upload_image(request, response): + async def upload_image(request, response): dynamips_manager = Dynamips.instance() - yield from dynamips_manager.write_image(request.match_info["filename"], request.content) + await dynamips_manager.write_image(request.match_info["filename"], request.content) response.set_status(204) @Route.get( @@ -459,7 +483,7 @@ class DynamipsVMHandler: }, raw=True, description="Download a Dynamips IOS image") - def download_image(request, response): + async def download_image(request, response): filename = request.match_info["filename"] dynamips_manager = Dynamips.instance() @@ -469,7 +493,7 @@ class DynamipsVMHandler: if filename[0] == ".": raise aiohttp.web.HTTPForbidden() - yield from response.file(image_path) + await response.stream_file(image_path) @Route.post( r"/projects/{project_id}/dynamips/nodes/{node_id}/duplicate", @@ -482,12 +506,10 @@ class DynamipsVMHandler: 404: "Instance doesn't exist" }, description="Duplicate a dynamips instance") - def duplicate(request, response): + async def duplicate(request, response): - new_node = yield from Dynamips.instance().duplicate_node( - request.match_info["node_id"], - request.json["destination_node_id"] - ) + new_node = await Dynamips.instance().duplicate_node(request.match_info["node_id"], + request.json["destination_node_id"]) response.set_status(201) response.json(new_node) diff --git a/gns3server/handlers/api/compute/ethernet_hub_handler.py b/gns3server/handlers/api/compute/ethernet_hub_handler.py index 77369567..fedf3418 100644 --- a/gns3server/handlers/api/compute/ethernet_hub_handler.py +++ b/gns3server/handlers/api/compute/ethernet_hub_handler.py @@ -48,11 +48,11 @@ class EthernetHubHandler: description="Create a new Ethernet hub instance", input=ETHERNET_HUB_CREATE_SCHEMA, output=ETHERNET_HUB_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): # Use the Dynamips Ethernet hub to simulate this node dynamips_manager = Dynamips.instance() - node = yield from dynamips_manager.create_node(request.json.pop("name"), + node = await dynamips_manager.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), node_type="ethernet_hub", @@ -92,12 +92,10 @@ class EthernetHubHandler: 404: "Instance doesn't exist" }, description="Duplicate an ethernet hub instance") - def duplicate(request, response): + async def duplicate(request, response): - new_node = yield from Dynamips.instance().duplicate_node( - request.match_info["node_id"], - request.json["destination_node_id"] - ) + new_node = await Dynamips.instance().duplicate_node(request.match_info["node_id"], + request.json["destination_node_id"]) response.set_status(201) response.json(new_node) @@ -116,12 +114,12 @@ class EthernetHubHandler: description="Update an Ethernet hub instance", input=ETHERNET_HUB_UPDATE_SCHEMA, output=ETHERNET_HUB_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) if "name" in request.json and node.name != request.json["name"]: - yield from node.set_name(request.json["name"]) + await node.set_name(request.json["name"]) if "ports_mapping" in request.json: node.ports_mapping = request.json["ports_mapping"] @@ -140,10 +138,10 @@ class EthernetHubHandler: 404: "Instance doesn't exist" }, description="Delete an Ethernet hub instance") - def delete(request, response): + async def delete(request, response): dynamips_manager = Dynamips.instance() - yield from dynamips_manager.delete_node(request.match_info["node_id"]) + await dynamips_manager.delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -213,13 +211,13 @@ class EthernetHubHandler: description="Add a NIO to an Ethernet hub instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = yield from dynamips_manager.create_nio(node, request.json) + nio = await dynamips_manager.create_nio(node, request.json) port_number = int(request.match_info["port_number"]) - yield from node.add_nio(nio, port_number) + await node.add_nio(nio, port_number) response.set_status(201) response.json(nio) @@ -238,13 +236,13 @@ class EthernetHubHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from an Ethernet hub instance") - def delete_nio(request, response): + async def delete_nio(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - nio = yield from node.remove_nio(port_number) - yield from nio.delete() + nio = await node.remove_nio(port_number) + await nio.delete() response.set_status(204) @Route.post( @@ -262,13 +260,13 @@ class EthernetHubHandler: }, description="Start a packet capture on an Ethernet hub instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) pcap_file_path = os.path.join(node.project.capture_working_directory(), request.json["capture_file_name"]) - yield from node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) + await node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -285,10 +283,32 @@ class EthernetHubHandler: 404: "Instance doesn't exist" }, description="Stop a packet capture on an Ethernet hub instance") - def stop_capture(request, response): + async def stop_capture(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - yield from node.stop_capture(port_number) + await node.stop_capture(port_number) response.set_status(204) + + @Route.get( + r"/projects/{project_id}/ethernet_hub/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture (always 0)", + "port_number": "Port on the hub" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + dynamips_manager = Dynamips.instance() + node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + nio = node.get_nio(port_number) + await dynamips_manager.stream_pcap_file(nio, node.project.id, request, response) diff --git a/gns3server/handlers/api/compute/ethernet_switch_handler.py b/gns3server/handlers/api/compute/ethernet_switch_handler.py index cfde2bfa..b75511f6 100644 --- a/gns3server/handlers/api/compute/ethernet_switch_handler.py +++ b/gns3server/handlers/api/compute/ethernet_switch_handler.py @@ -48,19 +48,21 @@ class EthernetSwitchHandler: description="Create a new Ethernet switch instance", input=ETHERNET_SWITCH_CREATE_SCHEMA, output=ETHERNET_SWITCH_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): # Use the Dynamips Ethernet switch to simulate this node dynamips_manager = Dynamips.instance() - node = yield from dynamips_manager.create_node(request.json.pop("name"), + node = await dynamips_manager.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), + console=request.json.get("console"), + console_type=request.json.get("console_type"), node_type="ethernet_switch", ports=request.json.get("ports_mapping")) # On Linux, use the generic switch # builtin_manager = Builtin.instance() - # node = yield from builtin_manager.create_node(request.json.pop("name"), + # node = await builtin_manager.create_node(request.json.pop("name"), # request.match_info["project_id"], # request.json.get("node_id"), # node_type="ethernet_switch") @@ -101,12 +103,10 @@ class EthernetSwitchHandler: 404: "Instance doesn't exist" }, description="Duplicate an ethernet switch instance") - def duplicate(request, response): + async def duplicate(request, response): - new_node = yield from Dynamips.instance().duplicate_node( - request.match_info["node_id"], - request.json["destination_node_id"] - ) + new_node = await Dynamips.instance().duplicate_node(request.match_info["node_id"], + request.json["destination_node_id"]) response.set_status(201) response.json(new_node) @@ -125,15 +125,17 @@ class EthernetSwitchHandler: description="Update an Ethernet switch instance", input=ETHERNET_SWITCH_UPDATE_SCHEMA, output=ETHERNET_SWITCH_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) if "name" in request.json and node.name != request.json["name"]: - yield from node.set_name(request.json["name"]) + await node.set_name(request.json["name"]) if "ports_mapping" in request.json: node.ports_mapping = request.json["ports_mapping"] - yield from node.update_port_settings() + await node.update_port_settings() + if "console_type" in request.json: + node.console_type = request.json["console_type"] # builtin_manager = Builtin.instance() # node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -153,10 +155,10 @@ class EthernetSwitchHandler: 404: "Instance doesn't exist" }, description="Delete an Ethernet switch instance") - def delete(request, response): + async def delete(request, response): dynamips_manager = Dynamips.instance() - yield from dynamips_manager.delete_node(request.match_info["node_id"]) + await dynamips_manager.delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -226,17 +228,17 @@ class EthernetSwitchHandler: description="Add a NIO to an Ethernet switch instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = yield from dynamips_manager.create_nio(node, request.json) + nio = await dynamips_manager.create_nio(node, request.json) port_number = int(request.match_info["port_number"]) - yield from node.add_nio(nio, port_number) + await node.add_nio(nio, port_number) #builtin_manager = Builtin.instance() #node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - #nio = yield from builtin_manager.create_nio(request.json["nio"]) + #nio = await builtin_manager.create_nio(request.json["nio"]) response.set_status(201) response.json(nio) @@ -255,15 +257,15 @@ class EthernetSwitchHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from an Ethernet switch instance") - def delete_nio(request, response): + async def delete_nio(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) #builtin_manager = Builtin.instance() #node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - nio = yield from node.remove_nio(port_number) - yield from nio.delete() + nio = await node.remove_nio(port_number) + await nio.delete() response.set_status(204) @Route.post( @@ -281,7 +283,7 @@ class EthernetSwitchHandler: }, description="Start a packet capture on an Ethernet switch instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -289,7 +291,7 @@ class EthernetSwitchHandler: #node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) pcap_file_path = os.path.join(node.project.capture_working_directory(), request.json["capture_file_name"]) - yield from node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) + await node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -306,12 +308,34 @@ class EthernetSwitchHandler: 404: "Instance doesn't exist" }, description="Stop a packet capture on an Ethernet switch instance") - def stop_capture(request, response): + async def stop_capture(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) #builtin_manager = Builtin.instance() #node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - yield from node.stop_capture(port_number) + await node.stop_capture(port_number) response.set_status(204) + + @Route.get( + r"/projects/{project_id}/ethernet_switch/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture (always 0)", + "port_number": "Port on the switch" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + dynamips_manager = Dynamips.instance() + node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + nio = node.get_nio(port_number) + await dynamips_manager.stream_pcap_file(nio, node.project.id, request, response) diff --git a/gns3server/handlers/api/compute/frame_relay_switch_handler.py b/gns3server/handlers/api/compute/frame_relay_switch_handler.py index fac4ebc5..2ea82c88 100644 --- a/gns3server/handlers/api/compute/frame_relay_switch_handler.py +++ b/gns3server/handlers/api/compute/frame_relay_switch_handler.py @@ -48,11 +48,11 @@ class FrameRelaySwitchHandler: description="Create a new Frame Relay switch instance", input=FRAME_RELAY_SWITCH_CREATE_SCHEMA, output=FRAME_RELAY_SWITCH_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): # Use the Dynamips Frame Relay switch to simulate this node dynamips_manager = Dynamips.instance() - node = yield from dynamips_manager.create_node(request.json.pop("name"), + node = await dynamips_manager.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), node_type="frame_relay_switch", @@ -90,9 +90,9 @@ class FrameRelaySwitchHandler: 404: "Instance doesn't exist" }, description="Duplicate a frame relay switch instance") - def duplicate(request, response): + async def duplicate(request, response): - new_node = yield from Dynamips.instance().duplicate_node( + new_node = await Dynamips.instance().duplicate_node( request.match_info["node_id"], request.json["destination_node_id"] ) @@ -114,12 +114,12 @@ class FrameRelaySwitchHandler: description="Update a Frame Relay switch instance", input=FRAME_RELAY_SWITCH_UPDATE_SCHEMA, output=FRAME_RELAY_SWITCH_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) if "name" in request.json and node.name != request.json["name"]: - yield from node.set_name(request.json["name"]) + await node.set_name(request.json["name"]) if "mappings" in request.json: node.mappings = request.json["mappings"] node.updated() @@ -137,10 +137,10 @@ class FrameRelaySwitchHandler: 404: "Instance doesn't exist" }, description="Delete a Frame Relay switch instance") - def delete(request, response): + async def delete(request, response): dynamips_manager = Dynamips.instance() - yield from dynamips_manager.delete_node(request.match_info["node_id"]) + await dynamips_manager.delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -210,13 +210,13 @@ class FrameRelaySwitchHandler: description="Add a NIO to a Frame Relay switch instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = yield from dynamips_manager.create_nio(node, request.json) + nio = await dynamips_manager.create_nio(node, request.json) port_number = int(request.match_info["port_number"]) - yield from node.add_nio(nio, port_number) + await node.add_nio(nio, port_number) response.set_status(201) response.json(nio) @@ -234,13 +234,13 @@ class FrameRelaySwitchHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a Frame Relay switch instance") - def delete_nio(request, response): + async def delete_nio(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - nio = yield from node.remove_nio(port_number) - yield from nio.delete() + nio = await node.remove_nio(port_number) + await nio.delete() response.set_status(204) @Route.post( @@ -258,13 +258,13 @@ class FrameRelaySwitchHandler: }, description="Start a packet capture on a Frame Relay switch instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) pcap_file_path = os.path.join(node.project.capture_working_directory(), request.json["capture_file_name"]) - yield from node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) + await node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -281,10 +281,32 @@ class FrameRelaySwitchHandler: 404: "Instance doesn't exist" }, description="Stop a packet capture on a Frame Relay switch instance") - def stop_capture(request, response): + async def stop_capture(request, response): dynamips_manager = Dynamips.instance() node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - yield from node.stop_capture(port_number) + await node.stop_capture(port_number) response.set_status(204) + + @Route.get( + r"/projects/{project_id}/frame_relay_switch/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture (always 0)", + "port_number": "Port on the switch" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + dynamips_manager = Dynamips.instance() + node = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + nio = node.get_nio(port_number) + await dynamips_manager.stream_pcap_file(nio, node.project.id, request, response) diff --git a/gns3server/handlers/api/compute/iou_handler.py b/gns3server/handlers/api/compute/iou_handler.py index ae661c36..43b1c07f 100644 --- a/gns3server/handlers/api/compute/iou_handler.py +++ b/gns3server/handlers/api/compute/iou_handler.py @@ -54,14 +54,15 @@ class IOUHandler: description="Create a new IOU instance", input=IOU_CREATE_SCHEMA, output=IOU_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): iou = IOU.instance() - vm = yield from iou.create_node(request.json.pop("name"), + vm = await iou.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), path=request.json.get("path"), - console=request.json.get("console")) + console=request.json.get("console"), + console_type=request.json.get("console_type", "telnet")) for name, value in request.json.items(): if hasattr(vm, name) and getattr(vm, name) != value: @@ -111,7 +112,7 @@ class IOUHandler: description="Update an IOU instance", input=IOU_OBJECT_SCHEMA, output=IOU_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -125,7 +126,7 @@ class IOUHandler: if vm.use_default_iou_values: # update the default IOU values in case the image or use_default_iou_values have changed # this is important to have the correct NVRAM amount in order to correctly push the configs to the NVRAM - yield from vm.update_default_iou_values() + await vm.update_default_iou_values() vm.updated() response.json(vm) @@ -141,9 +142,9 @@ class IOUHandler: 404: "Instance doesn't exist" }, description="Delete an IOU instance") - def delete(request, response): + async def delete(request, response): - yield from IOU.instance().delete_node(request.match_info["node_id"]) + await IOU.instance().delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -157,9 +158,9 @@ class IOUHandler: 404: "Instance doesn't exist" }, description="Duplicate a IOU instance") - def duplicate(request, response): + async def duplicate(request, response): - new_node = yield from IOU.instance().duplicate_node( + new_node = await IOU.instance().duplicate_node( request.match_info["node_id"], request.json["destination_node_id"] ) @@ -180,7 +181,7 @@ class IOUHandler: input=IOU_START_SCHEMA, output=IOU_OBJECT_SCHEMA, description="Start an IOU instance") - def start(request, response): + async def start(request, response): iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -189,7 +190,7 @@ class IOUHandler: if hasattr(vm, name) and getattr(vm, name) != value: setattr(vm, name, value) - yield from vm.start() + await vm.start() response.json(vm) @Route.post( @@ -204,11 +205,11 @@ class IOUHandler: 404: "Instance doesn't exist" }, description="Stop an IOU instance") - def stop(request, response): + async def stop(request, response): iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.stop() + await vm.stop() response.set_status(204) @Route.post( @@ -241,11 +242,11 @@ class IOUHandler: 404: "Instance doesn't exist" }, description="Reload an IOU instance") - def reload(request, response): + async def reload(request, response): iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.reload() + await vm.reload() response.set_status(204) @Route.post( @@ -264,7 +265,7 @@ class IOUHandler: description="Add a NIO to a IOU instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -272,7 +273,7 @@ class IOUHandler: if nio_type not in ("nio_udp", "nio_tap", "nio_ethernet", "nio_generic_ethernet"): raise aiohttp.web.HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) nio = iou_manager.create_nio(request.json) - yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), int(request.match_info["port_number"]), nio) + await vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), int(request.match_info["port_number"]), nio) response.set_status(201) response.json(nio) @@ -289,24 +290,21 @@ class IOUHandler: 400: "Invalid request", 404: "Instance doesn't exist" }, - description="Update a NIO from a IOU instance", + description="Update a NIO on an IOU instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def update_nio(request, response): + async def update_nio(request, response): iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) port_number = int(request.match_info["port_number"]) - nio = vm.adapters[adapter_number].get_nio(port_number) - if "filters" in request.json and nio: + nio = vm.get_nio(adapter_number, port_number) + if "filters" in request.json: nio.filters = request.json["filters"] - yield from vm.adapter_update_nio_binding( - adapter_number, - port_number, - nio) + await vm.adapter_update_nio_binding(adapter_number, port_number, nio) response.set_status(201) - response.json(nio) + response.json(request.json) @Route.delete( r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", @@ -322,11 +320,11 @@ class IOUHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a IOU instance") - def delete_nio(request, response): + async def delete_nio(request, response): iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]), int(request.match_info["port_number"])) + await vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]), int(request.match_info["port_number"])) response.set_status(204) @Route.post( @@ -345,14 +343,14 @@ class IOUHandler: }, description="Start a packet capture on an IOU VM instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) port_number = int(request.match_info["port_number"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) - yield from vm.start_capture(adapter_number, port_number, pcap_file_path, request.json["data_link_type"]) + await vm.start_capture(adapter_number, port_number, pcap_file_path, request.json["data_link_type"]) response.json({"pcap_file_path": str(pcap_file_path)}) @Route.post( @@ -370,16 +368,38 @@ class IOUHandler: 409: "VM not started" }, description="Stop a packet capture on an IOU VM instance") - def stop_capture(request, response): + async def stop_capture(request, response): iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - adapter_number = int(request.match_info["adapter_number"]) port_number = int(request.match_info["port_number"]) - yield from vm.stop_capture(adapter_number, port_number) + await vm.stop_capture(adapter_number, port_number) response.set_status(204) + @Route.get( + r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture", + "port_number": "Port on the adapter (always 0)" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + iou_manager = IOU.instance() + vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + adapter_number = int(request.match_info["adapter_number"]) + port_number = int(request.match_info["port_number"]) + nio = vm.get_nio(adapter_number, port_number) + await iou_manager.stream_pcap_file(nio, vm.project.id, request, response) + @Route.get( r"/iou/images", status_codes={ @@ -387,10 +407,10 @@ class IOUHandler: }, description="Retrieve the list of IOU images", output=NODE_LIST_IMAGES_SCHEMA) - def list_iou_images(request, response): + async def list_iou_images(request, response): iou_manager = IOU.instance() - images = yield from iou_manager.list_images() + images = await iou_manager.list_images() response.set_status(200) response.json(images) @@ -404,10 +424,10 @@ class IOUHandler: }, raw=True, description="Upload an IOU image") - def upload_image(request, response): + async def upload_image(request, response): iou_manager = IOU.instance() - yield from iou_manager.write_image(request.match_info["filename"], request.content) + await iou_manager.write_image(request.match_info["filename"], request.content) response.set_status(204) @@ -421,7 +441,7 @@ class IOUHandler: }, raw=True, description="Download an IOU image") - def download_image(request, response): + async def download_image(request, response): filename = request.match_info["filename"] iou_manager = IOU.instance() @@ -431,4 +451,4 @@ class IOUHandler: if filename[0] == ".": raise aiohttp.web.HTTPForbidden() - yield from response.file(image_path) + await response.stream_file(image_path) diff --git a/gns3server/handlers/api/compute/nat_handler.py b/gns3server/handlers/api/compute/nat_handler.py index 21487c1d..ae13c87e 100644 --- a/gns3server/handlers/api/compute/nat_handler.py +++ b/gns3server/handlers/api/compute/nat_handler.py @@ -21,6 +21,7 @@ from gns3server.web.route import Route from gns3server.schemas.node import NODE_CAPTURE_SCHEMA from gns3server.schemas.nio import NIO_SCHEMA from gns3server.compute.builtin import Builtin +from aiohttp.web import HTTPConflict from gns3server.schemas.nat import ( NAT_CREATE_SCHEMA, @@ -48,10 +49,10 @@ class NatHandler: description="Create a new nat instance", input=NAT_CREATE_SCHEMA, output=NAT_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): builtin_manager = Builtin.instance() - node = yield from builtin_manager.create_node(request.json.pop("name"), + node = await builtin_manager.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), node_type="nat", @@ -115,10 +116,10 @@ class NatHandler: 404: "Instance doesn't exist" }, description="Delete a nat instance") - def delete(request, response): + async def delete(request, response): builtin_manager = Builtin.instance() - yield from builtin_manager.delete_node(request.match_info["node_id"]) + await builtin_manager.delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -188,13 +189,13 @@ class NatHandler: description="Add a NIO to a nat instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) nio = builtin_manager.create_nio(request.json) port_number = int(request.match_info["port_number"]) - yield from node.add_nio(nio, port_number) + await node.add_nio(nio, port_number) response.set_status(201) response.json(nio) @@ -213,15 +214,16 @@ class NatHandler: }, input=NIO_SCHEMA, output=NIO_SCHEMA, - description="Update a NIO from a NAT instance") - def update_nio(request, response): + description="Update a NIO on a NAT instance") + async def update_nio(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = node.nios[int(request.match_info["adapter_number"])] - if "filters" in request.json and nio: + port_number = int(request.match_info["port_number"]) + nio = node.get_nio(port_number) + if "filters" in request.json: nio.filters = request.json["filters"] - yield from node.update_nio(int(request.match_info["port_number"]), nio) + await node.update_nio(port_number, nio) response.set_status(201) response.json(request.json) @@ -239,12 +241,12 @@ class NatHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a nat instance") - def delete_nio(request, response): + async def delete_nio(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - yield from node.remove_nio(port_number) + await node.remove_nio(port_number) response.set_status(204) @Route.post( @@ -262,13 +264,13 @@ class NatHandler: }, description="Start a packet capture on a nat instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) pcap_file_path = os.path.join(node.project.capture_working_directory(), request.json["capture_file_name"]) - yield from node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) + await node.start_capture(port_number, pcap_file_path, request.json["data_link_type"]) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -285,10 +287,32 @@ class NatHandler: 404: "Instance doesn't exist" }, description="Stop a packet capture on a nat instance") - def stop_capture(request, response): + async def stop_capture(request, response): builtin_manager = Builtin.instance() node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - yield from node.stop_capture(port_number) + await node.stop_capture(port_number) response.set_status(204) + + @Route.get( + r"/projects/{project_id}/nat/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture (always 0)", + "port_number": "Port on the nat" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + builtin_manager = Builtin.instance() + node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + nio = node.get_nio(port_number) + await builtin_manager.stream_pcap_file(nio, node.project.id, request, response) diff --git a/gns3server/handlers/api/compute/network_handler.py b/gns3server/handlers/api/compute/network_handler.py index dc2de232..d99cc212 100644 --- a/gns3server/handlers/api/compute/network_handler.py +++ b/gns3server/handlers/api/compute/network_handler.py @@ -49,3 +49,11 @@ class NetworkHandler: network_interfaces = interfaces() response.json(network_interfaces) + + @Route.get( + r"/network/ports", + description="List all the ports used by the server") + def network_ports(request, response): + + m = PortManager.instance() + response.json(m) diff --git a/gns3server/handlers/api/compute/notification_handler.py b/gns3server/handlers/api/compute/notification_handler.py index 3580a286..194d1fe5 100644 --- a/gns3server/handlers/api/compute/notification_handler.py +++ b/gns3server/handlers/api/compute/notification_handler.py @@ -21,14 +21,16 @@ from aiohttp.web import WebSocketResponse from gns3server.web.route import Route from gns3server.compute.notification_manager import NotificationManager +import logging +log = logging.getLogger(__name__) -@asyncio.coroutine -def process_websocket(ws): + +async def process_websocket(ws): """ Process ping / pong and close message """ try: - yield from ws.receive() + await ws.receive() except aiohttp.WSServerHandshakeError: pass @@ -38,20 +40,25 @@ class NotificationHandler: @Route.get( r"/notifications/ws", description="Send notifications using Websockets") - def notifications(request, response): + async def notifications(request, response): notifications = NotificationManager.instance() ws = WebSocketResponse() - yield from ws.prepare(request) + await ws.prepare(request) - asyncio.async(process_websocket(ws)) + request.app['websockets'].add(ws) + asyncio.ensure_future(process_websocket(ws)) + log.info("New client has connected to compute WebSocket") + try: + with notifications.queue() as queue: + while True: + notification = await queue.get_json(1) + if ws.closed: + break + await ws.send_str(notification) + finally: + log.info("Client has disconnected from compute WebSocket") + if not ws.closed: + await ws.close() + request.app['websockets'].discard(ws) - with notifications.queue() as queue: - while True: - try: - notification = yield from queue.get_json(1) - except asyncio.futures.CancelledError: - break - if ws.closed: - break - ws.send_str(notification) return ws diff --git a/gns3server/handlers/api/compute/project_handler.py b/gns3server/handlers/api/compute/project_handler.py index a7d8f760..e59d9ab5 100644 --- a/gns3server/handlers/api/compute/project_handler.py +++ b/gns3server/handlers/api/compute/project_handler.py @@ -37,6 +37,8 @@ from gns3server.schemas.project import ( import logging log = logging.getLogger() +CHUNK_SIZE = 1024 * 8 # 8KB + class ProjectHandler: @@ -73,11 +75,31 @@ class ProjectHandler: p = pm.create_project( name=request.json.get("name"), path=request.json.get("path"), - project_id=request.json.get("project_id") + project_id=request.json.get("project_id"), + variables=request.json.get("variables", None) ) response.set_status(201) response.json(p) + @Route.put( + r"/projects/{project_id}", + description="Update the project on the server", + status_codes={ + 201: "Project updated", + 403: "Forbidden to update a project" + }, + output=PROJECT_OBJECT_SCHEMA, + input=PROJECT_UPDATE_SCHEMA) + async def update_project(request, response): + + pm = ProjectManager.instance() + project = pm.get_project(request.match_info["project_id"]) + await project.update( + variables=request.json.get("variables", None) + ) + response.set_status(200) + response.json(project) + @Route.get( r"/projects/{project_id}", description="Get project information", @@ -105,12 +127,12 @@ class ProjectHandler: 204: "Project closed", 404: "The project doesn't exist" }) - def close(request, response): + async def close(request, response): pm = ProjectManager.instance() project = pm.get_project(request.match_info["project_id"]) if ProjectHandler._notifications_listening.setdefault(project.id, 0) <= 1: - yield from project.close() + await project.close() pm.remove_project(project.id) try: del ProjectHandler._notifications_listening[project.id] @@ -130,11 +152,11 @@ class ProjectHandler: 204: "Changes have been written on disk", 404: "The project doesn't exist" }) - def delete(request, response): + async def delete(request, response): pm = ProjectManager.instance() project = pm.get_project(request.match_info["project_id"]) - yield from project.delete() + await project.delete() pm.remove_project(project.id) response.set_status(204) @@ -148,7 +170,7 @@ class ProjectHandler: 200: "End of stream", 404: "The project doesn't exist" }) - def notification(request, response): + async def notification(request, response): pm = ProjectManager.instance() project = pm.get_project(request.match_info["project_id"]) @@ -161,20 +183,18 @@ class ProjectHandler: queue = project.get_listen_queue() ProjectHandler._notifications_listening.setdefault(project.id, 0) ProjectHandler._notifications_listening[project.id] += 1 - response.write("{}\n".format(json.dumps(ProjectHandler._getPingMessage())).encode("utf-8")) + await response.write("{}\n".format(json.dumps(ProjectHandler._getPingMessage())).encode("utf-8")) while True: try: - (action, msg) = yield from asyncio.wait_for(queue.get(), 5) + (action, msg) = await asyncio.wait_for(queue.get(), 5) if hasattr(msg, "__json__"): msg = json.dumps({"action": action, "event": msg.__json__()}, sort_keys=True) else: msg = json.dumps({"action": action, "event": msg}, sort_keys=True) log.debug("Send notification: %s", msg) - response.write(("{}\n".format(msg)).encode("utf-8")) - except asyncio.futures.CancelledError as e: - break + await response.write(("{}\n".format(msg)).encode("utf-8")) except asyncio.futures.TimeoutError: - response.write("{}\n".format(json.dumps(ProjectHandler._getPingMessage())).encode("utf-8")) + await response.write("{}\n".format(json.dumps(ProjectHandler._getPingMessage())).encode("utf-8")) project.stop_listen_queue(queue) if project.id in ProjectHandler._notifications_listening: ProjectHandler._notifications_listening[project.id] -= 1 @@ -199,11 +219,11 @@ class ProjectHandler: 404: "The project doesn't exist" }, output=PROJECT_FILE_LIST_SCHEMA) - def list_files(request, response): + async def list_files(request, response): pm = ProjectManager.instance() project = pm.get_project(request.match_info["project_id"]) - files = yield from project.list_files() + files = await project.list_files() response.json(files) response.set_status(200) @@ -218,7 +238,7 @@ class ProjectHandler: 403: "Permission denied", 404: "The file doesn't exist" }) - def get_file(request, response): + async def get_file(request, response): pm = ProjectManager.instance() project = pm.get_project(request.match_info["project_id"]) @@ -230,64 +250,7 @@ class ProjectHandler: raise aiohttp.web.HTTPForbidden() path = os.path.join(project.path, path) - response.content_type = "application/octet-stream" - response.set_status(200) - response.enable_chunked_encoding() - - try: - with open(path, "rb") as f: - yield from response.prepare(request) - while True: - data = f.read(4096) - if not data: - break - yield from response.write(data) - - except FileNotFoundError: - raise aiohttp.web.HTTPNotFound() - except PermissionError: - raise aiohttp.web.HTTPForbidden() - - @Route.get( - r"/projects/{project_id}/stream/{path:.+}", - description="Stream a file from a project", - parameters={ - "project_id": "Project UUID", - }, - status_codes={ - 200: "File returned", - 403: "Permission denied", - 404: "The file doesn't exist" - }) - def stream_file(request, response): - - pm = ProjectManager.instance() - project = pm.get_project(request.match_info["project_id"]) - path = request.match_info["path"] - path = os.path.normpath(path) - - # Raise an error if user try to escape - if path[0] == ".": - raise aiohttp.web.HTTPForbidden() - path = os.path.join(project.path, path) - - response.content_type = "application/octet-stream" - response.set_status(200) - response.enable_chunked_encoding() - - try: - with open(path, "rb") as f: - yield from response.prepare(request) - while True: - data = f.read(4096) - if not data: - yield from asyncio.sleep(0.1) - yield from response.write(data) - - except FileNotFoundError: - raise aiohttp.web.HTTPNotFound() - except PermissionError: - raise aiohttp.web.HTTPForbidden() + await response.stream_file(path) @Route.post( r"/projects/{project_id}/files/{path:.+}", @@ -301,7 +264,7 @@ class ProjectHandler: 403: "Permission denied", 404: "The path doesn't exist" }) - def write_file(request, response): + async def write_file(request, response): pm = ProjectManager.instance() project = pm.get_project(request.match_info["project_id"]) @@ -319,74 +282,15 @@ class ProjectHandler: os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, 'wb+') as f: while True: - packet = yield from request.content.read(512) - if not packet: + try: + chunk = await request.content.read(CHUNK_SIZE) + except asyncio.TimeoutError: + raise aiohttp.web.HTTPRequestTimeout(text="Timeout when writing to file '{}'".format(path)) + if not chunk: break - f.write(packet) + f.write(chunk) except FileNotFoundError: raise aiohttp.web.HTTPNotFound() except PermissionError: raise aiohttp.web.HTTPForbidden() - - @Route.get( - r"/projects/{project_id}/export", - description="Export a project as a portable archive", - parameters={ - "project_id": "Project UUID", - }, - raw=True, - status_codes={ - 200: "File returned", - 404: "The project doesn't exist" - }) - def export_project(request, response): - - pm = ProjectManager.instance() - project = pm.get_project(request.match_info["project_id"]) - response.content_type = 'application/gns3project' - response.headers['CONTENT-DISPOSITION'] = 'attachment; filename="{}.gns3project"'.format(project.name) - response.enable_chunked_encoding() - yield from response.prepare(request) - - include_images = bool(int(request.json.get("include_images", "0"))) - for data in project.export(include_images=include_images): - response.write(data) - yield from response.drain() - - yield from response.write_eof() - - @Route.post( - r"/projects/{project_id}/import", - description="Import a project from a portable archive", - parameters={ - "project_id": "Project UUID", - }, - raw=True, - output=PROJECT_OBJECT_SCHEMA, - status_codes={ - 200: "Project imported", - 403: "Forbidden to import project" - }) - def import_project(request, response): - - pm = ProjectManager.instance() - project_id = request.match_info["project_id"] - project = pm.create_project(project_id=project_id) - - # We write the content to a temporary location and after we extract it all. - # It could be more optimal to stream this but it is not implemented in Python. - # Spooled means the file is temporary kept in memory until max_size is reached - try: - with tempfile.SpooledTemporaryFile(max_size=10000) as temp: - while True: - packet = yield from request.content.read(512) - if not packet: - break - temp.write(packet) - project.import_zip(temp, gns3vm=bool(int(request.GET.get("gns3vm", "1")))) - except OSError as e: - raise aiohttp.web.HTTPInternalServerError(text="Could not import the project: {}".format(e)) - - response.json(project) - response.set_status(201) diff --git a/gns3server/handlers/api/compute/qemu_handler.py b/gns3server/handlers/api/compute/qemu_handler.py index 129ac0d9..30453f6e 100644 --- a/gns3server/handlers/api/compute/qemu_handler.py +++ b/gns3server/handlers/api/compute/qemu_handler.py @@ -35,10 +35,12 @@ from gns3server.schemas.qemu import ( QEMU_CREATE_SCHEMA, QEMU_UPDATE_SCHEMA, QEMU_OBJECT_SCHEMA, + QEMU_RESIZE_SCHEMA, QEMU_BINARY_LIST_SCHEMA, QEMU_BINARY_FILTER_SCHEMA, QEMU_CAPABILITY_LIST_SCHEMA, - QEMU_IMAGE_CREATE_SCHEMA + QEMU_IMAGE_CREATE_SCHEMA, + QEMU_IMAGE_UPDATE_SCHEMA ) @@ -61,10 +63,10 @@ class QEMUHandler: description="Create a new Qemu VM instance", input=QEMU_CREATE_SCHEMA, output=QEMU_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): qemu = Qemu.instance() - vm = yield from qemu.create_node(request.json.pop("name"), + vm = await qemu.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.pop("node_id", None), linked_clone=request.json.get("linked_clone", True), @@ -118,7 +120,8 @@ class QEMUHandler: qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - + # update the console first to avoid issue if updating console type + vm.console = request.json.pop("console", vm.console) for name, value in request.json.items(): if hasattr(vm, name) and getattr(vm, name) != value: setattr(vm, name, value) @@ -138,9 +141,9 @@ class QEMUHandler: 404: "Instance doesn't exist" }, description="Delete a Qemu VM instance") - def delete(request, response): + async def delete(request, response): - yield from Qemu.instance().delete_node(request.match_info["node_id"]) + await Qemu.instance().delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -154,15 +157,34 @@ class QEMUHandler: 404: "Instance doesn't exist" }, description="Duplicate a Qemu instance") - def duplicate(request, response): + async def duplicate(request, response): - new_node = yield from Qemu.instance().duplicate_node( + new_node = await Qemu.instance().duplicate_node( request.match_info["node_id"], request.json["destination_node_id"] ) response.set_status(201) response.json(new_node) + @Route.post( + r"/projects/{project_id}/qemu/nodes/{node_id}/resize_disk", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 201: "Instance updated", + 404: "Instance doesn't exist" + }, + description="Resize a Qemu VM disk image", + input=QEMU_RESIZE_SCHEMA) + async def resize_disk(request, response): + + qemu_manager = Qemu.instance() + vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + await vm.resize_disk(request.json["drive_name"], request.json["extend"]) + response.set_status(201) + @Route.post( r"/projects/{project_id}/qemu/nodes/{node_id}/start", parameters={ @@ -176,15 +198,21 @@ class QEMUHandler: }, description="Start a Qemu VM instance", output=QEMU_OBJECT_SCHEMA) - def start(request, response): + async def start(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - if sys.platform.startswith("linux") and qemu_manager.config.get_section_config("Qemu").getboolean("enable_kvm", True) and "-no-kvm" not in vm.options: + hardware_accel = qemu_manager.config.get_section_config("Qemu").getboolean("enable_hardware_acceleration", True) + if sys.platform.startswith("linux"): + # the enable_kvm option was used before version 2.0 and has priority + enable_kvm = qemu_manager.config.get_section_config("Qemu").getboolean("enable_kvm") + if enable_kvm is not None: + hardware_accel = enable_kvm + if hardware_accel and "-no-kvm" not in vm.options and "-no-hax" not in vm.options: pm = ProjectManager.instance() if pm.check_hardware_virtualization(vm) is False: - raise aiohttp.web.HTTPConflict(text="Cannot start VM with KVM enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox") - yield from vm.start() + raise aiohttp.web.HTTPConflict(text="Cannot start VM with hardware acceleration (KVM/HAX) enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox") + await vm.start() response.json(vm) @Route.post( @@ -199,11 +227,11 @@ class QEMUHandler: 404: "Instance doesn't exist" }, description="Stop a Qemu VM instance") - def stop(request, response): + async def stop(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.stop() + await vm.stop() response.set_status(204) @Route.post( @@ -218,11 +246,11 @@ class QEMUHandler: 404: "Instance doesn't exist" }, description="Reload a Qemu VM instance") - def reload(request, response): + async def reload(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.reload() + await vm.reload() response.set_status(204) @Route.post( @@ -237,11 +265,11 @@ class QEMUHandler: 404: "Instance doesn't exist" }, description="Suspend a Qemu VM instance") - def suspend(request, response): + async def suspend(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.suspend() + await vm.suspend() response.set_status(204) @Route.post( @@ -256,11 +284,11 @@ class QEMUHandler: 404: "Instance doesn't exist" }, description="Resume a Qemu VM instance") - def resume(request, response): + async def resume(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.resume() + await vm.resume() response.set_status(204) @Route.post( @@ -279,15 +307,15 @@ class QEMUHandler: description="Add a NIO to a Qemu VM instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) nio_type = request.json["type"] - if nio_type not in ("nio_udp", "nio_tap", "nio_nat"): + if nio_type not in ("nio_udp"): raise aiohttp.web.HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) nio = qemu_manager.create_nio(request.json) - yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio) + await vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio) response.set_status(201) response.json(nio) @@ -306,15 +334,18 @@ class QEMUHandler: }, input=NIO_SCHEMA, output=NIO_SCHEMA, - description="Update a NIO from a Qemu instance") - def update_nio(request, response): + description="Update a NIO on a Qemu instance") + async def update_nio(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = vm.ethernet_adapters[int(request.match_info["adapter_number"])] - if "filters" in request.json and nio: + adapter_number = int(request.match_info["adapter_number"]) + nio = vm.get_nio(adapter_number) + if "filters" in request.json: nio.filters = request.json["filters"] - yield from vm.adapter_update_nio_binding(int(request.match_info["adapter_number"]), nio) + if "suspend" in request.json: + nio.suspend = request.json["suspend"] + await vm.adapter_update_nio_binding(adapter_number, nio) response.set_status(201) response.json(request.json) @@ -332,11 +363,12 @@ class QEMUHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a Qemu VM instance") - def delete_nio(request, response): + async def delete_nio(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"])) + adapter_number = int(request.match_info["adapter_number"]) + await vm.adapter_remove_nio_binding(adapter_number) response.set_status(204) @Route.post( @@ -354,13 +386,13 @@ class QEMUHandler: }, description="Start a packet capture on a Qemu VM instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) - yield from vm.start_capture(adapter_number, pcap_file_path) + await vm.start_capture(adapter_number, pcap_file_path) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -377,14 +409,36 @@ class QEMUHandler: 404: "Instance doesn't exist", }, description="Stop a packet capture on a Qemu VM instance") - def stop_capture(request, response): + async def stop_capture(request, response): qemu_manager = Qemu.instance() vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) - yield from vm.stop_capture(adapter_number) + await vm.stop_capture(adapter_number) response.set_status(204) + @Route.get( + r"/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture", + "port_number": "Port on the adapter (always 0)" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + qemu_manager = Qemu.instance() + vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + adapter_number = int(request.match_info["adapter_number"]) + nio = vm.get_nio(adapter_number) + await qemu_manager.stream_pcap_file(nio, vm.project.id, request, response) + @Route.get( r"/qemu/binaries", status_codes={ @@ -395,9 +449,9 @@ class QEMUHandler: description="Get a list of available Qemu binaries", input=QEMU_BINARY_FILTER_SCHEMA, output=QEMU_BINARY_LIST_SCHEMA) - def list_binaries(request, response): + async def list_binaries(request, response): - binaries = yield from Qemu.binary_list(request.json.get("archs", None)) + binaries = await Qemu.binary_list(request.json.get("archs", None)) response.json(binaries) @Route.get( @@ -409,9 +463,9 @@ class QEMUHandler: }, description="Get a list of available Qemu-img binaries", output=QEMU_BINARY_LIST_SCHEMA) - def list_img_binaries(request, response): + async def list_img_binaries(request, response): - binaries = yield from Qemu.img_binary_list() + binaries = await Qemu.img_binary_list() response.json(binaries) @Route.get( @@ -422,9 +476,9 @@ class QEMUHandler: description="Get a list of Qemu capabilities on this server", output=QEMU_CAPABILITY_LIST_SCHEMA ) - def get_capabilities(request, response): + async def get_capabilities(request, response): capabilities = {"kvm": []} - kvms = yield from Qemu.get_kvm_archs() + kvms = await Qemu.get_kvm_archs() if kvms: capabilities["kvm"] = kvms response.json(capabilities) @@ -437,7 +491,7 @@ class QEMUHandler: description="Create a Qemu image", input=QEMU_IMAGE_CREATE_SCHEMA ) - def create_img(request, response): + async def create_img(request, response): qemu_img = request.json.pop("qemu_img") path = request.json.pop("path") @@ -447,7 +501,29 @@ class QEMUHandler: response.set_status(403) return - yield from Qemu.instance().create_disk(qemu_img, path, request.json) + await Qemu.instance().create_disk(qemu_img, path, request.json) + response.set_status(201) + + @Route.put( + r"/qemu/img", + status_codes={ + 201: "Image Updated", + }, + description="Update a Qemu image", + input=QEMU_IMAGE_UPDATE_SCHEMA + ) + async def update_img(request, response): + + qemu_img = request.json.pop("qemu_img") + path = request.json.pop("path") + if os.path.isabs(path): + config = Config.instance() + if config.get_section_config("Server").getboolean("local", False) is False: + response.set_status(403) + return + + if "extend" in request.json: + await Qemu.instance().resize_disk(qemu_img, path, request.json.pop("extend")) response.set_status(201) @Route.get( @@ -457,10 +533,10 @@ class QEMUHandler: }, description="Retrieve the list of Qemu images", output=NODE_LIST_IMAGES_SCHEMA) - def list_qemu_images(request, response): + async def list_qemu_images(request, response): qemu_manager = Qemu.instance() - images = yield from qemu_manager.list_images() + images = await qemu_manager.list_images() response.set_status(200) response.json(images) @@ -474,10 +550,10 @@ class QEMUHandler: }, raw=True, description="Upload Qemu image") - def upload_image(request, response): + async def upload_image(request, response): qemu_manager = Qemu.instance() - yield from qemu_manager.write_image(request.match_info["filename"], request.content) + await qemu_manager.write_image(request.match_info["filename"], request.content) response.set_status(204) @Route.get( @@ -490,14 +566,14 @@ class QEMUHandler: }, raw=True, description="Download Qemu image") - def download_image(request, response): + async def download_image(request, response): filename = request.match_info["filename"] - iou_manager = Qemu.instance() - image_path = iou_manager.get_abs_image_path(filename) + qemu_manager = Qemu.instance() + image_path = qemu_manager.get_abs_image_path(filename) # Raise error if user try to escape if filename[0] == ".": raise aiohttp.web.HTTPForbidden() - yield from response.file(image_path) + await response.stream_file(image_path) diff --git a/gns3server/handlers/api/compute/server_handler.py b/gns3server/handlers/api/compute/server_handler.py index 33ab1792..82e69a73 100644 --- a/gns3server/handlers/api/compute/server_handler.py +++ b/gns3server/handlers/api/compute/server_handler.py @@ -15,7 +15,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os import psutil import platform @@ -24,7 +23,6 @@ from gns3server.config import Config from gns3server.schemas.version import VERSION_SCHEMA from gns3server.compute.port_manager import PortManager from gns3server.version import __version__ -from aiohttp.web import HTTPConflict class ServerHandler: @@ -39,12 +37,11 @@ class ServerHandler: local_server = config.get_section_config("Server").getboolean("local", False) response.json({"version": __version__, "local": local_server}) - @Route.get( r"/debug", - description="Return debug informations about the compute", + description="Return debug information about the compute", status_codes={ - 201: "Writed" + 201: "Written" }) def debug(request, response): response.content_type = "text/plain" diff --git a/gns3server/handlers/api/compute/traceng_handler.py b/gns3server/handlers/api/compute/traceng_handler.py new file mode 100644 index 00000000..f4061692 --- /dev/null +++ b/gns3server/handlers/api/compute/traceng_handler.py @@ -0,0 +1,365 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2018 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 +from aiohttp.web import HTTPConflict +from gns3server.web.route import Route +from gns3server.schemas.nio import NIO_SCHEMA +from gns3server.schemas.node import NODE_CAPTURE_SCHEMA +from gns3server.compute.traceng import TraceNG + +from gns3server.schemas.traceng import ( + TRACENG_CREATE_SCHEMA, + TRACENG_UPDATE_SCHEMA, + TRACENG_START_SCHEMA, + TRACENG_OBJECT_SCHEMA +) + + +class TraceNGHandler: + """ + API entry points for TraceNG. + """ + + @Route.post( + r"/projects/{project_id}/traceng/nodes", + parameters={ + "project_id": "Project UUID" + }, + status_codes={ + 201: "Instance created", + 400: "Invalid request", + 409: "Conflict" + }, + description="Create a new TraceNG instance", + input=TRACENG_CREATE_SCHEMA, + output=TRACENG_OBJECT_SCHEMA) + async def create(request, response): + + traceng = TraceNG.instance() + vm = await traceng.create_node(request.json["name"], + request.match_info["project_id"], + request.json.get("node_id"), + console=request.json.get("console")) + vm.ip_address = request.json.get("ip_address", "") + vm.default_destination = request.json.get("default_destination", "") + response.set_status(201) + response.json(vm) + + @Route.get( + r"/projects/{project_id}/traceng/nodes/{node_id}", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 200: "Success", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Get a TraceNG instance", + output=TRACENG_OBJECT_SCHEMA) + def show(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + response.json(vm) + + @Route.put( + r"/projects/{project_id}/traceng/nodes/{node_id}", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 200: "Instance updated", + 400: "Invalid request", + 404: "Instance doesn't exist", + 409: "Conflict" + }, + description="Update a TraceNG instance", + input=TRACENG_UPDATE_SCHEMA, + output=TRACENG_OBJECT_SCHEMA) + def update(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + vm.name = request.json.get("name", vm.name) + vm.ip_address = request.json.get("ip_address", vm.ip_address) + vm.default_destination = request.json.get("default_destination", vm.default_destination) + vm.updated() + response.json(vm) + + @Route.delete( + r"/projects/{project_id}/traceng/nodes/{node_id}", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 204: "Instance deleted", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Delete a TraceNG instance") + async def delete(request, response): + + await TraceNG.instance().delete_node(request.match_info["node_id"]) + response.set_status(204) + + @Route.post( + r"/projects/{project_id}/traceng/nodes/{node_id}/duplicate", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 201: "Instance duplicated", + 404: "Instance doesn't exist" + }, + description="Duplicate a TraceNG instance") + async def duplicate(request, response): + + new_node = await TraceNG.instance().duplicate_node( + request.match_info["node_id"], + request.json["destination_node_id"] + ) + response.set_status(201) + response.json(new_node) + + @Route.post( + r"/projects/{project_id}/traceng/nodes/{node_id}/start", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 204: "Instance started", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Start a TraceNG instance", + input=TRACENG_START_SCHEMA, + output=TRACENG_OBJECT_SCHEMA) + async def start(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + await vm.start(request.get("destination")) + response.json(vm) + + @Route.post( + r"/projects/{project_id}/traceng/nodes/{node_id}/stop", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 204: "Instance stopped", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Stop a TraceNG instance") + async def stop(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + await vm.stop() + response.set_status(204) + + @Route.post( + r"/projects/{project_id}/traceng/nodes/{node_id}/suspend", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 204: "Instance suspended", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Suspend a TraceNG instance (does nothing)") + def suspend(request, response): + + traceng_manager = TraceNG.instance() + traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + response.set_status(204) + + @Route.post( + r"/projects/{project_id}/traceng/nodes/{node_id}/reload", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + }, + status_codes={ + 204: "Instance reloaded", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Reload a TraceNG instance") + async def reload(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + await vm.reload() + response.set_status(204) + + @Route.post( + r"/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Network adapter where the nio is located", + "port_number": "Port where the nio should be added" + }, + status_codes={ + 201: "NIO created", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Add a NIO to a TraceNG instance", + input=NIO_SCHEMA, + output=NIO_SCHEMA) + async def create_nio(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + nio_type = request.json["type"] + if nio_type not in ("nio_udp"): + raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) + nio = traceng_manager.create_nio(request.json) + await vm.port_add_nio_binding(int(request.match_info["port_number"]), nio) + response.set_status(201) + response.json(nio) + + @Route.put( + r"/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Network adapter where the nio is located", + "port_number": "Port from where the nio should be updated" + }, + status_codes={ + 201: "NIO updated", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + input=NIO_SCHEMA, + output=NIO_SCHEMA, + description="Update a NIO on a TraceNG instance") + async def update_nio(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + nio = vm.get_nio(port_number) + if "filters" in request.json: + nio.filters = request.json["filters"] + await vm.port_update_nio_binding(port_number, nio) + response.set_status(201) + response.json(request.json) + + @Route.delete( + r"/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Network adapter where the nio is located", + "port_number": "Port from where the nio should be removed" + }, + status_codes={ + 204: "NIO deleted", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Remove a NIO from a TraceNG instance") + async def delete_nio(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + await vm.port_remove_nio_binding(port_number) + response.set_status(204) + + @Route.post( + r"/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to start a packet capture", + "port_number": "Port on the adapter" + }, + status_codes={ + 200: "Capture started", + 400: "Invalid request", + 404: "Instance doesn't exist", + }, + description="Start a packet capture on a TraceNG instance", + input=NODE_CAPTURE_SCHEMA) + async def start_capture(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) + await vm.start_capture(port_number, pcap_file_path) + response.json({"pcap_file_path": pcap_file_path}) + + @Route.post( + r"/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to stop a packet capture", + "port_number": "Port on the adapter" + }, + status_codes={ + 204: "Capture stopped", + 400: "Invalid request", + 404: "Instance doesn't exist", + }, + description="Stop a packet capture on a TraceNG instance") + async def stop_capture(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + await vm.stop_capture(port_number) + response.set_status(204) + + @Route.get( + r"/projects/{project_id}/traceng/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture", + "port_number": "Port on the adapter" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + traceng_manager = TraceNG.instance() + vm = traceng_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + nio = vm.get_nio(port_number) + await traceng_manager.stream_pcap_file(nio, vm.project.id, request, response) diff --git a/gns3server/handlers/api/compute/virtualbox_handler.py b/gns3server/handlers/api/compute/virtualbox_handler.py index 0d35ba6b..6e63c9f5 100644 --- a/gns3server/handlers/api/compute/virtualbox_handler.py +++ b/gns3server/handlers/api/compute/virtualbox_handler.py @@ -50,21 +50,22 @@ class VirtualBoxHandler: description="Create a new VirtualBox VM instance", input=VBOX_CREATE_SCHEMA, output=VBOX_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): vbox_manager = VirtualBox.instance() - vm = yield from vbox_manager.create_node(request.json.pop("name"), + vm = await vbox_manager.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), request.json.pop("vmname"), linked_clone=request.json.pop("linked_clone", False), console=request.json.get("console", None), + console_type=request.json.get("console_type", "telnet"), adapters=request.json.get("adapters", 0)) if "ram" in request.json: ram = request.json.pop("ram") if ram != vm.ram: - yield from vm.set_ram(ram) + await vm.set_ram(ram) for name, value in request.json.items(): if name != "node_id": @@ -108,7 +109,7 @@ class VirtualBoxHandler: description="Update a VirtualBox VM instance", input=VBOX_OBJECT_SCHEMA, output=VBOX_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -121,7 +122,7 @@ class VirtualBoxHandler: vm.name = name if vm.linked_clone: try: - yield from vm.set_vmname(vm.name) + await vm.set_vmname(vm.name) except VirtualBoxError as e: # In case of error we rollback (we can't change the name when running) vm.name = oldname vm.updated() @@ -130,12 +131,15 @@ class VirtualBoxHandler: if "adapters" in request.json: adapters = int(request.json.pop("adapters")) if adapters != vm.adapters: - yield from vm.set_adapters(adapters) + await vm.set_adapters(adapters) if "ram" in request.json: ram = request.json.pop("ram") if ram != vm.ram: - yield from vm.set_ram(ram) + await vm.set_ram(ram) + + # update the console first to avoid issue if updating console type + vm.console = request.json.pop("console", vm.console) for name, value in request.json.items(): if hasattr(vm, name) and getattr(vm, name) != value: @@ -156,11 +160,11 @@ class VirtualBoxHandler: 404: "Instance doesn't exist" }, description="Delete a VirtualBox VM instance") - def delete(request, response): + async def delete(request, response): # check the project_id exists ProjectManager.instance().get_project(request.match_info["project_id"]) - yield from VirtualBox.instance().delete_node(request.match_info["node_id"]) + await VirtualBox.instance().delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -175,15 +179,15 @@ class VirtualBoxHandler: 404: "Instance doesn't exist" }, description="Start a VirtualBox VM instance") - def start(request, response): + async def start(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - if (yield from vm.check_hw_virtualization()): + if (await vm.check_hw_virtualization()): pm = ProjectManager.instance() if pm.check_hardware_virtualization(vm) is False: raise HTTPConflict(text="Cannot start VM because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or KVM (on Linux)") - yield from vm.start() + await vm.start() response.set_status(204) @Route.post( @@ -198,11 +202,11 @@ class VirtualBoxHandler: 404: "Instance doesn't exist" }, description="Stop a VirtualBox VM instance") - def stop(request, response): + async def stop(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.stop() + await vm.stop() response.set_status(204) @Route.post( @@ -217,11 +221,11 @@ class VirtualBoxHandler: 404: "Instance doesn't exist" }, description="Suspend a VirtualBox VM instance") - def suspend(request, response): + async def suspend(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.suspend() + await vm.suspend() response.set_status(204) @Route.post( @@ -236,11 +240,11 @@ class VirtualBoxHandler: 404: "Instance doesn't exist" }, description="Resume a suspended VirtualBox VM instance") - def resume(request, response): + async def resume(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.resume() + await vm.resume() response.set_status(204) @Route.post( @@ -255,11 +259,11 @@ class VirtualBoxHandler: 404: "Instance doesn't exist" }, description="Reload a VirtualBox VM instance") - def reload(request, response): + async def reload(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.reload() + await vm.reload() response.set_status(204) @Route.post( @@ -278,7 +282,7 @@ class VirtualBoxHandler: description="Add a NIO to a VirtualBox VM instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -286,7 +290,7 @@ class VirtualBoxHandler: if nio_type not in ("nio_udp", "nio_nat"): raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) nio = vbox_manager.create_nio(request.json) - yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio) + await vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio) response.set_status(201) response.json(nio) @@ -305,15 +309,18 @@ class VirtualBoxHandler: }, input=NIO_SCHEMA, output=NIO_SCHEMA, - description="Update a NIO from a Virtualbox instance") - def update_nio(request, response): + description="Update a NIO on a Virtualbox instance") + async def update_nio(request, response): virtualbox_manager = VirtualBox.instance() vm = virtualbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = vm.ethernet_adapters[int(request.match_info["adapter_number"])] - if "filters" in request.json and nio: + adapter_number = int(request.match_info["adapter_number"]) + nio = vm.get_nio(adapter_number) + if "filters" in request.json: nio.filters = request.json["filters"] - yield from vm.adapter_update_nio_binding(int(request.match_info["adapter_number"]), nio) + if "suspend" in request.json: + nio.suspend = request.json["suspend"] + await vm.adapter_update_nio_binding(adapter_number, nio) response.set_status(201) response.json(request.json) @@ -331,11 +338,12 @@ class VirtualBoxHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a VirtualBox VM instance") - def delete_nio(request, response): + async def delete_nio(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"])) + adapter_number = int(request.match_info["adapter_number"]) + await vm.adapter_remove_nio_binding(adapter_number) response.set_status(204) @Route.post( @@ -353,13 +361,13 @@ class VirtualBoxHandler: }, description="Start a packet capture on a VirtualBox VM instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) - yield from vm.start_capture(adapter_number, pcap_file_path) + await vm.start_capture(adapter_number, pcap_file_path) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -376,20 +384,43 @@ class VirtualBoxHandler: 404: "Instance doesn't exist" }, description="Stop a packet capture on a VirtualBox VM instance") - def stop_capture(request, response): + async def stop_capture(request, response): vbox_manager = VirtualBox.instance() vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - vm.stop_capture(int(request.match_info["adapter_number"])) + adapter_number = int(request.match_info["adapter_number"]) + await vm.stop_capture(adapter_number) response.set_status(204) + @Route.get( + r"/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture", + "port_number": "Port on the adapter (always 0)" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + virtualbox_manager = VirtualBox.instance() + vm = virtualbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + adapter_number = int(request.match_info["adapter_number"]) + nio = vm.get_nio(adapter_number) + await virtualbox_manager.stream_pcap_file(nio, vm.project.id, request, response) + @Route.get( r"/virtualbox/vms", status_codes={ 200: "Success", }, description="Get all available VirtualBox VMs") - def get_vms(request, response): + async def get_vms(request, response): vbox_manager = VirtualBox.instance() - vms = yield from vbox_manager.list_vms() + vms = await vbox_manager.list_vms() response.json(vms) diff --git a/gns3server/handlers/api/compute/vmware_handler.py b/gns3server/handlers/api/compute/vmware_handler.py index 06d8a545..9c596deb 100644 --- a/gns3server/handlers/api/compute/vmware_handler.py +++ b/gns3server/handlers/api/compute/vmware_handler.py @@ -49,15 +49,16 @@ class VMwareHandler: description="Create a new VMware VM instance", input=VMWARE_CREATE_SCHEMA, output=VMWARE_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): vmware_manager = VMware.instance() - vm = yield from vmware_manager.create_node(request.json.pop("name"), + vm = await vmware_manager.create_node(request.json.pop("name"), request.match_info["project_id"], request.json.get("node_id"), request.json.pop("vmx_path"), linked_clone=request.json.pop("linked_clone"), - console=request.json.get("console", None)) + console=request.json.get("console", None), + console_type=request.json.get("console_type", "telnet")) for name, value in request.json.items(): if name != "node_id": @@ -105,7 +106,8 @@ class VMwareHandler: vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - + # update the console first to avoid issue if updating console type + vm.console = request.json.pop("console", vm.console) for name, value in request.json.items(): if hasattr(vm, name) and getattr(vm, name) != value: setattr(vm, name, value) @@ -125,11 +127,11 @@ class VMwareHandler: 404: "Instance doesn't exist" }, description="Delete a VMware VM instance") - def delete(request, response): + async def delete(request, response): # check the project_id exists ProjectManager.instance().get_project(request.match_info["project_id"]) - yield from VMware.instance().delete_node(request.match_info["node_id"]) + await VMware.instance().delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -144,7 +146,7 @@ class VMwareHandler: 404: "Instance doesn't exist" }, description="Start a VMware VM instance") - def start(request, response): + async def start(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -152,7 +154,7 @@ class VMwareHandler: pm = ProjectManager.instance() if pm.check_hardware_virtualization(vm) is False: raise HTTPConflict(text="Cannot start VM because hardware virtualization (VT-x/AMD-V) is already used by another software like VirtualBox or KVM (on Linux)") - yield from vm.start() + await vm.start() response.set_status(204) @Route.post( @@ -167,11 +169,11 @@ class VMwareHandler: 404: "Instance doesn't exist" }, description="Stop a VMware VM instance") - def stop(request, response): + async def stop(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.stop() + await vm.stop() response.set_status(204) @Route.post( @@ -186,11 +188,11 @@ class VMwareHandler: 404: "Instance doesn't exist" }, description="Suspend a VMware VM instance") - def suspend(request, response): + async def suspend(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.suspend() + await vm.suspend() response.set_status(204) @Route.post( @@ -205,11 +207,11 @@ class VMwareHandler: 404: "Instance doesn't exist" }, description="Resume a suspended VMware VM instance") - def resume(request, response): + async def resume(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.resume() + await vm.resume() response.set_status(204) @Route.post( @@ -224,11 +226,11 @@ class VMwareHandler: 404: "Instance doesn't exist" }, description="Reload a VMware VM instance") - def reload(request, response): + async def reload(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.reload() + await vm.reload() response.set_status(204) @Route.post( @@ -247,7 +249,7 @@ class VMwareHandler: description="Add a NIO to a VMware VM instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) @@ -255,7 +257,7 @@ class VMwareHandler: if nio_type not in ("nio_udp", "nio_vmnet", "nio_nat", "nio_tap"): raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) nio = vmware_manager.create_nio(request.json) - yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio) + await vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio) response.set_status(201) response.json(nio) @@ -274,17 +276,18 @@ class VMwareHandler: }, input=NIO_SCHEMA, output=NIO_SCHEMA, - description="Update a NIO from a Virtualbox instance") - def update_nio(request, response): + description="Update a NIO on a VMware VM instance") + async def update_nio(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = vm.ethernet_adapters[int(request.match_info["adapter_number"])] - if "filters" in request.json and nio: + adapter_number = int(request.match_info["adapter_number"]) + nio = vm.get_nio(adapter_number) + if "filters" in request.json: nio.filters = request.json["filters"] - yield from vm.adapter_update_nio_binding(int(request.match_info["adapter_number"]), nio) - response.set_status(201) - response.json(request.json) + await vm.adapter_update_nio_binding(adapter_number, nio) + response.set_status(201) + response.json(request.json) @Route.delete( r"/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", @@ -300,11 +303,12 @@ class VMwareHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a VMware VM instance") - def delete_nio(request, response): + async def delete_nio(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"])) + adapter_number = int(request.match_info["adapter_number"]) + await vm.adapter_remove_nio_binding(adapter_number) response.set_status(204) @Route.post( @@ -322,13 +326,13 @@ class VMwareHandler: }, description="Start a packet capture on a VMware VM instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) - yield from vm.start_capture(adapter_number, pcap_file_path) + await vm.start_capture(adapter_number, pcap_file_path) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -345,14 +349,36 @@ class VMwareHandler: 404: "Instance doesn't exist", }, description="Stop a packet capture on a VMware VM instance") - def stop_capture(request, response): + async def stop_capture(request, response): vmware_manager = VMware.instance() vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) adapter_number = int(request.match_info["adapter_number"]) - yield from vm.stop_capture(adapter_number) + await vm.stop_capture(adapter_number) response.set_status(204) + @Route.get( + r"/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture", + "port_number": "Port on the adapter (always 0)" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + vmware_manager = VMware.instance() + vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + adapter_number = int(request.match_info["adapter_number"]) + nio = vm.get_nio(adapter_number) + await vmware_manager.stream_pcap_file(nio, vm.project.id, request, response) + @Route.post( r"/projects/{project_id}/vmware/nodes/{node_id}/interfaces/vmnet", parameters={ @@ -379,7 +405,7 @@ class VMwareHandler: 200: "Success", }, description="Get all VMware VMs available") - def get_vms(request, response): + async def get_vms(request, response): vmware_manager = VMware.instance() - vms = yield from vmware_manager.list_vms() + vms = await vmware_manager.list_vms() response.json(vms) diff --git a/gns3server/handlers/api/compute/vpcs_handler.py b/gns3server/handlers/api/compute/vpcs_handler.py index 6dbf2bee..51a3ca7e 100644 --- a/gns3server/handlers/api/compute/vpcs_handler.py +++ b/gns3server/handlers/api/compute/vpcs_handler.py @@ -47,13 +47,14 @@ class VPCSHandler: description="Create a new VPCS instance", input=VPCS_CREATE_SCHEMA, output=VPCS_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): vpcs = VPCS.instance() - vm = yield from vpcs.create_node(request.json["name"], + vm = await vpcs.create_node(request.json["name"], request.match_info["project_id"], request.json.get("node_id"), console=request.json.get("console"), + console_type=request.json.get("console_type", "telnet"), startup_script=request.json.get("startup_script")) response.set_status(201) response.json(vm) @@ -98,6 +99,7 @@ class VPCSHandler: vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) vm.name = request.json.get("name", vm.name) vm.console = request.json.get("console", vm.console) + vm.console_type = request.json.get("console_type", vm.console_type) vm.updated() response.json(vm) @@ -113,9 +115,9 @@ class VPCSHandler: 404: "Instance doesn't exist" }, description="Delete a VPCS instance") - def delete(request, response): + async def delete(request, response): - yield from VPCS.instance().delete_node(request.match_info["node_id"]) + await VPCS.instance().delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -129,9 +131,9 @@ class VPCSHandler: 404: "Instance doesn't exist" }, description="Duplicate a VPCS instance") - def duplicate(request, response): + async def duplicate(request, response): - new_node = yield from VPCS.instance().duplicate_node( + new_node = await VPCS.instance().duplicate_node( request.match_info["node_id"], request.json["destination_node_id"] ) @@ -151,11 +153,11 @@ class VPCSHandler: }, description="Start a VPCS instance", output=VPCS_OBJECT_SCHEMA) - def start(request, response): + async def start(request, response): vpcs_manager = VPCS.instance() vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.start() + await vm.start() response.json(vm) @Route.post( @@ -170,11 +172,11 @@ class VPCSHandler: 404: "Instance doesn't exist" }, description="Stop a VPCS instance") - def stop(request, response): + async def stop(request, response): vpcs_manager = VPCS.instance() vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.stop() + await vm.stop() response.set_status(204) @Route.post( @@ -207,11 +209,11 @@ class VPCSHandler: 404: "Instance doesn't exist" }, description="Reload a VPCS instance") - def reload(request, response): + async def reload(request, response): vpcs_manager = VPCS.instance() vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.reload() + await vm.reload() response.set_status(204) @Route.post( @@ -230,15 +232,16 @@ class VPCSHandler: description="Add a NIO to a VPCS instance", input=NIO_SCHEMA, output=NIO_SCHEMA) - def create_nio(request, response): + async def create_nio(request, response): vpcs_manager = VPCS.instance() vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) nio_type = request.json["type"] if nio_type not in ("nio_udp", "nio_tap"): raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) + port_number = int(request.match_info["port_number"]) nio = vpcs_manager.create_nio(request.json) - yield from vm.port_add_nio_binding(int(request.match_info["port_number"]), nio) + await vm.port_add_nio_binding(port_number, nio) response.set_status(201) response.json(nio) @@ -257,15 +260,16 @@ class VPCSHandler: }, input=NIO_SCHEMA, output=NIO_SCHEMA, - description="Update a NIO from a VPCS instance") - def update_nio(request, response): + description="Update a NIO on a VPCS instance") + async def update_nio(request, response): vpcs_manager = VPCS.instance() vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - nio = vm.ethernet_adapter.get_nio(int(request.match_info["port_number"])) - if "filters" in request.json and nio: + port_number = int(request.match_info["port_number"]) + nio = vm.get_nio(port_number) + if "filters" in request.json: nio.filters = request.json["filters"] - yield from vm.port_update_nio_binding(int(request.match_info["port_number"]), nio) + await vm.port_update_nio_binding(port_number, nio) response.set_status(201) response.json(request.json) @@ -283,11 +287,12 @@ class VPCSHandler: 404: "Instance doesn't exist" }, description="Remove a NIO from a VPCS instance") - def delete_nio(request, response): + async def delete_nio(request, response): vpcs_manager = VPCS.instance() vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) - yield from vm.port_remove_nio_binding(int(request.match_info["port_number"])) + port_number = int(request.match_info["port_number"]) + await vm.port_remove_nio_binding(port_number) response.set_status(204) @Route.post( @@ -305,13 +310,13 @@ class VPCSHandler: }, description="Start a packet capture on a VPCS instance", input=NODE_CAPTURE_SCHEMA) - def start_capture(request, response): + async def start_capture(request, response): vpcs_manager = VPCS.instance() vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) - yield from vm.start_capture(port_number, pcap_file_path) + await vm.start_capture(port_number, pcap_file_path) response.json({"pcap_file_path": pcap_file_path}) @Route.post( @@ -328,10 +333,32 @@ class VPCSHandler: 404: "Instance doesn't exist", }, description="Stop a packet capture on a VPCS instance") - def stop_capture(request, response): + async def stop_capture(request, response): vpcs_manager = VPCS.instance() vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) port_number = int(request.match_info["port_number"]) - yield from vm.stop_capture(port_number) + await vm.stop_capture(port_number) response.set_status(204) + + @Route.get( + r"/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/pcap", + description="Stream the pcap capture file", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID", + "adapter_number": "Adapter to steam a packet capture", + "port_number": "Port on the adapter" + }, + status_codes={ + 200: "File returned", + 403: "Permission denied", + 404: "The file doesn't exist" + }) + async def stream_pcap_file(request, response): + + vpcs_manager = VPCS.instance() + vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) + port_number = int(request.match_info["port_number"]) + nio = vm.get_nio(port_number) + await vpcs_manager.stream_pcap_file(nio, vm.project.id, request, response) diff --git a/gns3server/handlers/api/controller/__init__.py b/gns3server/handlers/api/controller/__init__.py index b64424be..db93870f 100644 --- a/gns3server/handlers/api/controller/__init__.py +++ b/gns3server/handlers/api/controller/__init__.py @@ -24,4 +24,6 @@ from .drawing_handler import DrawingHandler from .symbol_handler import SymbolHandler from .snapshot_handler import SnapshotHandler from .appliance_handler import ApplianceHandler +from .template_handler import TemplateHandler from .gns3_vm_handler import GNS3VMHandler +from .notification_handler import NotificationHandler diff --git a/gns3server/handlers/api/controller/appliance_handler.py b/gns3server/handlers/api/controller/appliance_handler.py index b9dbc4cf..e8ceff84 100644 --- a/gns3server/handlers/api/controller/appliance_handler.py +++ b/gns3server/handlers/api/controller/appliance_handler.py @@ -17,58 +17,27 @@ from gns3server.web.route import Route from gns3server.controller import Controller -from gns3server.schemas.node import NODE_OBJECT_SCHEMA -from gns3server.schemas.appliance import APPLIANCE_USAGE_SCHEMA - import logging log = logging.getLogger(__name__) class ApplianceHandler: - """API entry points for appliance management.""" - - @Route.get( - r"/appliances/templates", - description="List of appliance templates", - status_codes={ - 200: "Appliance template list returned" - }) - def list_templates(request, response): - - controller = Controller.instance() - response.json([c for c in controller.appliance_templates.values()]) + """ + API entry points for appliance management. + """ @Route.get( r"/appliances", - description="List of appliance", + description="List of appliances", status_codes={ 200: "Appliance list returned" }) - def list(request, response): + async def list_appliances(request, response): controller = Controller.instance() - response.json([c for c in controller.appliances.values()]) - - @Route.post( - r"/projects/{project_id}/appliances/{appliance_id}", - description="Create a node from an appliance", - parameters={ - "project_id": "Project UUID", - "appliance_id": "Appliance template UUID" - }, - status_codes={ - 201: "Node created", - 404: "The project or template doesn't exist" - }, - input=APPLIANCE_USAGE_SCHEMA, - output=NODE_OBJECT_SCHEMA) - def create_node_from_appliance(request, response): - - controller = Controller.instance() - project = controller.get_project(request.match_info["project_id"]) - yield from project.add_node_from_appliance(request.match_info["appliance_id"], - x=request.json["x"], - y=request.json["y"], - compute_id=request.json.get("compute_id")) - response.set_status(201) + if request.query.get("update", "no").lower() == "yes": + await controller.appliance_manager.download_appliances() + symbol_theme = request.query.get("symbol_theme", "Classic") + controller.appliance_manager.load_appliances(symbol_theme=symbol_theme) + response.json([c for c in controller.appliance_manager.appliances.values()]) diff --git a/gns3server/handlers/api/controller/compute_handler.py b/gns3server/handlers/api/controller/compute_handler.py index 8695c900..fccc63f8 100644 --- a/gns3server/handlers/api/controller/compute_handler.py +++ b/gns3server/handlers/api/controller/compute_handler.py @@ -22,7 +22,8 @@ from gns3server.schemas.compute import ( COMPUTE_CREATE_SCHEMA, COMPUTE_OBJECT_SCHEMA, COMPUTE_UPDATE_SCHEMA, - COMPUTE_ENDPOINT_OUTPUT_OBJECT_SCHEMA + COMPUTE_ENDPOINT_OUTPUT_OBJECT_SCHEMA, + COMPUTE_PORTS_OBJECT_SCHEMA ) import logging @@ -30,27 +31,27 @@ log = logging.getLogger(__name__) class ComputeHandler: - """API entry points for compute server management.""" + """API entry points for compute management.""" @Route.post( r"/computes", - description="Register a compute server", + description="Register a compute", status_codes={ - 201: "Compute server added" + 201: "Compute added" }, input=COMPUTE_CREATE_SCHEMA, output=COMPUTE_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): - compute = yield from Controller.instance().add_compute(**request.json) + compute = await Controller.instance().add_compute(**request.json) response.set_status(201) response.json(compute) @Route.get( r"/computes", - description="List of compute servers", + description="List of computes", status_codes={ - 200: "Compute servers list returned" + 200: "Computes list returned" }) def list(request, response): @@ -59,39 +60,40 @@ class ComputeHandler: @Route.put( r"/computes/{compute_id}", - description="Get a compute server information", + description="Update a compute", status_codes={ - 200: "Compute server updated", + 200: "Compute updated", 400: "Invalid request", 404: "Instance doesn't exist" }, input=COMPUTE_UPDATE_SCHEMA, output=COMPUTE_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): controller = Controller.instance() compute = controller.get_compute(request.match_info["compute_id"]) # Ignore these because we only use them when creating a node request.json.pop("compute_id", None) - yield from compute.update(**request.json) + await compute.update(**request.json) response.set_status(200) response.json(compute) @Route.get( r"/computes/{compute_id}/{emulator}/images", parameters={ - "compute_id": "Compute UUID" + "compute_id": "Compute UUID", + "emulator": "Emulator type" }, status_codes={ 200: "OK", 404: "Instance doesn't exist" }, - description="Return the list of images available on compute and controller for this emulator type") - def images(request, response): + description="Return the list of images available on compute for this emulator type") + async def images(request, response): controller = Controller.instance() compute = controller.get_compute(request.match_info["compute_id"]) - res = yield from compute.images(request.match_info["emulator"]) + res = await compute.images(request.match_info["emulator"]) response.json(res) @Route.get( @@ -132,10 +134,10 @@ class ComputeHandler: 404: "Instance doesn't exist" }, description="Forward call specific to compute node. Read the full compute API for available actions") - def get_forward(request, response): + async def get_forward(request, response): controller = Controller.instance() compute = controller.get_compute(request.match_info["compute_id"]) - res = yield from compute.forward("GET", request.match_info["emulator"], request.match_info["action"]) + res = await compute.forward("GET", request.match_info["emulator"], request.match_info["action"]) response.json(res) @Route.post( @@ -149,17 +151,34 @@ class ComputeHandler: }, raw=True, description="Forward call specific to compute node. Read the full compute API for available actions") - def post_forward(request, response): + async def post_forward(request, response): controller = Controller.instance() compute = controller.get_compute(request.match_info["compute_id"]) - res = yield from compute.forward("POST", request.match_info["emulator"], request.match_info["action"], data=request.content) + res = await compute.forward("POST", request.match_info["emulator"], request.match_info["action"], data=request.content) + response.json(res) + + @Route.put( + r"/computes/{compute_id}/{emulator}/{action:.+}", + parameters={ + "compute_id": "Compute UUID" + }, + status_codes={ + 200: "OK", + 404: "Instance doesn't exist" + }, + raw=True, + description="Forward call specific to compute node. Read the full compute API for available actions") + async def put_forward(request, response): + controller = Controller.instance() + compute = controller.get_compute(request.match_info["compute_id"]) + res = await compute.forward("PUT", request.match_info["emulator"], request.match_info["action"], data=request.content) response.json(res) @Route.get( r"/computes/{compute_id}", - description="Get a compute server information", + description="Get a compute information", status_codes={ - 200: "Compute server information returned" + 200: "Compute information returned" }, output=COMPUTE_OBJECT_SCHEMA) def get(request, response): @@ -179,9 +198,9 @@ class ComputeHandler: 404: "Instance doesn't exist" }, description="Delete a compute instance") - def delete(request, response): + async def delete(request, response): controller = Controller.instance() - yield from controller.delete_compute(request.match_info["compute_id"]) + await controller.delete_compute(request.match_info["compute_id"]) response.set_status(204) @Route.post( @@ -193,8 +212,23 @@ class ComputeHandler: 200: "Idle PC computed", }, description="Compute IDLE PC value") - def autoidlepc(request, response): + async def autoidlepc(request, response): controller = Controller.instance() - res = yield from controller.autoidlepc(request.match_info["compute_id"], request.json["platform"], request.json["image"], request.json["ram"]) + res = await controller.autoidlepc(request.match_info["compute_id"], request.json["platform"], request.json["image"], request.json["ram"]) response.json(res) - response.set_status(200) + + @Route.get( + r"/computes/{compute_id}/ports", + parameters={ + "compute_id": "Compute UUID" + }, + status_codes={ + 200: "Ports information returned", + }, + description="Get ports used by a compute", + output=COMPUTE_PORTS_OBJECT_SCHEMA) + async def ports(request, response): + controller = Controller.instance() + res = await controller.compute_ports(request.match_info["compute_id"]) + response.json(res) + diff --git a/gns3server/handlers/api/controller/drawing_handler.py b/gns3server/handlers/api/controller/drawing_handler.py index 719b2694..2ff19b41 100644 --- a/gns3server/handlers/api/controller/drawing_handler.py +++ b/gns3server/handlers/api/controller/drawing_handler.py @@ -37,9 +37,9 @@ class DrawingHandler: 200: "List of drawings returned", }, description="List drawings of a project") - def list_drawings(request, response): + async def list_drawings(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) response.json([v for v in project.drawings.values()]) @Route.post( @@ -54,10 +54,10 @@ class DrawingHandler: description="Create a new drawing instance", input=DRAWING_OBJECT_SCHEMA, output=DRAWING_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - drawing = yield from project.add_drawing(**request.json) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + drawing = await project.add_drawing(**request.json) response.set_status(201) response.json(drawing) @@ -74,9 +74,9 @@ class DrawingHandler: }, description="Get a drawing instance", output=DRAWING_OBJECT_SCHEMA) - def get_drawing(request, response): + async def get_drawing(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) drawing = project.get_drawing(request.match_info["drawing_id"]) response.set_status(200) response.json(drawing) @@ -94,11 +94,11 @@ class DrawingHandler: description="Update a drawing instance", input=DRAWING_OBJECT_SCHEMA, output=DRAWING_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) drawing = project.get_drawing(request.match_info["drawing_id"]) - yield from drawing.update(**request.json) + await drawing.update(**request.json) response.set_status(201) response.json(drawing) @@ -113,8 +113,8 @@ class DrawingHandler: 400: "Invalid request" }, description="Delete a drawing instance") - def delete(request, response): + async def delete(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - yield from project.delete_drawing(request.match_info["drawing_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + await project.delete_drawing(request.match_info["drawing_id"]) response.set_status(204) diff --git a/gns3server/handlers/api/controller/gns3_vm_handler.py b/gns3server/handlers/api/controller/gns3_vm_handler.py index 87366f71..5506260d 100644 --- a/gns3server/handlers/api/controller/gns3_vm_handler.py +++ b/gns3server/handlers/api/controller/gns3_vm_handler.py @@ -15,12 +15,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from aiohttp.web import HTTPConflict from gns3server.web.route import Route from gns3server.controller import Controller from gns3server.schemas.gns3vm import GNS3VM_SETTINGS_SCHEMA - import logging log = logging.getLogger(__name__) @@ -49,9 +47,9 @@ class GNS3VMHandler: 400: "Invalid request", }, description="Get all the available VMs for a specific virtualization engine") - def get_vms(request, response): + async def get_vms(request, response): - vms = yield from Controller.instance().gns3vm.list(request.match_info["engine"]) + vms = await Controller.instance().gns3vm.list(request.match_info["engine"]) response.json(vms) @Route.get( @@ -72,9 +70,11 @@ class GNS3VMHandler: status_codes={ 201: "GNS3 VM updated" }) - def update(request, response): + async def update(request, response): - gns3_vm = Controller().instance().gns3vm - yield from gns3_vm.update_settings(request.json) + controller = Controller().instance() + gns3_vm = controller.gns3vm + await gns3_vm.update_settings(request.json) + controller.save() response.json(gns3_vm) response.set_status(201) diff --git a/gns3server/handlers/api/controller/link_handler.py b/gns3server/handlers/api/controller/link_handler.py index 48e394cb..7854583a 100644 --- a/gns3server/handlers/api/controller/link_handler.py +++ b/gns3server/handlers/api/controller/link_handler.py @@ -15,9 +15,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os -import asyncio import aiohttp +import multidict from gns3server.web.route import Route from gns3server.controller import Controller @@ -42,9 +41,9 @@ class LinkHandler: 200: "List of links returned", }, description="List links of a project") - def list_links(request, response): + async def list_links(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) response.json([v for v in project.links.values()]) @Route.post( @@ -59,22 +58,22 @@ class LinkHandler: description="Create a new link instance", input=LINK_OBJECT_SCHEMA, output=LINK_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - link = yield from project.add_link() + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + link = await project.add_link() if "filters" in request.json: - yield from link.update_filters(request.json["filters"]) + await link.update_filters(request.json["filters"]) if "suspend" in request.json: - yield from link.update_suspend(request.json["suspend"]) + await link.update_suspend(request.json["suspend"]) try: for node in request.json["nodes"]: - yield from link.add_node(project.get_node(node["node_id"]), + await link.add_node(project.get_node(node["node_id"]), node.get("adapter_number", 0), node.get("port_number", 0), label=node.get("label")) - except aiohttp.web_exceptions.HTTPException as e: - yield from project.delete_link(link.id) + except aiohttp.web.HTTPException as e: + await project.delete_link(link.id) raise e response.set_status(201) response.json(link) @@ -90,9 +89,9 @@ class LinkHandler: 400: "Invalid request" }, description="Return the list of filters available for this link") - def list_filters(request, response): + async def list_filters(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) link = project.get_link(request.match_info["link_id"]) response.set_status(200) response.json(link.available_filters()) @@ -110,9 +109,9 @@ class LinkHandler: }, description="Get a link instance", output=LINK_OBJECT_SCHEMA) - def get_link(request, response): + async def get_link(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) link = project.get_link(request.match_info["link_id"]) response.set_status(200) response.json(link) @@ -130,16 +129,16 @@ class LinkHandler: description="Update a link instance", input=LINK_OBJECT_SCHEMA, output=LINK_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) link = project.get_link(request.match_info["link_id"]) if "filters" in request.json: - yield from link.update_filters(request.json["filters"]) + await link.update_filters(request.json["filters"]) if "suspend" in request.json: - yield from link.update_suspend(request.json["suspend"]) + await link.update_suspend(request.json["suspend"]) if "nodes" in request.json: - yield from link.update_nodes(request.json["nodes"]) + await link.update_nodes(request.json["nodes"]) response.set_status(201) response.json(link) @@ -156,11 +155,12 @@ class LinkHandler: input=LINK_CAPTURE_SCHEMA, output=LINK_OBJECT_SCHEMA, description="Start capture on a link instance. By default we consider it as an Ethernet link") - def start_capture(request, response): + async def start_capture(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) link = project.get_link(request.match_info["link_id"]) - yield from link.start_capture(data_link_type=request.json.get("data_link_type", "DLT_EN10MB"), capture_file_name=request.json.get("capture_file_name")) + await link.start_capture(data_link_type=request.json.get("data_link_type", "DLT_EN10MB"), + capture_file_name=request.json.get("capture_file_name")) response.set_status(201) response.json(link) @@ -175,11 +175,11 @@ class LinkHandler: 400: "Invalid request" }, description="Stop capture on a link instance") - def stop_capture(request, response): + async def stop_capture(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) link = project.get_link(request.match_info["link_id"]) - yield from link.stop_capture() + await link.stop_capture() response.set_status(201) response.json(link) @@ -194,10 +194,10 @@ class LinkHandler: 400: "Invalid request" }, description="Delete a link instance") - def delete(request, response): + async def delete(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - yield from project.delete_link(request.match_info["link_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + await project.delete_link(request.match_info["link_id"]) response.set_status(204) @Route.get( @@ -206,35 +206,35 @@ class LinkHandler: "project_id": "Project UUID", "link_id": "Link UUID" }, - description="Stream the pcap capture file", + description="Stream the PCAP capture file from compute", status_codes={ 200: "File returned", 403: "Permission denied", 404: "The file doesn't exist" }) - def pcap(request, response): + async def pcap(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) link = project.get_link(request.match_info["link_id"]) + if not link.capturing: + raise aiohttp.web.HTTPConflict(text="This link has no active packet capture") - while link.capture_file_path is None: - raise aiohttp.web.HTTPNotFound(text="pcap file not found") + compute = link.compute + pcap_streaming_url = link.pcap_streaming_url() + headers = multidict.MultiDict(request.headers) + headers['Host'] = compute.host + headers['Router-Host'] = request.host + body = await request.read() - while not os.path.isfile(link.capture_file_path): - yield from asyncio.sleep(0.5) + connector = aiohttp.TCPConnector(limit=None, force_close=True) + async with aiohttp.ClientSession(connector=connector, headers=headers) as session: + async with session.request(request.method, pcap_streaming_url, timeout=None, data=body) as response: + proxied_response = aiohttp.web.Response(headers=response.headers, status=response.status) + if response.headers.get('Transfer-Encoding', '').lower() == 'chunked': + proxied_response.enable_chunked_encoding() - try: - with open(link.capture_file_path, "rb") as f: - - response.content_type = "application/vnd.tcpdump.pcap" - response.set_status(200) - response.enable_chunked_encoding() - yield from response.prepare(request) - - while True: - chunk = f.read(4096) - if not chunk: - yield from asyncio.sleep(0.1) - yield from response.write(chunk) - except OSError: - raise aiohttp.web.HTTPNotFound(text="pcap file {} not found or not accessible".format(link.capture_file_path)) + await proxied_response.prepare(request) + async for data in response.content.iter_any(): + if not data: + break + await proxied_response.write(data) diff --git a/gns3server/handlers/api/controller/node_handler.py b/gns3server/handlers/api/controller/node_handler.py index 808390ab..db3ae4a6 100644 --- a/gns3server/handlers/api/controller/node_handler.py +++ b/gns3server/handlers/api/controller/node_handler.py @@ -46,30 +46,15 @@ class NodeHandler: description="Create a new node instance", input=NODE_CREATE_SCHEMA, output=NODE_OBJECT_SCHEMA) - def create(request, response): + async def create(request, response): controller = Controller.instance() compute = controller.get_compute(request.json.pop("compute_id")) - project = yield from controller.get_loaded_project(request.match_info["project_id"]) - node = yield from project.add_node(compute, request.json.pop("name"), request.json.pop("node_id", None), **request.json) + project = await controller.get_loaded_project(request.match_info["project_id"]) + node = await project.add_node(compute, request.json.pop("name"), request.json.pop("node_id", None), **request.json) response.set_status(201) response.json(node) - @Route.get( - r"/projects/{project_id}/nodes/{node_id}", - status_codes={ - 200: "Node found", - 400: "Invalid request", - 404: "Node doesn't exist" - }, - description="Update a node instance", - output=NODE_OBJECT_SCHEMA) - def get_node(request, response): - project = Controller.instance().get_project(request.match_info["project_id"]) - node = project.get_node(request.match_info["node_id"]) - response.set_status(200) - response.json(node) - @Route.get( r"/projects/{project_id}/nodes", parameters={ @@ -79,34 +64,11 @@ class NodeHandler: 200: "List of nodes returned", }, description="List nodes of a project") - def list_nodes(request, response): + async def list_nodes(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) response.json([v for v in project.nodes.values()]) - @Route.put( - r"/projects/{project_id}/nodes/{node_id}", - status_codes={ - 200: "Instance updated", - 400: "Invalid request", - 404: "Instance doesn't exist" - }, - description="Update a node instance", - input=NODE_UPDATE_SCHEMA, - output=NODE_OBJECT_SCHEMA) - def update(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - node = project.get_node(request.match_info["node_id"]) - - # Ignore these because we only use them when creating a node - request.json.pop("node_id", None) - request.json.pop("node_type", None) - request.json.pop("compute_id", None) - - yield from node.update(**request.json) - response.set_status(200) - response.json(node) - @Route.post( r"/projects/{project_id}/nodes/start", parameters={ @@ -119,10 +81,10 @@ class NodeHandler: }, description="Start all nodes belonging to the project", output=NODE_OBJECT_SCHEMA) - def start_all(request, response): + async def start_all(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - yield from project.start_all() + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + await project.start_all() response.set_status(204) @Route.post( @@ -137,10 +99,10 @@ class NodeHandler: }, description="Stop all nodes belonging to the project", output=NODE_OBJECT_SCHEMA) - def stop_all(request, response): + async def stop_all(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - yield from project.stop_all() + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + await project.stop_all() response.set_status(204) @Route.post( @@ -155,10 +117,10 @@ class NodeHandler: }, description="Suspend all nodes belonging to the project", output=NODE_OBJECT_SCHEMA) - def suspend_all(request, response): + async def suspend_all(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - yield from project.suspend_all() + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + await project.suspend_all() response.set_status(204) @Route.post( @@ -173,11 +135,67 @@ class NodeHandler: }, description="Reload all nodes belonging to the project", output=NODE_OBJECT_SCHEMA) - def reload_all(request, response): + async def reload_all(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - yield from project.stop_all() - yield from project.start_all() + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + await project.stop_all() + await project.start_all() + response.set_status(204) + + @Route.get( + r"/projects/{project_id}/nodes/{node_id}", + status_codes={ + 200: "Node found", + 400: "Invalid request", + 404: "Node doesn't exist" + }, + description="Get a node", + output=NODE_OBJECT_SCHEMA) + def get_node(request, response): + project = Controller.instance().get_project(request.match_info["project_id"]) + node = project.get_node(request.match_info["node_id"]) + response.set_status(200) + response.json(node) + + @Route.put( + r"/projects/{project_id}/nodes/{node_id}", + status_codes={ + 200: "Instance updated", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Update a node instance", + input=NODE_UPDATE_SCHEMA, + output=NODE_OBJECT_SCHEMA) + async def update(request, response): + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + node = project.get_node(request.match_info["node_id"]) + + # Ignore these because we only use them when creating a node + request.json.pop("node_id", None) + request.json.pop("node_type", None) + request.json.pop("compute_id", None) + + await node.update(**request.json) + response.set_status(200) + response.json(node) + + @Route.delete( + r"/projects/{project_id}/nodes/{node_id}", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 204: "Instance deleted", + 400: "Invalid request", + 404: "Instance doesn't exist", + 409: "Cannot delete locked node" + }, + description="Delete a node instance") + async def delete(request, response): + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + await project.delete_node(request.match_info["node_id"]) response.set_status(204) @Route.post( @@ -194,11 +212,11 @@ class NodeHandler: description="Duplicate a node instance", input=NODE_DUPLICATE_SCHEMA, output=NODE_OBJECT_SCHEMA) - def duplicate(request, response): + async def duplicate(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) node = project.get_node(request.match_info["node_id"]) - new_node = yield from project.duplicate_node( + new_node = await project.duplicate_node( node, request.json["x"], request.json["y"], @@ -213,19 +231,19 @@ class NodeHandler: "node_id": "Node UUID" }, status_codes={ - 204: "Instance started", + 200: "Instance started", 400: "Invalid request", 404: "Instance doesn't exist" }, description="Start a node instance", output=NODE_OBJECT_SCHEMA) - def start(request, response): + async def start(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) node = project.get_node(request.match_info["node_id"]) - yield from node.start() + await node.start(data=request.json) response.json(node) - response.set_status(201) + response.set_status(200) @Route.post( r"/projects/{project_id}/nodes/{node_id}/stop", @@ -234,19 +252,19 @@ class NodeHandler: "node_id": "Node UUID" }, status_codes={ - 204: "Instance stopped", + 200: "Instance stopped", 400: "Invalid request", 404: "Instance doesn't exist" }, description="Stop a node instance", output=NODE_OBJECT_SCHEMA) - def stop(request, response): + async def stop(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) node = project.get_node(request.match_info["node_id"]) - yield from node.stop() + await node.stop() response.json(node) - response.set_status(201) + response.set_status(200) @Route.post( r"/projects/{project_id}/nodes/{node_id}/suspend", @@ -255,19 +273,19 @@ class NodeHandler: "node_id": "Node UUID" }, status_codes={ - 204: "Instance suspended", + 200: "Instance suspended", 400: "Invalid request", 404: "Instance doesn't exist" }, description="Suspend a node instance", output=NODE_OBJECT_SCHEMA) - def suspend(request, response): + async def suspend(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) node = project.get_node(request.match_info["node_id"]) - yield from node.suspend() + await node.suspend() response.json(node) - response.set_status(201) + response.set_status(200) @Route.post( r"/projects/{project_id}/nodes/{node_id}/reload", @@ -276,36 +294,41 @@ class NodeHandler: "node_id": "Node UUID" }, status_codes={ - 204: "Instance reloaded", + 200: "Instance reloaded", 400: "Invalid request", 404: "Instance doesn't exist" }, description="Reload a node instance", output=NODE_OBJECT_SCHEMA) - def reload(request, response): + async def reload(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) node = project.get_node(request.match_info["node_id"]) - yield from node.reload() + await node.reload() response.json(node) - response.set_status(201) + response.set_status(200) - @Route.delete( - r"/projects/{project_id}/nodes/{node_id}", + @Route.get( + r"/projects/{project_id}/nodes/{node_id}/links", parameters={ "project_id": "Project UUID", "node_id": "Node UUID" }, status_codes={ - 204: "Instance deleted", + 200: "Links returned", 400: "Invalid request", 404: "Instance doesn't exist" }, - description="Delete a node instance") - def delete(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) - yield from project.delete_node(request.match_info["node_id"]) - response.set_status(204) + description="Return all the links connected to this node") + async def links(request, response): + + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + node = project.get_node(request.match_info["node_id"]) + links = [] + for link in node.links: + links.append(link.__json__()) + response.json(links) + response.set_status(200) @Route.get( r"/projects/{project_id}/nodes/{node_id}/dynamips/auto_idlepc", @@ -319,11 +342,11 @@ class NodeHandler: 404: "Instance doesn't exist" }, description="Compute the IDLE PC for a Dynamips node") - def auto_idlepc(request, response): + async def auto_idlepc(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) node = project.get_node(request.match_info["node_id"]) - idle = yield from node.dynamips_auto_idlepc() + idle = await node.dynamips_auto_idlepc() response.json(idle) response.set_status(200) @@ -339,14 +362,33 @@ class NodeHandler: 404: "Instance doesn't exist" }, description="Compute a list of potential idle PC for a node") - def idlepc_proposals(request, response): + async def idlepc_proposals(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) node = project.get_node(request.match_info["node_id"]) - idle = yield from node.dynamips_idlepc_proposals() + idle = await node.dynamips_idlepc_proposals() response.json(idle) response.set_status(200) + @Route.post( + r"/projects/{project_id}/nodes/{node_id}/resize_disk", + parameters={ + "project_id": "Project UUID", + "node_id": "Node UUID" + }, + status_codes={ + 201: "Disk image resized", + 400: "Invalid request", + 404: "Instance doesn't exist" + }, + description="Reload a node instance") + async def resize_disk(request, response): + + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) + node = project.get_node(request.match_info["node_id"]) + await node.post("/resize_disk", request.json) + response.set_status(201) + @Route.get( r"/projects/{project_id}/nodes/{node_id}/files/{path:.+}", parameters={ @@ -359,9 +401,9 @@ class NodeHandler: 404: "Instance doesn't exist" }, description="Get a file in the node directory") - def get_file(request, response): + async def get_file(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) node = project.get_node(request.match_info["node_id"]) path = request.match_info["path"] path = force_unix_path(path) @@ -374,14 +416,13 @@ class NodeHandler: node_type = node.node_type path = "/project-files/{}/{}/{}".format(node_type, node.id, path) - res = yield from node.compute.http_query("GET", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), timeout=None, raw=True) + res = await node.compute.http_query("GET", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), timeout=None, raw=True) response.set_status(200) response.content_type = "application/octet-stream" response.enable_chunked_encoding() - yield from response.prepare(request) - - response.write(res.body) - yield from response.write_eof() + await response.prepare(request) + await response.write(res.body) + # await response.write_eof() #FIXME: shound't be needed anymore @Route.post( r"/projects/{project_id}/nodes/{node_id}/files/{path:.+}", @@ -396,9 +437,9 @@ class NodeHandler: }, raw=True, description="Write a file in the node directory") - def post_file(request, response): + async def post_file(request, response): - project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"]) + project = await Controller.instance().get_loaded_project(request.match_info["project_id"]) node = project.get_node(request.match_info["node_id"]) path = request.match_info["path"] path = force_unix_path(path) @@ -409,8 +450,6 @@ class NodeHandler: node_type = node.node_type path = "/project-files/{}/{}/{}".format(node_type, node.id, path) - - data = yield from request.content.read() - - yield from node.compute.http_query("POST", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), data=data, timeout=None, raw=True) + data = await request.content.read() #FIXME: are we handling timeout or large files correctly? + await node.compute.http_query("POST", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), data=data, timeout=None, raw=True) response.set_status(201) diff --git a/gns3server/handlers/api/controller/notification_handler.py b/gns3server/handlers/api/controller/notification_handler.py new file mode 100644 index 00000000..bf41ad20 --- /dev/null +++ b/gns3server/handlers/api/controller/notification_handler.py @@ -0,0 +1,87 @@ +# -*- 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 asyncio +import aiohttp +from aiohttp.web import WebSocketResponse +from gns3server.web.route import Route +from gns3server.controller import Controller + +import logging +log = logging.getLogger(__name__) + + +async def process_websocket(ws): + """ + Process ping / pong and close message + """ + try: + await ws.receive() + except aiohttp.WSServerHandshakeError: + pass + + +class NotificationHandler: + + @Route.get( + r"/notifications", + description="Receive notifications about the controller", + status_codes={ + 200: "End of stream" + }) + async def notification(request, response): + + controller = Controller.instance() + response.content_type = "application/json" + response.set_status(200) + response.enable_chunked_encoding() + + await response.prepare(request) + with controller.notification.controller_queue() as queue: + while True: + msg = await queue.get_json(5) + await response.write(("{}\n".format(msg)).encode("utf-8")) + + @Route.get( + r"/notifications/ws", + description="Receive notifications about controller from a Websocket", + status_codes={ + 200: "End of stream" + }) + async def notification_ws(request, response): + + controller = Controller.instance() + ws = aiohttp.web.WebSocketResponse() + await ws.prepare(request) + + request.app['websockets'].add(ws) + asyncio.ensure_future(process_websocket(ws)) + log.info("New client has connected to controller WebSocket") + try: + with controller.notification.controller_queue() as queue: + while True: + notification = await queue.get_json(5) + if ws.closed: + break + await ws.send_str(notification) + finally: + log.info("Client has disconnected from controller WebSocket") + if not ws.closed: + await ws.close() + request.app['websockets'].discard(ws) + + return ws diff --git a/gns3server/handlers/api/controller/project_handler.py b/gns3server/handlers/api/controller/project_handler.py index 8d7337dd..e27c43ec 100644 --- a/gns3server/handlers/api/controller/project_handler.py +++ b/gns3server/handlers/api/controller/project_handler.py @@ -19,11 +19,15 @@ import os import aiohttp import asyncio import tempfile +import zipfile +import aiofiles +import time from gns3server.web.route import Route from gns3server.controller import Controller from gns3server.controller.import_project import import_project from gns3server.controller.export_project import export_project +from gns3server.utils.asyncio import aiozipstream from gns3server.config import Config @@ -38,16 +42,17 @@ import logging log = logging.getLogger() -@asyncio.coroutine -def process_websocket(ws): +async def process_websocket(ws): """ Process ping / pong and close message """ try: - yield from ws.receive() + await ws.receive() except aiohttp.WSServerHandshakeError: pass +CHUNK_SIZE = 1024 * 8 # 8KB + class ProjectHandler: @@ -60,10 +65,10 @@ class ProjectHandler: }, output=PROJECT_OBJECT_SCHEMA, input=PROJECT_CREATE_SCHEMA) - def create_project(request, response): + async def create_project(request, response): controller = Controller.instance() - project = yield from controller.add_project(**request.json) + project = await controller.add_project(**request.json) response.set_status(201) response.json(project) @@ -102,16 +107,49 @@ class ProjectHandler: description="Update a project instance", input=PROJECT_UPDATE_SCHEMA, output=PROJECT_OBJECT_SCHEMA) - def update(request, response): + async def update(request, response): project = Controller.instance().get_project(request.match_info["project_id"]) # Ignore these because we only use them when creating a project request.json.pop("project_id", None) - yield from project.update(**request.json) + await project.update(**request.json) response.set_status(200) response.json(project) + @Route.delete( + r"/projects/{project_id}", + description="Delete a project from disk", + parameters={ + "project_id": "Project UUID", + }, + status_codes={ + 204: "Changes have been written on disk", + 404: "The project doesn't exist" + }) + async def delete(request, response): + + controller = Controller.instance() + project = controller.get_project(request.match_info["project_id"]) + await project.delete() + controller.remove_project(project) + response.set_status(204) + + @Route.get( + r"/projects/{project_id}/stats", + description="Get a project statistics", + parameters={ + "project_id": "Project UUID", + }, + status_codes={ + 200: "Project statistics returned", + 404: "The project doesn't exist" + }) + def get(request, response): + controller = Controller.instance() + project = controller.get_project(request.match_info["project_id"]) + response.json(project.stats()) + @Route.post( r"/projects/{project_id}/close", description="Close a project", @@ -123,11 +161,11 @@ class ProjectHandler: 404: "The project doesn't exist" }, output=PROJECT_OBJECT_SCHEMA) - def close(request, response): + async def close(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - yield from project.close() + await project.close() response.set_status(201) response.json(project) @@ -142,11 +180,11 @@ class ProjectHandler: 404: "The project doesn't exist" }, output=PROJECT_OBJECT_SCHEMA) - def open(request, response): + async def open(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - yield from project.open() + await project.open() response.set_status(201) response.json(project) @@ -162,7 +200,7 @@ class ProjectHandler: }, input=PROJECT_LOAD_SCHEMA, output=PROJECT_OBJECT_SCHEMA) - def load(request, response): + async def load(request, response): controller = Controller.instance() config = Config.instance() @@ -170,28 +208,10 @@ class ProjectHandler: log.error("Can't load the project the server is not started with --local") response.set_status(403) return - project = yield from controller.load_project(request.json.get("path"),) + project = await controller.load_project(request.json.get("path"),) response.set_status(201) response.json(project) - @Route.delete( - r"/projects/{project_id}", - description="Delete a project from disk", - parameters={ - "project_id": "Project UUID", - }, - status_codes={ - 204: "Changes have been written on disk", - 404: "The project doesn't exist" - }) - def delete(request, response): - - controller = Controller.instance() - project = controller.get_project(request.match_info["project_id"]) - yield from project.delete() - controller.remove_project(project) - response.set_status(204) - @Route.get( r"/projects/{project_id}/notifications", description="Receive notifications about projects", @@ -202,31 +222,31 @@ class ProjectHandler: 200: "End of stream", 404: "The project doesn't exist" }) - def notification(request, response): + async def notification(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - response.content_type = "application/json" response.set_status(200) response.enable_chunked_encoding() + await response.prepare(request) + log.info("New client has connected to the notification stream for project ID '{}' (HTTP long-polling method)".format(project.id)) - yield from response.prepare(request) - with controller.notification.queue(project) as queue: - while True: - try: - msg = yield from queue.get_json(5) - response.write(("{}\n".format(msg)).encode("utf-8")) - except asyncio.futures.CancelledError as e: - break - yield from response.drain() + try: + with controller.notification.project_queue(project.id) as queue: + while True: + msg = await queue.get_json(5) + await response.write(("{}\n".format(msg)).encode("utf-8")) + finally: + log.info("Client has disconnected from notification for project ID '{}' (HTTP long-polling method)".format(project.id)) + if project.auto_close: + # To avoid trouble with client connecting disconnecting we sleep few seconds before checking + # if someone else is not connected + await asyncio.sleep(5) + if not controller.notification.project_has_listeners(project.id): + log.info("Project '{}' is automatically closing due to no client listening".format(project.id)) + await project.close() - if project.auto_close: - # To avoid trouble with client connecting disconnecting we sleep few seconds before checking - # if someone else is not connected - yield from asyncio.sleep(5) - if not controller.notification.project_has_listeners(project): - yield from project.close() @Route.get( r"/projects/{project_id}/notifications/ws", @@ -238,32 +258,35 @@ class ProjectHandler: 200: "End of stream", 404: "The project doesn't exist" }) - def notification_ws(request, response): + async def notification_ws(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - ws = aiohttp.web.WebSocketResponse() - yield from ws.prepare(request) + await ws.prepare(request) - asyncio.async(process_websocket(ws)) - - with controller.notification.queue(project) as queue: - while True: - try: - notification = yield from queue.get_json(5) - except asyncio.futures.CancelledError as e: - break - if ws.closed: - break - ws.send_str(notification) - - if project.auto_close: - # To avoid trouble with client connecting disconnecting we sleep few seconds before checking - # if someone else is not connected - yield from asyncio.sleep(5) - if not controller.notification.project_has_listeners(project): - yield from project.close() + request.app['websockets'].add(ws) + asyncio.ensure_future(process_websocket(ws)) + log.info("New client has connected to the notification stream for project ID '{}' (WebSocket method)".format(project.id)) + try: + with controller.notification.project_queue(project.id) as queue: + while True: + notification = await queue.get_json(5) + if ws.closed: + break + await ws.send_str(notification) + finally: + log.info("Client has disconnected from notification stream for project ID '{}' (WebSocket method)".format(project.id)) + if not ws.closed: + await ws.close() + request.app['websockets'].discard(ws) + if project.auto_close: + # To avoid trouble with client connecting disconnecting we sleep few seconds before checking + # if someone else is not connected + await asyncio.sleep(5) + if not controller.notification.project_has_listeners(project.id): + log.info("Project '{}' is automatically closing due to no client listening".format(project.id)) + await project.close() return ws @@ -278,32 +301,50 @@ class ProjectHandler: 200: "File returned", 404: "The project doesn't exist" }) - def export_project(request, response): + async def export_project(request, response): controller = Controller.instance() - project = yield from controller.get_loaded_project(request.match_info["project_id"]) + project = await controller.get_loaded_project(request.match_info["project_id"]) + if request.query.get("include_snapshots", "no").lower() == "yes": + include_snapshots = True + else: + include_snapshots = False + if request.query.get("include_images", "no").lower() == "yes": + include_images = True + else: + include_images = False + compression_query = request.query.get("compression", "zip").lower() + if compression_query == "zip": + compression = zipfile.ZIP_DEFLATED + elif compression_query == "none": + compression = zipfile.ZIP_STORED + elif compression_query == "bzip2": + compression = zipfile.ZIP_BZIP2 + elif compression_query == "lzma": + compression = zipfile.ZIP_LZMA try: + begin = time.time() with tempfile.TemporaryDirectory() as tmp_dir: - datas = yield from export_project( - project, tmp_dir, - include_images=bool(int(request.query.get("include_images", "0")))) - # We need to do that now because export could failed and raise an HTTP error - # that why response start need to be the later possible - response.content_type = 'application/gns3project' - response.headers['CONTENT-DISPOSITION'] = 'attachment; filename="{}.gns3project"'.format(project.name) - response.enable_chunked_encoding() - yield from response.prepare(request) + with aiozipstream.ZipFile(compression=compression) as zstream: + await export_project(zstream, project, tmp_dir, include_snapshots=include_snapshots, include_images=include_images) - for data in datas: - response.write(data) - yield from response.drain() + # We need to do that now because export could failed and raise an HTTP error + # that why response start need to be the later possible + response.content_type = 'application/gns3project' + response.headers['CONTENT-DISPOSITION'] = 'attachment; filename="{}.gns3project"'.format(project.name) + response.enable_chunked_encoding() + await response.prepare(request) + + async for chunk in zstream: + await response.write(chunk) + + log.info("Project '{}' exported in {:.4f} seconds".format(project.name, time.time() - begin)) - yield from response.write_eof() # Will be raise if you have no space left or permission issue on your temporary directory # RuntimeError: something was wrong during the zip process - except (OSError, RuntimeError) as e: - raise aiohttp.web.HTTPNotFound(text="Can't export project: {}".format(str(e))) + except (ValueError, OSError, RuntimeError) as e: + raise aiohttp.web.HTTPNotFound(text="Cannot export project: {}".format(str(e))) @Route.post( r"/projects/{project_id}/import", @@ -317,7 +358,7 @@ class ProjectHandler: 200: "Project imported", 403: "Forbidden to import project" }) - def import_project(request, response): + async def import_project(request, response): controller = Controller.instance() @@ -331,18 +372,23 @@ class ProjectHandler: # We write the content to a temporary location and after we extract it all. # It could be more optimal to stream this but it is not implemented in Python. - # Spooled means the file is temporary kept in memory until max_size is reached try: - with tempfile.SpooledTemporaryFile(max_size=10000) as temp: - while True: - packet = yield from request.content.read(512) - if not packet: - break - temp.write(packet) - project = yield from import_project(controller, request.match_info["project_id"], temp, location=path, name=name) + begin = time.time() + with tempfile.TemporaryDirectory() as tmpdir: + temp_project_path = os.path.join(tmpdir, "project.zip") + async with aiofiles.open(temp_project_path, 'wb') as f: + while True: + chunk = await request.content.read(CHUNK_SIZE) + if not chunk: + break + await f.write(chunk) + + with open(temp_project_path, "rb") as f: + project = await import_project(controller, request.match_info["project_id"], f, location=path, name=name) + + log.info("Project '{}' imported in {:.4f} seconds".format(project.name, time.time() - begin)) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not import the project: {}".format(e)) - response.json(project) response.set_status(201) @@ -359,10 +405,10 @@ class ProjectHandler: 403: "The server is not the local server", 404: "The project doesn't exist" }) - def duplicate(request, response): + async def duplicate(request, response): controller = Controller.instance() - project = yield from controller.get_loaded_project(request.match_info["project_id"]) + project = await controller.get_loaded_project(request.match_info["project_id"]) if request.json.get("path"): config = Config.instance() @@ -373,7 +419,7 @@ class ProjectHandler: else: location = None - new_project = yield from project.duplicate(name=request.json.get("name"), location=location) + new_project = await project.duplicate(name=request.json.get("name"), location=location) response.json(new_project) response.set_status(201) @@ -389,10 +435,10 @@ class ProjectHandler: 403: "Permission denied", 404: "The file doesn't exist" }) - def get_file(request, response): + async def get_file(request, response): controller = Controller.instance() - project = yield from controller.get_loaded_project(request.match_info["project_id"]) + project = await controller.get_loaded_project(request.match_info["project_id"]) path = request.match_info["path"] path = os.path.normpath(path).strip('/') @@ -401,23 +447,7 @@ class ProjectHandler: raise aiohttp.web.HTTPForbidden() path = os.path.join(project.path, path) - response.content_type = "application/octet-stream" - response.set_status(200) - response.enable_chunked_encoding() - - try: - with open(path, "rb") as f: - yield from response.prepare(request) - while True: - data = f.read(4096) - if not data: - break - yield from response.write(data) - - except FileNotFoundError: - raise aiohttp.web.HTTPNotFound() - except PermissionError: - raise aiohttp.web.HTTPForbidden() + await response.stream_file(path) @Route.post( r"/projects/{project_id}/files/{path:.+}", @@ -431,10 +461,10 @@ class ProjectHandler: 403: "Permission denied", 404: "The path doesn't exist" }) - def write_file(request, response): + async def write_file(request, response): controller = Controller.instance() - project = yield from controller.get_loaded_project(request.match_info["project_id"]) + project = await controller.get_loaded_project(request.match_info["project_id"]) path = request.match_info["path"] path = os.path.normpath(path).strip("/") @@ -446,12 +476,15 @@ class ProjectHandler: response.set_status(200) try: - with open(path, 'wb+') as f: + async with aiofiles.open(path, 'wb+') as f: while True: - packet = yield from request.content.read(512) - if not packet: + try: + chunk = await request.content.read(CHUNK_SIZE) + except asyncio.TimeoutError: + raise aiohttp.web.HTTPRequestTimeout(text="Timeout when writing to file '{}'".format(path)) + if not chunk: break - f.write(packet) + await f.write(chunk) except FileNotFoundError: raise aiohttp.web.HTTPNotFound() except PermissionError: diff --git a/gns3server/handlers/api/controller/server_handler.py b/gns3server/handlers/api/controller/server_handler.py index 7de4a66a..ae1160c4 100644 --- a/gns3server/handlers/api/controller/server_handler.py +++ b/gns3server/handlers/api/controller/server_handler.py @@ -19,6 +19,7 @@ from gns3server.web.route import Route from gns3server.config import Config from gns3server.controller import Controller from gns3server.schemas.version import VERSION_SCHEMA +from gns3server.schemas.iou_license import IOU_LICENSE_SETTINGS_SCHEMA from gns3server.version import __version__ from aiohttp.web import HTTPConflict, HTTPForbidden @@ -43,7 +44,7 @@ class ServerHandler: 201: "Server is shutting down", 403: "Server shutdown refused" }) - def shutdown(request, response): + async def shutdown(request, response): config = Config.instance() if config.get_section_config("Server").getboolean("local", False) is False: @@ -57,10 +58,10 @@ class ServerHandler: tasks = [] for project in projects: - tasks.append(asyncio.async(project.close())) + tasks.append(asyncio.ensure_future(project.close())) if tasks: - done, _ = yield from asyncio.wait(tasks) + done, _ = await asyncio.wait(tasks) for future in done: try: future.result() @@ -71,7 +72,10 @@ class ServerHandler: # then shutdown the server itself from gns3server.web.web_server import WebServer server = WebServer.instance() - asyncio.async(server.shutdown_server()) + try: + asyncio.ensure_future(server.shutdown_server()) + except asyncio.CancelledError: + pass response.set_status(201) @Route.get( @@ -99,45 +103,40 @@ class ServerHandler: response.json({"version": __version__}) @Route.get( - r"/settings", - description="Retrieve gui settings from the server. Temporary will we removed in later release") - def read_settings(request, response): - - settings = None - while True: - # The init of the server could take some times - # we ensure settings are loaded before returning them - settings = Controller.instance().settings - if settings is not None: - break - yield from asyncio.sleep(0.5) - response.json(settings) - - @Route.post( - r"/settings", - description="Write gui settings on the server. Temporary will we removed in later releas", + r"/iou_license", + description="Get the IOU license settings", status_codes={ - 201: "Writed" + 200: "IOU license settings returned" + }, + output_schema=IOU_LICENSE_SETTINGS_SCHEMA) + def show(request, response): + + response.json(Controller.instance().iou_license) + + @Route.put( + r"/iou_license", + description="Update the IOU license settings", + input_schema=IOU_LICENSE_SETTINGS_SCHEMA, + output_schema=IOU_LICENSE_SETTINGS_SCHEMA, + status_codes={ + 201: "IOU license settings updated" }) - def write_settings(request, response): - controller = Controller.instance() - if controller.settings is None: # Server is not loaded ignore settings update to prevent buggy client sync issue - return - controller.settings = request.json - try: - controller.save() - except (OSError, PermissionError) as e: - raise HTTPConflict(text="Can't save the settings {}".format(str(e))) - response.json(controller.settings) + async def update(request, response): + + controller = Controller().instance() + iou_license = controller.iou_license + iou_license.update(request.json) + controller.save() + response.json(iou_license) response.set_status(201) @Route.post( r"/debug", - description="Dump debug informations to disk (debug directory in config directory). Work only for local server", + description="Dump debug information to disk (debug directory in config directory). Work only for local server", status_codes={ - 201: "Writed" + 201: "Written" }) - def debug(request, response): + async def debug(request, response): config = Config.instance() if config.get_section_config("Server").getboolean("local", False) is False: @@ -152,7 +151,7 @@ class ServerHandler: f.write(ServerHandler._getDebugData()) except Exception as e: # If something is wrong we log the info to the log and we hope the log will be include correctly to the debug export - log.error("Could not export debug informations {}".format(e), exc_info=1) + log.error("Could not export debug information {}".format(e), exc_info=1) try: if Controller.instance().gns3vm.engine == "vmware": @@ -165,7 +164,7 @@ class ServerHandler: for compute in list(Controller.instance().computes.values()): try: - r = yield from compute.get("/debug", raw=True) + r = await compute.get("/debug", raw=True) data = r.body.decode("utf-8") except Exception as e: data = str(e) diff --git a/gns3server/handlers/api/controller/snapshot_handler.py b/gns3server/handlers/api/controller/snapshot_handler.py index 81ae8113..513bbe3e 100644 --- a/gns3server/handlers/api/controller/snapshot_handler.py +++ b/gns3server/handlers/api/controller/snapshot_handler.py @@ -43,10 +43,10 @@ class SnapshotHandler: 201: "Snasphot created", 404: "The project doesn't exist" }) - def create(request, response): + async def create(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - snapshot = yield from project.snapshot(request.json["name"]) + snapshot = await project.snapshot(request.json["name"]) response.json(snapshot) response.set_status(201) @@ -77,11 +77,11 @@ class SnapshotHandler: 204: "Changes have been written on disk", 404: "The project or snapshot doesn't exist" }) - def delete(request, response): + async def delete(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) - yield from project.delete_snapshot(request.match_info["snapshot_id"]) + await project.delete_snapshot(request.match_info["snapshot_id"]) response.set_status(204) @Route.post( @@ -96,11 +96,11 @@ class SnapshotHandler: 201: "The snapshot has been restored", 404: "The project or snapshot doesn't exist" }) - def restore(request, response): + async def restore(request, response): controller = Controller.instance() project = controller.get_project(request.match_info["project_id"]) snapshot = project.get_snapshot(request.match_info["snapshot_id"]) - project = yield from snapshot.restore() + project = await snapshot.restore() response.set_status(201) response.json(project) diff --git a/gns3server/handlers/api/controller/symbol_handler.py b/gns3server/handlers/api/controller/symbol_handler.py index b0c4600c..a8a23e82 100644 --- a/gns3server/handlers/api/controller/symbol_handler.py +++ b/gns3server/handlers/api/controller/symbol_handler.py @@ -17,6 +17,8 @@ import os import aiohttp +import asyncio + from gns3server.web.route import Route from gns3server.controller import Controller @@ -26,7 +28,9 @@ log = logging.getLogger(__name__) class SymbolHandler: - """API entry points for symbols management.""" + """ + API entry points for symbols management. + """ @Route.get( r"/symbols", @@ -45,33 +49,65 @@ class SymbolHandler: status_codes={ 200: "Symbol returned" }) - def raw(request, response): + async def raw(request, response): controller = Controller.instance() try: - yield from response.file(controller.symbols.get_path(request.match_info["symbol_id"])) - except (KeyError, FileNotFoundError, PermissionError): + await response.stream_file(controller.symbols.get_path(request.match_info["symbol_id"])) + except (KeyError, OSError) as e: + log.warning("Could not get symbol file: {}".format(e)) response.set_status(404) @Route.post( r"/symbols/{symbol_id:.+}/raw", description="Write the symbol file", status_codes={ - 200: "Symbol returned" + 200: "Symbol written" }, raw=True) - def upload(request, response): + async def upload(request, response): controller = Controller.instance() path = os.path.join(controller.symbols.symbols_path(), os.path.basename(request.match_info["symbol_id"])) try: - with open(path, 'wb') as f: + with open(path, "wb") as f: while True: - packet = yield from request.content.read(512) - if not packet: + try: + chunk = await request.content.read(1024) + except asyncio.TimeoutError: + raise aiohttp.web.HTTPRequestTimeout(text="Timeout when writing to symbol '{}'".format(path)) + if not chunk: break - f.write(packet) - except OSError as e: + f.write(chunk) + except (UnicodeEncodeError, OSError) as e: raise aiohttp.web.HTTPConflict(text="Could not write symbol file '{}': {}".format(path, e)) + # Reset the symbol list controller.symbols.list() response.set_status(204) + + @Route.get( + r"/default_symbols", + description="List of default symbols", + status_codes={ + 200: "Default symbols list returned" + }) + def list_default_symbols(request, response): + + controller = Controller.instance() + response.json(controller.symbols.default_symbols()) + + # @Route.post( + # r"/symbol_theme", + # description="Create a new symbol theme", + # status_codes={ + # 201: "Appliance created", + # 400: "Invalid request" + # }, + # input=APPLIANCE_CREATE_SCHEMA, + # output=APPLIANCE_OBJECT_SCHEMA) + # def create(request, response): + # + # controller = Controller.instance() + # appliance = controller.add_appliance(request.json) + # response.set_status(201) + # response.json(appliance) \ No newline at end of file diff --git a/gns3server/handlers/api/controller/template_handler.py b/gns3server/handlers/api/controller/template_handler.py new file mode 100644 index 00000000..0f88efb3 --- /dev/null +++ b/gns3server/handlers/api/controller/template_handler.py @@ -0,0 +1,174 @@ +# -*- 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 . + +from gns3server.web.route import Route +from gns3server.controller import Controller +from gns3server.schemas.node import NODE_OBJECT_SCHEMA +from gns3server.schemas.template import TEMPLATE_USAGE_SCHEMA + +import hashlib +import json + +from gns3server.schemas.template import ( + TEMPLATE_OBJECT_SCHEMA, + TEMPLATE_UPDATE_SCHEMA, + TEMPLATE_CREATE_SCHEMA +) + +import logging +log = logging.getLogger(__name__) + + +class TemplateHandler: + """ + API entry points for template management. + """ + + @Route.post( + r"/templates", + description="Create a new template", + status_codes={ + 201: "Template created", + 400: "Invalid request" + }, + input=TEMPLATE_CREATE_SCHEMA, + output=TEMPLATE_OBJECT_SCHEMA) + def create(request, response): + + controller = Controller.instance() + template = controller.template_manager.add_template(request.json) + # Reset the symbol list + controller.symbols.list() + response.set_status(201) + response.json(template) + + @Route.get( + r"/templates/{template_id}", + status_codes={ + 200: "Template found", + 400: "Invalid request", + 404: "Template doesn't exist" + }, + description="Get an template", + output=TEMPLATE_OBJECT_SCHEMA) + def get(request, response): + + request_etag = request.headers.get("If-None-Match", "") + controller = Controller.instance() + template = controller.template_manager.get_template(request.match_info["template_id"]) + data = json.dumps(template.__json__()) + template_etag = '"' + hashlib.md5(data.encode()).hexdigest() + '"' + if template_etag == request_etag: + response.set_status(304) + else: + response.headers["ETag"] = template_etag + response.set_status(200) + response.json(template) + + @Route.put( + r"/templates/{template_id}", + status_codes={ + 200: "Template updated", + 400: "Invalid request", + 404: "Template doesn't exist" + }, + description="Update an template", + input=TEMPLATE_UPDATE_SCHEMA, + output=TEMPLATE_OBJECT_SCHEMA) + def update(request, response): + + controller = Controller.instance() + template = controller.template_manager.get_template(request.match_info["template_id"]) + # Ignore these because we only use them when creating a template + request.json.pop("template_id", None) + request.json.pop("template_type", None) + request.json.pop("compute_id", None) + request.json.pop("builtin", None) + template.update(**request.json) + response.set_status(200) + response.json(template) + + @Route.delete( + r"/templates/{template_id}", + parameters={ + "template_id": "template UUID" + }, + status_codes={ + 204: "Template deleted", + 400: "Invalid request", + 404: "Template doesn't exist" + }, + description="Delete an template") + def delete(request, response): + + controller = Controller.instance() + controller.template_manager.delete_template(request.match_info["template_id"]) + response.set_status(204) + + @Route.get( + r"/templates", + description="List of template", + status_codes={ + 200: "Template list returned" + }) + def list(request, response): + + controller = Controller.instance() + response.json([c for c in controller.template_manager.templates.values()]) + + @Route.post( + r"/templates/{template_id}/duplicate", + parameters={ + "template_id": "Template UUID" + }, + status_codes={ + 201: "Template duplicated", + 400: "Invalid request", + 404: "Template doesn't exist" + }, + description="Duplicate an template", + output=TEMPLATE_OBJECT_SCHEMA) + async def duplicate(request, response): + + controller = Controller.instance() + template = controller.template_manager.duplicate_template(request.match_info["template_id"]) + response.set_status(201) + response.json(template) + + @Route.post( + r"/projects/{project_id}/templates/{template_id}", + description="Create a node from a template", + parameters={ + "project_id": "Project UUID", + "template_id": "Template UUID" + }, + status_codes={ + 201: "Node created", + 404: "The project or template doesn't exist" + }, + input=TEMPLATE_USAGE_SCHEMA, + output=NODE_OBJECT_SCHEMA) + async def create_node_from_template(request, response): + + controller = Controller.instance() + project = controller.get_project(request.match_info["project_id"]) + node = await project.add_node_from_template(request.match_info["template_id"], + x=request.json["x"], + y=request.json["y"], + compute_id=request.json.get("compute_id")) + response.set_status(201) + response.json(node) diff --git a/gns3server/handlers/index_handler.py b/gns3server/handlers/index_handler.py index 082e13ba..364bf902 100644 --- a/gns3server/handlers/index_handler.py +++ b/gns3server/handlers/index_handler.py @@ -14,12 +14,15 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os +import aiohttp from gns3server.web.route import Route from gns3server.controller import Controller from gns3server.compute.port_manager import PortManager from gns3server.compute.project_manager import ProjectManager from gns3server.version import __version__ +from gns3server.utils.get_resource import get_resource class IndexHandler: @@ -40,7 +43,7 @@ class IndexHandler: @Route.get( r"/compute", - description="Resources used by the GNS3 compute servers" + description="Resources used by the GNS3 computes" ) def compute(request, response): response.template("compute.html", @@ -64,6 +67,39 @@ class IndexHandler: response.template("project.html", project=controller.get_project(request.match_info["project_id"])) + @Route.get( + r"/static/web-ui/{filename:.+}", + parameters={ + "filename": "Static filename" + }, + status_codes={ + 200: "Static file returned", + 404: "Static cannot be found", + }, + raw=True, + description="Get static resource") + async def webui(request, response): + filename = request.match_info["filename"] + filename = os.path.normpath(filename).strip("/") + filename = os.path.join('static', 'web-ui', filename) + + # Raise error if user try to escape + if filename[0] == ".": + raise aiohttp.web.HTTPForbidden() + + static = get_resource(filename) + + if static is None or not os.path.exists(static): + static = get_resource(os.path.join('static', 'web-ui', 'index.html')) + + # guesstype prefers to have text/html type than application/javascript + # which results with warnings in Firefox 66 on Windows + # Ref. gns3-server#1559 + _, ext = os.path.splitext(static) + mimetype = ext == '.js' and 'application/javascript' or None + + await response.stream_file(static, status=200, set_content_type=mimetype) + @Route.get( r"/v1/version", description="Old 1.0 API" diff --git a/gns3server/notification_queue.py b/gns3server/notification_queue.py index 2412d5cb..889e49b9 100644 --- a/gns3server/notification_queue.py +++ b/gns3server/notification_queue.py @@ -30,8 +30,7 @@ class NotificationQueue(asyncio.Queue): super().__init__() self._first = True - @asyncio.coroutine - def get(self, timeout): + async def get(self, timeout): """ When timeout is expire we send a ping notification with server information """ @@ -42,17 +41,16 @@ class NotificationQueue(asyncio.Queue): return ("ping", PingStats.get(), {}) try: - (action, msg, kwargs) = yield from asyncio.wait_for(super().get(), timeout) + (action, msg, kwargs) = await asyncio.wait_for(super().get(), timeout) except asyncio.futures.TimeoutError: return ("ping", PingStats.get(), {}) return (action, msg, kwargs) - @asyncio.coroutine - def get_json(self, timeout): + async def get_json(self, timeout): """ Get a message as a JSON """ - (action, msg, kwargs) = yield from self.get(timeout) + (action, msg, kwargs) = await self.get(timeout) if hasattr(msg, "__json__"): msg = {"action": action, "event": msg.__json__()} else: diff --git a/gns3server/run.py b/gns3server/run.py index 0d23b124..f1768402 100644 --- a/gns3server/run.py +++ b/gns3server/run.py @@ -91,7 +91,6 @@ def parse_arguments(argv): parser.add_argument("--host", help="run on the given host/IP address") parser.add_argument("--port", help="run on the given port", type=int) parser.add_argument("--ssl", action="store_true", help="run in SSL mode") - parser.add_argument("--no-ubridge", action="store_false", help="do not use ubridge to handle node connections") parser.add_argument("--config", help="Configuration file") parser.add_argument("--certfile", help="SSL cert file") parser.add_argument("--certkey", help="SSL key file") @@ -183,7 +182,7 @@ def kill_ghosts(): """ Kill process from previous GNS3 session """ - detect_process = ["vpcs", "ubridge", "dynamips"] + detect_process = ["vpcs", "traceng", "ubridge", "dynamips"] for proc in psutil.process_iter(): try: name = proc.name().lower().split(".")[0] @@ -223,9 +222,9 @@ def run(): if server_config.getboolean("local"): log.warning("Local mode is enabled. Beware, clients will have full control on your filesystem") - # we only support Python 3 version >= 3.4 - if sys.version_info < (3, 4): - raise SystemExit("Python 3.4 or higher is required") + # we only support Python 3 version >= 3.5 + if sys.version_info < (3, 5, 3): + raise SystemExit("Python 3.5.3 or higher is required") user_log.info("Running with Python {major}.{minor}.{micro} and has PID {pid}".format( major=sys.version_info[0], minor=sys.version_info[1], diff --git a/gns3server/schemas/cloud.py b/gns3server/schemas/cloud.py index aaf58467..190a5e6d 100644 --- a/gns3server/schemas/cloud.py +++ b/gns3server/schemas/cloud.py @@ -62,6 +62,24 @@ CLOUD_CREATE_SCHEMA = { "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"} ] }, + "remote_console_host": { + "description": "Remote console host or IP", + "type": ["string"] + }, + "remote_console_port": { + "description": "Console TCP port", + "minimum": 1, + "maximum": 65535, + "type": ["integer", "null"] + }, + "remote_console_type": { + "description": "Console type", + "enum": ["telnet", "vnc", "spice", "http", "https", "none"] + }, + "remote_console_http_path": { + "description": "Path of the remote web interface", + "type": "string", + }, "ports_mapping": { "type": "array", "items": [ @@ -109,6 +127,24 @@ CLOUD_OBJECT_SCHEMA = { "maxLength": 36, "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" }, + "remote_console_host": { + "description": "Remote console host or IP", + "type": ["string"] + }, + "remote_console_port": { + "description": "Console TCP port", + "minimum": 1, + "maximum": 65535, + "type": ["integer", "null"] + }, + "remote_console_type": { + "description": "Console type", + "enum": ["telnet", "vnc", "spice", "http", "https", "none"] + }, + "remote_console_http_path": { + "description": "Path of the remote web interface", + "type": "string", + }, "ports_mapping": { "type": "array", "items": [ diff --git a/gns3server/schemas/cloud_template.py b/gns3server/schemas/cloud_template.py new file mode 100644 index 00000000..43d6c4ab --- /dev/null +++ b/gns3server/schemas/cloud_template.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES +from .port import PORT_OBJECT_SCHEMA + + +CLOUD_TEMPLATE_PROPERTIES = { + "ports_mapping": { + "type": "array", + "items": [PORT_OBJECT_SCHEMA] + }, + "remote_console_host": { + "description": "Remote console host or IP", + "type": ["string"], + "minLength": 1 + }, + "remote_console_port": { + "description": "Console TCP port", + "minimum": 1, + "maximum": 65535, + "type": "integer" + }, + "remote_console_type": { + "description": "Console type", + "enum": ["telnet", "vnc", "spice", "http", "https", "none"] + }, + "remote_console_http_path": { + "description": "Path of the remote web interface", + "type": "string", + "minLength": 1 + }, +} + +CLOUD_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +CLOUD_TEMPLATE_PROPERTIES["category"]["default"] = "guest" +CLOUD_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "Cloud{0}" +CLOUD_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/cloud.svg" + +CLOUD_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A cloud template object", + "type": "object", + "properties": CLOUD_TEMPLATE_PROPERTIES, + "additionalProperties": False +} diff --git a/gns3server/schemas/compute.py b/gns3server/schemas/compute.py index 2e8d08bc..12716dad 100644 --- a/gns3server/schemas/compute.py +++ b/gns3server/schemas/compute.py @@ -89,7 +89,7 @@ COMPUTE_OBJECT_SCHEMA = { "type": ["string", "null"] }, "connected": { - "description": "Whether the controller is connected to the compute server or not", + "description": "Whether the controller is connected to the compute or not", "type": "boolean" }, "cpu_usage_percent": { @@ -104,6 +104,10 @@ COMPUTE_OBJECT_SCHEMA = { "maximum": 100, "minimum": 0 }, + "last_error": { + "description": "Last error on the compute", + "type": ["string", "null"] + }, "capabilities": CAPABILITIES_SCHEMA }, "additionalProperties": False, @@ -123,3 +127,56 @@ COMPUTE_ENDPOINT_OUTPUT_OBJECT_SCHEMA = { "additionalProperties": False, } +COMPUTE_PORTS_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Output schema for open ports on a compute", + "type": "object", + "properties": { + "console_port_range": { + "description": "Console port range", + "type": "array", + "uniqueItems": True, + "minItems": 2, + "maxItems": 2, + "items": { + "type": "integer", + "minimum": 1, + "maximum": 65535 + } + }, + "console_ports": { + "description": "Console ports used by the compute", + "type": "array", + "uniqueItems": True, + "items": { + "type": "integer", + "minimum": 1, + "maximum": 65535 + } + }, + "udp_port_range": { + "description": "UDP port range", + "type": "array", + "uniqueItems": True, + "minItems": 2, + "maxItems": 2, + "items": { + "type": "integer", + "minimum": 1, + "maximum": 65535 + } + }, + "udp_ports": { + "description": "UDP ports used by the compute", + "type": "array", + "uniqueItems": True, + "items": { + "type": "integer", + "minimum": 1, + "maximum": 65535 + } + }, + }, + "additionalProperties": False, +} + diff --git a/gns3server/schemas/custom_adapters.py b/gns3server/schemas/custom_adapters.py new file mode 100644 index 00000000..f3472540 --- /dev/null +++ b/gns3server/schemas/custom_adapters.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 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 . + +CUSTOM_ADAPTERS_ARRAY_SCHEMA = { + "type": "array", + "default": [], + "items": { + "type": "object", + "description": "Custom properties", + "properties": { + "adapter_number": { + "type": "integer", + "description": "Adapter number" + }, + "port_name": { + "type": "string", + "description": "Custom port name", + "minLength": 1, + }, + "adapter_type": { + "type": "string", + "description": "Custom adapter type", + "minLength": 1, + }, + "mac_address": { + "description": "Custom MAC address", + "type": "string", + "minLength": 1, + "pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$" + }, + }, + "additionalProperties": False, + "required": ["adapter_number"] + }, +} diff --git a/gns3server/schemas/docker.py b/gns3server/schemas/docker.py index d9934d74..6cea166a 100644 --- a/gns3server/schemas/docker.py +++ b/gns3server/schemas/docker.py @@ -16,6 +16,9 @@ # along with this program. If not, see . +from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA + + DOCKER_CREATE_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Request validation to create a new Docker container", @@ -41,7 +44,7 @@ DOCKER_CREATE_SCHEMA = { }, "console_type": { "description": "Console type", - "enum": ["telnet", "vnc", "http", "https"] + "enum": ["telnet", "vnc", "http", "https", "none"] }, "console_resolution": { "description": "Console resolution for VNC", @@ -63,7 +66,7 @@ DOCKER_CREATE_SCHEMA = { "type": ["integer", "null"] }, "usage": { - "description": "How to use the qemu VM", + "description": "How to use the Docker container", "type": "string", }, "start_command": { @@ -87,13 +90,27 @@ DOCKER_CREATE_SCHEMA = { "type": ["string", "null"], "minLength": 0, }, + "extra_hosts": { + "description": "Docker extra hosts (added to /etc/hosts)", + "type": ["string", "null"], + "minLength": 0, + }, + "extra_volumes": { + "description": "Additional directories to make persistent", + "type": "array", + "minItems": 0, + "items": { + "type": "string" + } + }, "container_id": { "description": "Docker container ID Read only", "type": "string", "minLength": 12, "maxLength": 64, "pattern": "^[a-f0-9]+$" - } + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA }, "additionalProperties": False, "required": ["name", "image"] @@ -126,7 +143,7 @@ DOCKER_OBJECT_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_resolution": { "description": "Console resolution for VNC", @@ -135,7 +152,7 @@ DOCKER_OBJECT_SCHEMA = { }, "console_type": { "description": "Console type", - "enum": ["telnet", "vnc", "http", "https"] + "enum": ["telnet", "vnc", "http", "https", "none"] }, "console_http_port": { "description": "Internal port in the container for the HTTP server", @@ -171,7 +188,7 @@ DOCKER_OBJECT_SCHEMA = { "maximum": 99, }, "usage": { - "description": "How to use the qemu VM", + "description": "How to use the Docker container", "type": "string", }, "start_command": { @@ -184,6 +201,19 @@ DOCKER_OBJECT_SCHEMA = { "type": ["string", "null"], "minLength": 0, }, + "extra_hosts": { + "description": "Docker extra hosts (added to /etc/hosts)", + "type": ["string", "null"], + "minLength": 0, + }, + "extra_volumes": { + "description": "Additional directories to make persistent", + "type": "array", + "minItems": 0, + "items": { + "type": "string", + } + }, "node_directory": { "description": "Path to the node working directory Read only", "type": "string" @@ -192,6 +222,7 @@ DOCKER_OBJECT_SCHEMA = { "description": "VM status Read only", "enum": ["started", "stopped", "suspended"] }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA }, "additionalProperties": False, } diff --git a/gns3server/schemas/docker_template.py b/gns3server/schemas/docker_template.py new file mode 100644 index 00000000..0e04bbd1 --- /dev/null +++ b/gns3server/schemas/docker_template.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES +from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA + + +DOCKER_TEMPLATE_PROPERTIES = { + "image": { + "description": "Docker image name", + "type": "string", + "minLength": 1 + }, + "usage": { + "description": "How to use the Docker container", + "type": "string", + "default": "" + }, + "adapters": { + "description": "Number of adapters", + "type": "integer", + "minimum": 0, + "maximum": 99, + "default": 1 + }, + "start_command": { + "description": "Docker CMD entry", + "type": "string", + "default": "" + }, + "environment": { + "description": "Docker environment variables", + "type": "string", + "default": "" + }, + "console_type": { + "description": "Console type", + "enum": ["telnet", "vnc", "http", "https", "none"], + "default": "telnet" + }, + "console_auto_start": { + "description": "Automatically start the console when the node has started", + "type": "boolean", + "default": False, + }, + "console_http_port": { + "description": "Internal port in the container for the HTTP server", + "type": "integer", + "minimum": 1, + "maximum": 65535, + "default": 80 + }, + "console_http_path": { + "description": "Path of the web interface", + "type": "string", + "minLength": 1, + "default": "/" + }, + "console_resolution": { + "description": "Console resolution for VNC", + "type": "string", + "pattern": "^[0-9]+x[0-9]+$", + "default": "1024x768" + }, + "extra_hosts": { + "description": "Docker extra hosts (added to /etc/hosts)", + "type": "string", + "default": "" + }, + "extra_volumes": { + "description": "Additional directories to make persistent", + "type": "array", + "default": [] + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA +} + +DOCKER_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +DOCKER_TEMPLATE_PROPERTIES["category"]["default"] = "guest" +DOCKER_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "{name}-{0}" +DOCKER_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/docker_guest.svg" + +DOCKER_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A Docker template object", + "type": "object", + "properties": DOCKER_TEMPLATE_PROPERTIES, + "required": ["image"], + "additionalProperties": False +} diff --git a/gns3server/schemas/drawing.py b/gns3server/schemas/drawing.py index b15a5e3c..37f8fd6c 100644 --- a/gns3server/schemas/drawing.py +++ b/gns3server/schemas/drawing.py @@ -47,6 +47,10 @@ DRAWING_OBJECT_SCHEMA = { "description": "Z property", "type": "integer" }, + "locked": { + "description": "Whether the element locked or not", + "type": "boolean" + }, "rotation": { "description": "Rotation of the element", "type": "integer", diff --git a/gns3server/schemas/dynamips_template.py b/gns3server/schemas/dynamips_template.py new file mode 100644 index 00000000..61a41fc1 --- /dev/null +++ b/gns3server/schemas/dynamips_template.py @@ -0,0 +1,404 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES +from .dynamips_vm import DYNAMIPS_ADAPTERS, DYNAMIPS_WICS + + +DYNAMIPS_TEMPLATE_PROPERTIES = { + "platform": { + "description": "Platform type", + "enum": ["c7200", "c3745", "c3725", "c3600", "c2691", "c2600", "c1700"] + }, + "image": { + "description": "Path to the IOS image", + "type": "string", + "minLength": 1 + }, + "usage": { + "description": "How to use the Dynamips VM", + "type": "string", + "default": "" + }, + "mmap": { + "description": "MMAP feature", + "type": "boolean", + "default": True + }, + "exec_area": { + "description": "Exec area value", + "type": "integer", + "default": 64 + }, + "mac_addr": { + "description": "Base MAC address", + "type": "string", + "anyOf": [ + {"pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$"}, + {"pattern": "^$"} + ], + "default": "" + }, + "system_id": { + "description": "System ID", + "type": "string", + "minLength": 1, + "default": "FTX0945W0MY" + }, + "startup_config": { + "description": "IOS startup configuration file", + "type": "string", + "default": "ios_base_startup-config.txt" + }, + "private_config": { + "description": "IOS private configuration file", + "type": "string", + "default": "" + }, + "idlepc": { + "description": "Idle-PC value", + "type": "string", + "pattern": "^(0x[0-9a-fA-F]+)?$", + "default": "" + }, + "idlemax": { + "description": "Idlemax value", + "type": "integer", + "default": 500 + }, + "idlesleep": { + "description": "Idlesleep value", + "type": "integer", + "default": 30 + }, + "disk0": { + "description": "Disk0 size in MB", + "type": "integer", + "default": 0 + }, + "disk1": { + "description": "Disk1 size in MB", + "type": "integer", + "default": 0 + }, + "auto_delete_disks": { + "description": "Automatically delete nvram and disk files", + "type": "boolean", + "default": False + }, + "wic0": DYNAMIPS_WICS, + "wic1": DYNAMIPS_WICS, + "wic2": DYNAMIPS_WICS, + "slot0": DYNAMIPS_ADAPTERS, + "slot1": DYNAMIPS_ADAPTERS, + "slot2": DYNAMIPS_ADAPTERS, + "slot3": DYNAMIPS_ADAPTERS, + "slot4": DYNAMIPS_ADAPTERS, + "slot5": DYNAMIPS_ADAPTERS, + "slot6": DYNAMIPS_ADAPTERS, + "console_type": { + "description": "Console type", + "enum": ["telnet", "none"], + "default": "telnet" + }, + "console_auto_start": { + "description": "Automatically start the console when the node has started", + "type": "boolean", + "default": False + } +} + +DYNAMIPS_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +DYNAMIPS_TEMPLATE_PROPERTIES["category"]["default"] = "router" +DYNAMIPS_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "R{0}" +DYNAMIPS_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/router.svg" + +DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A Dynamips template object", + "type": "object", + "properties": DYNAMIPS_TEMPLATE_PROPERTIES, + "required": ["platform", "image"], +} + +C7200_DYNAMIPS_TEMPLATE_PROPERTIES = { + "ram": { + "description": "Amount of RAM in MB", + "type": "integer", + "default": 512 + }, + "nvram": { + "description": "Amount of NVRAM in KB", + "type": "integer", + "default": 512 + }, + "npe": { + "description": "NPE model", + "enum": ["npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300", "npe-400", "npe-g2"], + "default": "npe-400" + }, + "midplane": { + "description": "Midplane model", + "enum": ["std", "vxr"], + "default": "vxr" + }, + "sparsemem": { + "description": "Sparse memory feature", + "type": "boolean", + "default": True + } +} + +C7200_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES) + +C7200_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A c7200 Dynamips template object", + "type": "object", + "properties": C7200_DYNAMIPS_TEMPLATE_PROPERTIES, + "additionalProperties": False +} + +C3745_DYNAMIPS_TEMPLATE_PROPERTIES = { + "ram": { + "description": "Amount of RAM in MB", + "type": "integer", + "default": 256 + }, + "nvram": { + "description": "Amount of NVRAM in KB", + "type": "integer", + "default": 256 + }, + "iomem": { + "description": "I/O memory percentage", + "type": "integer", + "minimum": 0, + "maximum": 100, + "default": 5 + }, + "sparsemem": { + "description": "Sparse memory feature", + "type": "boolean", + "default": True + } +} + +C3745_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES) + +C3745_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A c3745 Dynamips template object", + "type": "object", + "properties": C3745_DYNAMIPS_TEMPLATE_PROPERTIES, + "additionalProperties": False +} + +C3725_DYNAMIPS_TEMPLATE_PROPERTIES = { + "ram": { + "description": "Amount of RAM in MB", + "type": "integer", + "default": 128 + }, + "nvram": { + "description": "Amount of NVRAM in KB", + "type": "integer", + "default": 256 + }, + "iomem": { + "description": "I/O memory percentage", + "type": "integer", + "minimum": 0, + "maximum": 100, + "default": 5 + }, + "sparsemem": { + "description": "Sparse memory feature", + "type": "boolean", + "default": True + } +} + +C3725_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES) + +C3725_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A c3725 Dynamips template object", + "type": "object", + "properties": C3725_DYNAMIPS_TEMPLATE_PROPERTIES, + "additionalProperties": False +} + +C3600_DYNAMIPS_TEMPLATE_PROPERTIES = { + "chassis": { + "description": "Chassis type", + "enum": ["3620", "3640", "3660"], + "default": "3660" + }, + "ram": { + "description": "Amount of RAM in MB", + "type": "integer", + "default": 192 + }, + "nvram": { + "description": "Amount of NVRAM in KB", + "type": "integer", + "default": 128 + }, + + "iomem": { + "description": "I/O memory percentage", + "type": "integer", + "minimum": 0, + "maximum": 100, + "default": 5 + }, + "sparsemem": { + "description": "Sparse memory feature", + "type": "boolean", + "default": True + } +} + +C3600_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES) + +C3600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A c3600 Dynamips template object", + "type": "object", + "properties": C3600_DYNAMIPS_TEMPLATE_PROPERTIES, + "required": ["chassis"], + "additionalProperties": False +} + +C2691_DYNAMIPS_TEMPLATE_PROPERTIES = { + "ram": { + "description": "Amount of RAM in MB", + "type": "integer", + "default": 192 + }, + "nvram": { + "description": "Amount of NVRAM in KB", + "type": "integer", + "default": 256 + }, + "iomem": { + "description": "I/O memory percentage", + "type": "integer", + "minimum": 0, + "maximum": 100, + "default": 5 + }, + "sparsemem": { + "description": "Sparse memory feature", + "type": "boolean", + "default": True + } +} + +C2691_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES) + +C2691_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A c2691 Dynamips template object", + "type": "object", + "properties": C2691_DYNAMIPS_TEMPLATE_PROPERTIES, + "additionalProperties": False +} + +C2600_DYNAMIPS_TEMPLATE_PROPERTIES = { + "chassis": { + "description": "Chassis type", + "enum": ["2610", "2620", "2610XM", "2620XM", "2650XM", "2621", "2611XM", "2621XM", "2651XM"], + "default": "2651XM" + }, + "ram": { + "description": "Amount of RAM in MB", + "type": "integer", + "default": 160 + }, + "nvram": { + "description": "Amount of NVRAM in KB", + "type": "integer", + "default": 128 + }, + "iomem": { + "description": "I/O memory percentage", + "type": "integer", + "minimum": 0, + "maximum": 100, + "default": 15 + }, + "sparsemem": { + "description": "Sparse memory feature", + "type": "boolean", + "default": True + } +} + +C2600_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES) + +C2600_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A c2600 Dynamips template object", + "type": "object", + "properties": C2600_DYNAMIPS_TEMPLATE_PROPERTIES, + "required": ["chassis"], + "additionalProperties": False +} + +C1700_DYNAMIPS_TEMPLATE_PROPERTIES = { + "chassis": { + "description": "Chassis type", + "enum": ["1720", "1721", "1750", "1751", "1760"], + "default": "1760" + }, + "ram": { + "description": "Amount of RAM in MB", + "type": "integer", + "default": 160 + }, + "nvram": { + "description": "Amount of NVRAM in KB", + "type": "integer", + "default": 128 + }, + "iomem": { + "description": "I/O memory percentage", + "type": "integer", + "minimum": 0, + "maximum": 100, + "default": 15 + }, + "sparsemem": { + "description": "Sparse memory feature", + "type": "boolean", + "default": False + } +} + +C1700_DYNAMIPS_TEMPLATE_PROPERTIES.update(DYNAMIPS_TEMPLATE_PROPERTIES) + +C1700_DYNAMIPS_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A c1700 Dynamips template object", + "type": "object", + "properties": C1700_DYNAMIPS_TEMPLATE_PROPERTIES, + "required": ["chassis"], + "additionalProperties": False +} diff --git a/gns3server/schemas/dynamips_vm.py b/gns3server/schemas/dynamips_vm.py index 43b7da4f..1fc939a6 100644 --- a/gns3server/schemas/dynamips_vm.py +++ b/gns3server/schemas/dynamips_vm.py @@ -16,6 +16,45 @@ # along with this program. If not, see . +DYNAMIPS_ADAPTERS = { + "description": "Dynamips Network Module", + "enum": ["C7200-IO-2FE", + "C7200-IO-FE", + "C7200-IO-GE-E", + "NM-16ESW", + "NM-1E", + "NM-1FE-TX", + "NM-4E", + "NM-4T", + "PA-2FE-TX", + "PA-4E", + "PA-4T+", + "PA-8E", + "PA-8T", + "PA-A1", + "PA-FE-TX", + "PA-GE", + "PA-POS-OC3", + "C2600-MB-2FE", + "C2600-MB-1E", + "C1700-MB-1FE", + "C2600-MB-2E", + "C2600-MB-1FE", + "C1700-MB-WIC1", + "GT96100-FE", + "Leopard-2FE", + ""] +} + +DYNAMIPS_WICS = { + "description": "Dynamips WIC", + "enum": ["WIC-1ENET", + "WIC-1T", + "WIC-2T", + ""] +} + +#TODO: improve schema for Dynamips (match platform specific options, e.g. NPE allowd only for c7200) VM_CREATE_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Request validation to create a new Dynamips VM instance", @@ -40,6 +79,10 @@ VM_CREATE_SCHEMA = { "type": "string", "minLength": 1, }, + "usage": { + "description": "How to use the Dynamips VM", + "type": "string", + }, "platform": { "description": "Cisco router platform", "type": "string", @@ -121,13 +164,13 @@ VM_CREATE_SCHEMA = { }, "console": { "description": "Console TCP port", - "type": "integer", + "type": ["integer", "null"], "minimum": 1, "maximum": 65535 }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "aux": { "description": "Auxiliary console TCP port", @@ -137,7 +180,7 @@ VM_CREATE_SCHEMA = { }, "mac_addr": { "description": "Base MAC address", - "type": "string", + "type": ["null", "string"], "minLength": 1, "pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$" }, @@ -262,6 +305,10 @@ VM_UPDATE_SCHEMA = { "type": "string", "minLength": 1, }, + "usage": { + "description": "How to use the Dynamips VM", + "type": "string", + }, "platform": { "description": "Cisco router platform", "type": "string", @@ -339,13 +386,13 @@ VM_UPDATE_SCHEMA = { }, "console": { "description": "Console TCP port", - "type": "integer", + "type": ["integer", "null"], "minimum": 1, "maximum": 65535 }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "aux": { "description": "Auxiliary console TCP port", @@ -355,7 +402,7 @@ VM_UPDATE_SCHEMA = { }, "mac_addr": { "description": "Base MAC address", - "type": "string", + "type": ["null", "string"], "minLength": 1, "pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$" }, @@ -502,6 +549,10 @@ VM_OBJECT_SCHEMA = { "type": "string", "minLength": 1, }, + "usage": { + "description": "How to use the Dynamips VM", + "type": "string", + }, "status": { "description": "VM status", "enum": ["started", "stopped", "suspended"] @@ -579,13 +630,13 @@ VM_OBJECT_SCHEMA = { }, "console": { "description": "Console TCP port", - "type": "integer", + "type": ["integer", "null"], "minimum": 1, "maximum": 65535 }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "aux": { "description": "Auxiliary console TCP port", @@ -595,7 +646,7 @@ VM_OBJECT_SCHEMA = { }, "mac_addr": { "description": "Base MAC address", - "type": "string", + "type": ["null", "string"] #"minLength": 1, #"pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$" }, diff --git a/gns3server/schemas/ethernet_hub_template.py b/gns3server/schemas/ethernet_hub_template.py new file mode 100644 index 00000000..f7a5edcd --- /dev/null +++ b/gns3server/schemas/ethernet_hub_template.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES + + +ETHERNET_HUB_TEMPLATE_PROPERTIES = { + "ports_mapping": { + "type": "array", + "default": [{"port_number": 0, + "name": "Ethernet0" + }, + {"port_number": 1, + "name": "Ethernet1" + }, + {"port_number": 2, + "name": "Ethernet2" + }, + {"port_number": 3, + "name": "Ethernet3" + }, + {"port_number": 4, + "name": "Ethernet4" + }, + {"port_number": 5, + "name": "Ethernet5" + }, + {"port_number": 6, + "name": "Ethernet6" + }, + {"port_number": 7, + "name": "Ethernet7" + } + ], + "items": [ + {"type": "object", + "oneOf": [{"description": "Ethernet port", + "properties": {"name": {"description": "Port name", + "type": "string", + "minLength": 1}, + "port_number": { + "description": "Port number", + "type": "integer", + "minimum": 0} + }, + "required": ["name", "port_number"], + "additionalProperties": False} + ], + } + ] + } +} + +ETHERNET_HUB_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +ETHERNET_HUB_TEMPLATE_PROPERTIES["category"]["default"] = "switch" +ETHERNET_HUB_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "Hub{0}" +ETHERNET_HUB_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/hub.svg" + +ETHERNET_HUB_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "An Ethernet hub template object", + "type": "object", + "properties": ETHERNET_HUB_TEMPLATE_PROPERTIES, + "additionalProperties": False +} diff --git a/gns3server/schemas/ethernet_switch.py b/gns3server/schemas/ethernet_switch.py index af9cf952..52951d3b 100644 --- a/gns3server/schemas/ethernet_switch.py +++ b/gns3server/schemas/ethernet_switch.py @@ -62,11 +62,11 @@ ETHERNET_SWITCH_CREATE_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "node_id": { "description": "Node UUID", @@ -163,11 +163,11 @@ ETHERNET_SWITCH_OBJECT_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, }, "additionalProperties": False, diff --git a/gns3server/schemas/ethernet_switch_template.py b/gns3server/schemas/ethernet_switch_template.py new file mode 100644 index 00000000..e2473220 --- /dev/null +++ b/gns3server/schemas/ethernet_switch_template.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES + + +ETHERNET_SWITCH_TEMPLATE_PROPERTIES = { + "ports_mapping": { + "type": "array", + "default": [{"ethertype": "", + "name": "Ethernet0", + "vlan": 1, + "type": "access", + "port_number": 0 + }, + {"ethertype": "", + "name": "Ethernet1", + "vlan": 1, + "type": "access", + "port_number": 1 + }, + {"ethertype": "", + "name": "Ethernet2", + "vlan": 1, + "type": "access", + "port_number": 2 + }, + {"ethertype": "", + "name": "Ethernet3", + "vlan": 1, + "type": "access", + "port_number": 3 + }, + {"ethertype": "", + "name": "Ethernet4", + "vlan": 1, + "type": "access", + "port_number": 4 + }, + {"ethertype": "", + "name": "Ethernet5", + "vlan": 1, + "type": "access", + "port_number": 5 + }, + {"ethertype": "", + "name": "Ethernet6", + "vlan": 1, + "type": "access", + "port_number": 6 + }, + {"ethertype": "", + "name": "Ethernet7", + "vlan": 1, + "type": "access", + "port_number": 7 + } + ], + "items": [ + {"type": "object", + "oneOf": [ + { + "description": "Ethernet port", + "properties": { + "name": { + "description": "Port name", + "type": "string", + "minLength": 1 + }, + "port_number": { + "description": "Port number", + "type": "integer", + "minimum": 0 + }, + "type": { + "description": "Port type", + "enum": ["access", "dot1q", "qinq"], + }, + "vlan": {"description": "VLAN number", + "type": "integer", + "minimum": 1 + }, + "ethertype": { + "description": "QinQ Ethertype", + "enum": ["", "0x8100", "0x88A8", "0x9100", "0x9200"], + }, + }, + "required": ["name", "port_number", "type"], + "additionalProperties": False + }, + ]}, + ] + }, + "console_type": { + "description": "Console type", + "enum": ["telnet", "none"], + "default": "none" + }, +} + +ETHERNET_SWITCH_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +ETHERNET_SWITCH_TEMPLATE_PROPERTIES["category"]["default"] = "switch" +ETHERNET_SWITCH_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "Switch{0}" +ETHERNET_SWITCH_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/ethernet_switch.svg" + +ETHERNET_SWITCH_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "An Ethernet switch template object", + "type": "object", + "properties": ETHERNET_SWITCH_TEMPLATE_PROPERTIES, + "additionalProperties": False +} diff --git a/gns3server/schemas/iou.py b/gns3server/schemas/iou.py index 656eb524..12e186e7 100644 --- a/gns3server/schemas/iou.py +++ b/gns3server/schemas/iou.py @@ -36,6 +36,10 @@ IOU_CREATE_SCHEMA = { {"type": "integer"} # for legacy projects ] }, + "usage": { + "description": "How to use the IOU VM", + "type": "string", + }, "console": { "description": "Console TCP port", "minimum": 1, @@ -44,7 +48,7 @@ IOU_CREATE_SCHEMA = { }, "console_type": { "description": "Console type", - "enum": ["telnet", None] + "enum": ["telnet", "none", None] }, "path": { "description": "Path of iou binary", @@ -104,6 +108,10 @@ IOU_START_SCHEMA = { "iourc_content": { "description": "Content of the iourc file. Ignored if Null", "type": ["string", "null"] + }, + "license_check": { + "description": "Whether the license should be checked", + "type": "boolean" } } } @@ -126,6 +134,10 @@ IOU_OBJECT_SCHEMA = { "maxLength": 36, "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" }, + "usage": { + "description": "How to use the IOU VM", + "type": "string", + }, "node_directory": { "description": "Path to the node working directory", "type": "string" @@ -138,11 +150,11 @@ IOU_OBJECT_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "project_id": { "description": "Project UUID", diff --git a/gns3server/schemas/appliance.py b/gns3server/schemas/iou_license.py similarity index 59% rename from gns3server/schemas/appliance.py rename to gns3server/schemas/iou_license.py index fde89ae3..4b2262cf 100644 --- a/gns3server/schemas/appliance.py +++ b/gns3server/schemas/iou_license.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2015 GNS3 Technologies Inc. +# Copyright (C) 2018 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 @@ -15,25 +15,19 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -APPLIANCE_USAGE_SCHEMA = { +IOU_LICENSE_SETTINGS_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", - "description": "Request validation to use an Appliance instance", + "description": "IOU license", "type": "object", "properties": { - "x": { - "description": "X position", - "type": "integer" + "iourc_content": { + "type": "string", + "description": "Content of iourc file" }, - "y": { - "description": "Y position", - "type": "integer" + "license_check": { + "type": "boolean", + "description": "Whether the license must be checked or not", }, - "compute_id": { - "description": "If the appliance don't have a default compute use this compute", - "type": ["null", "string"] - } }, - "additionalProperties": False, - "required": ["x", "y"] + "additionalProperties": False } diff --git a/gns3server/schemas/iou_template.py b/gns3server/schemas/iou_template.py new file mode 100644 index 00000000..f2dab0fb --- /dev/null +++ b/gns3server/schemas/iou_template.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES + + +IOU_TEMPLATE_PROPERTIES = { + "path": { + "description": "Path of IOU executable", + "type": "string", + "minLength": 1 + }, + "usage": { + "description": "How to use the IOU VM", + "type": "string", + }, + "ethernet_adapters": { + "description": "Number of ethernet adapters", + "type": "integer", + "default": 2 + }, + "serial_adapters": { + "description": "Number of serial adapters", + "type": "integer", + "default": 2 + }, + "ram": { + "description": "RAM in MB", + "type": "integer", + "default": 256 + }, + "nvram": { + "description": "NVRAM in KB", + "type": "integer", + "default": 128 + }, + "use_default_iou_values": { + "description": "Use default IOU values", + "type": "boolean", + "default": True + }, + "startup_config": { + "description": "Startup-config of IOU", + "type": "string", + "default": "iou_l3_base_startup-config.txt" + }, + "private_config": { + "description": "Private-config of IOU", + "type": "string", + "default": "" + }, + "l1_keepalives": { + "description": "Always keep up Ethernet interface (does not always work)", + "type": "boolean", + "default": False + }, + "console_type": { + "description": "Console type", + "enum": ["telnet", "none"], + "default": "telnet" + }, + "console_auto_start": { + "description": "Automatically start the console when the node has started", + "type": "boolean", + "default": False + }, +} + +IOU_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +IOU_TEMPLATE_PROPERTIES["category"]["default"] = "router" +IOU_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "IOU{0}" +IOU_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/multilayer_switch.svg" + +IOU_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A IOU template object", + "type": "object", + "properties": IOU_TEMPLATE_PROPERTIES, + "required": ["path"], + "additionalProperties": False +} diff --git a/gns3server/schemas/label.py b/gns3server/schemas/label.py index eae97417..eb5c2de1 100644 --- a/gns3server/schemas/label.py +++ b/gns3server/schemas/label.py @@ -20,11 +20,11 @@ LABEL_OBJECT_SCHEMA = { "properties": { "text": {"type": "string"}, "style": { - "description": "SVG style attribute", - "type": "string" + "description": "SVG style attribute. Apply default style if null", + "type": ["string", "null"] }, "x": { - "description": "Relative X position of the label. If null center it", + "description": "Relative X position of the label. Center it if null", "type": ["integer", "null"] }, "y": { diff --git a/gns3server/schemas/link.py b/gns3server/schemas/link.py index 05376888..6dd5ffe4 100644 --- a/gns3server/schemas/link.py +++ b/gns3server/schemas/link.py @@ -74,11 +74,15 @@ LINK_OBJECT_SCHEMA = { "type": "boolean" }, "capture_file_name": { - "description": "Read only property. The name of the capture file if capture is running", + "description": "Read only property. The name of the capture file if a capture is running", "type": ["string", "null"] }, "capture_file_path": { - "description": "Read only property. The full path of the capture file if capture is running", + "description": "Read only property. The full path of the capture file if a capture is running", + "type": ["string", "null"] + }, + "capture_compute_id": { + "description": "Read only property. The compute identifier where a capture is running", "type": ["string", "null"] }, "link_type": { diff --git a/gns3server/schemas/nio.py b/gns3server/schemas/nio.py index e45211a7..edee0eab 100644 --- a/gns3server/schemas/nio.py +++ b/gns3server/schemas/nio.py @@ -46,6 +46,10 @@ NIO_SCHEMA = { "minimum": 1, "maximum": 65535 }, + "suspend": { + "type": "boolean", + "description": "Suspend the link" + }, "filters": FILTER_OBJECT_SCHEMA }, "required": ["type", "lport", "rhost", "rport"], diff --git a/gns3server/schemas/node.py b/gns3server/schemas/node.py index d39ba747..5d3cc11a 100644 --- a/gns3server/schemas/node.py +++ b/gns3server/schemas/node.py @@ -17,6 +17,7 @@ import copy from .label import LABEL_OBJECT_SCHEMA +from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA NODE_TYPE_SCHEMA = { "description": "Type of node", @@ -30,6 +31,7 @@ NODE_TYPE_SCHEMA = { "docker", "dynamips", "vpcs", + "traceng", "virtualbox", "vmware", "iou", @@ -117,6 +119,13 @@ NODE_OBJECT_SCHEMA = { "maxLength": 36, "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" }, + "template_id": { + "description": "Template UUID from which the node has been created. Read only", + "type": ["null", "string"], + "minLength": 36, + "maxLength": 36, + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, "node_type": NODE_TYPE_SCHEMA, "node_directory": { "description": "Working directory of the node. Read only", @@ -144,7 +153,11 @@ NODE_OBJECT_SCHEMA = { }, "console_type": { "description": "Console type", - "enum": ["vnc", "telnet", "http", "https", "spice", None] + "enum": ["vnc", "telnet", "http", "https", "spice", "spice+agent", "none", None] + }, + "console_auto_start": { + "description": "Automatically start the console when the node has started", + "type": "boolean" }, "properties": { "description": "Properties specific to an emulator", @@ -180,6 +193,10 @@ NODE_OBJECT_SCHEMA = { "description": "Z position of the node", "type": "integer" }, + "locked": { + "description": "Whether the element locked or not", + "type": "boolean" + }, "port_name_format": { "description": "Formating for port name {0} will be replace by port number", "type": "string" @@ -193,6 +210,7 @@ NODE_OBJECT_SCHEMA = { "description": "Name of the first port", "type": ["string", "null"], }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA, "ports": { "description": "List of node ports READ only", "type": "array", @@ -212,6 +230,11 @@ NODE_OBJECT_SCHEMA = { "type": "integer", "description": "Adapter slot" }, + "adapter_type": { + "description": "Adapter type", + "type": ["string", "null"], + "minLength": 1, + }, "port_number": { "type": "integer", "description": "Port slot" @@ -222,9 +245,15 @@ NODE_OBJECT_SCHEMA = { }, "data_link_types": { "type": "object", - "description": "Available PCAP type for capture", + "description": "Available PCAP types for capture", "properties": {} }, + "mac_address": { + "description": "MAC address (if available)", + "type": ["string", "null"], + "minLength": 1, + "pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$" + }, }, "additionalProperties": False } diff --git a/gns3server/schemas/project.py b/gns3server/schemas/project.py index eb008389..23f23ac2 100644 --- a/gns3server/schemas/project.py +++ b/gns3server/schemas/project.py @@ -15,6 +15,40 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +SUPPLIER_OBJECT_SCHEMA = { + "type": ["object", "null"], + "description": "Supplier of the project", + "properties": { + "logo": { + "type": "string", + "description": "Path to the project supplier logo" + }, + "url": { + "type": "string", + "description": "URL to the project supplier site" + } + } +} + + +VARIABLES_OBJECT_SCHEMA = { + "type": ["array", "null"], + "description": "Variables required to run the project", + "items": { + "properties": { + "name": { + "type": "string", + "description": "Variable name" + }, + "value": { + "type": "string", + "description": "Variable value" + } + }, + "required": ["name"] + } +} + PROJECT_CREATE_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", @@ -66,10 +100,20 @@ PROJECT_CREATE_SCHEMA = { "type": "boolean", "description": "Show the grid on the drawing area" }, + "grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for nodes" + }, + "drawing_grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for drawings" + }, "show_interface_labels": { "type": "boolean", "description": "Show interface labels on the drawing area" - } + }, + "supplier": SUPPLIER_OBJECT_SCHEMA, + "variables": VARIABLES_OBJECT_SCHEMA }, "additionalProperties": False, "required": ["name"] @@ -125,10 +169,20 @@ PROJECT_UPDATE_SCHEMA = { "type": "boolean", "description": "Show the grid on the drawing area" }, + "grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for nodes" + }, + "drawing_grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for drawings" + }, "show_interface_labels": { "type": "boolean", "description": "Show interface labels on the drawing area" - } + }, + "supplier": SUPPLIER_OBJECT_SCHEMA, + "variables": VARIABLES_OBJECT_SCHEMA }, "additionalProperties": False, } @@ -200,10 +254,20 @@ PROJECT_OBJECT_SCHEMA = { "type": "boolean", "description": "Show the grid on the drawing area" }, + "grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for nodes" + }, + "drawing_grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for drawings" + }, "show_interface_labels": { "type": "boolean", "description": "Show interface labels on the drawing area" - } + }, + "supplier": SUPPLIER_OBJECT_SCHEMA, + "variables": VARIABLES_OBJECT_SCHEMA }, "additionalProperties": False, "required": ["project_id"] diff --git a/gns3server/schemas/qemu.py b/gns3server/schemas/qemu.py index f67f808a..e3e7a1d6 100644 --- a/gns3server/schemas/qemu.py +++ b/gns3server/schemas/qemu.py @@ -15,7 +15,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -QEMU_PLATFORMS = ["aarch64", "alpha", "arm", "cris", "i386", "lm32", "m68k", "microblaze", "microblazeel", "mips", "mips64", "mips64el", "mipsel", "moxie", "or32", "ppc", "ppc64", "ppcemb", "s390x", "sh4", "sh4eb", "sparc", "sparc64", "tricore", "unicore32", "x86_64", "xtensa", "xtensaeb"] +from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA + +QEMU_PLATFORMS = ["aarch64", "alpha", "arm", "cris", "i386", "lm32", "m68k", "microblaze", "microblazeel", "mips", "mips64", "mips64el", "mipsel", "moxie", "or32", "ppc", "ppc64", "ppcemb", "s390x", "sh4", "sh4eb", "sparc", "sparc64", "tricore", "unicore32", "x86_64", "xtensa", "xtensaeb", ""] QEMU_CREATE_SCHEMA = { @@ -39,7 +41,7 @@ QEMU_CREATE_SCHEMA = { "minLength": 1, }, "usage": { - "description": "How to use the qemu VM", + "description": "How to use the Qemu VM", "type": "string", }, "linked_clone": { @@ -63,7 +65,7 @@ QEMU_CREATE_SCHEMA = { }, "console_type": { "description": "Console type", - "enum": ["telnet", "vnc", "spice"] + "enum": ["telnet", "vnc", "spice", "spice+agent", "none"] }, "hda_disk_image": { "description": "QEMU hda disk image path", @@ -131,7 +133,7 @@ QEMU_CREATE_SCHEMA = { }, "boot_priority": { "description": "QEMU boot priority", - "enum": ["c", "d", "n", "cn", "cd"] + "enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"] }, "ram": { "description": "Amount of RAM in MB", @@ -184,9 +186,9 @@ QEMU_CREATE_SCHEMA = { "description": "Use QEMU legagy networking commands (-net syntax)", "type": ["boolean", "null"], }, - "acpi_shutdown": { - "description": "ACPI shutdown support", - "type": ["boolean", "null"], + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], }, "cpu_throttling": { "description": "Percentage of CPU allowed for QEMU", @@ -207,7 +209,8 @@ QEMU_CREATE_SCHEMA = { "options": { "description": "Additional QEMU options", "type": ["string", "null"], - } + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA }, "additionalProperties": False, "required": ["name"], @@ -244,7 +247,7 @@ QEMU_UPDATE_SCHEMA = { }, "console_type": { "description": "Console type", - "enum": ["telnet", "vnc", "spice"] + "enum": ["telnet", "vnc", "spice", "spice+agent", "none"] }, "linked_clone": { "description": "Whether the VM is a linked clone or not", @@ -316,7 +319,7 @@ QEMU_UPDATE_SCHEMA = { }, "boot_priority": { "description": "QEMU boot priority", - "enum": ["c", "d", "n", "cn", "cd"] + "enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"] }, "ram": { "description": "Amount of RAM in MB", @@ -369,9 +372,9 @@ QEMU_UPDATE_SCHEMA = { "description": "Use QEMU legagy networking commands (-net syntax)", "type": ["boolean", "null"], }, - "acpi_shutdown": { - "description": "ACPI shutdown support", - "type": ["boolean", "null"], + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], }, "cpu_throttling": { "description": "Percentage of CPU allowed for QEMU", @@ -392,7 +395,8 @@ QEMU_UPDATE_SCHEMA = { "options": { "description": "Additional QEMU options", "type": ["string", "null"], - } + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA }, "additionalProperties": False, } @@ -500,7 +504,7 @@ QEMU_OBJECT_SCHEMA = { }, "boot_priority": { "description": "QEMU boot priority", - "enum": ["c", "d", "n", "cn", "cd"] + "enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"] }, "node_directory": { "description": "Path to the VM working directory", @@ -537,11 +541,11 @@ QEMU_OBJECT_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_type": { "description": "Console type", - "enum": ["telnet", "vnc", "spice"] + "enum": ["telnet", "vnc", "spice","spice+agent", "none"] }, "initrd": { "description": "QEMU initrd path", @@ -567,9 +571,13 @@ QEMU_OBJECT_SCHEMA = { "description": "Use QEMU legagy networking commands (-net syntax)", "type": "boolean", }, - "acpi_shutdown": { - "description": "ACPI shutdown support", - "type": "boolean", + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], + }, + "save_vm_state": { + "description": "Save VM state support", + "type": ["boolean", "null"], }, "cpu_throttling": { "description": "Percentage of CPU allowed for QEMU", @@ -632,7 +640,7 @@ QEMU_OBJECT_SCHEMA = { "kernel_image_md5sum", "kernel_command_line", "legacy_networking", - "acpi_shutdown", + "on_close", "cpu_throttling", "process_priority", "options", @@ -641,6 +649,25 @@ QEMU_OBJECT_SCHEMA = { "status"] } +QEMU_RESIZE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Resize a disk in a QEMU VM", + "type": "object", + "properties": { + "drive_name": { + "description": "Absolute or relative path of the image", + "enum": ["hda", "hdb", "hdc", "hdd"] + }, + "extend": { + "description": "Number of Megabytes to extend the image", + "type": "integer" + }, + # TODO: support shrink? (could be dangerous) + }, + "required": ["drive_name", "extend"], + "additionalProperties": False +} + QEMU_BINARY_FILTER_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Request validation for a list of QEMU capabilities", @@ -758,3 +785,25 @@ QEMU_IMAGE_CREATE_SCHEMA = { "required": ["qemu_img", "path", "format", "size"], "additionalProperties": False } + +QEMU_IMAGE_UPDATE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Update an existing QEMU image", + "type": "object", + "properties": { + "qemu_img": { + "description": "Path to the qemu-img binary", + "type": "string" + }, + "path": { + "description": "Absolute or relative path of the image", + "type": "string" + }, + "extend": { + "description": "Number of Megabytes to extend the image", + "type": "integer" + }, + }, + "required": ["qemu_img", "path"], + "additionalProperties": False +} diff --git a/gns3server/schemas/qemu_template.py b/gns3server/schemas/qemu_template.py new file mode 100644 index 00000000..514056e9 --- /dev/null +++ b/gns3server/schemas/qemu_template.py @@ -0,0 +1,217 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES +from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA +from .qemu import QEMU_PLATFORMS + + +QEMU_TEMPLATE_PROPERTIES = { + "qemu_path": { + "description": "Path to QEMU", + "type": "string", + "default": "" + }, + "usage": { + "description": "How to use the Qemu VM", + "type": "string", + "default": "" + }, + "platform": { + "description": "Platform to emulate", + "enum": QEMU_PLATFORMS, + "default": "i386" + }, + "linked_clone": { + "description": "Whether the VM is a linked clone or not", + "type": "boolean", + "default": True + }, + "ram": { + "description": "Amount of RAM in MB", + "type": "integer", + "default": 256 + }, + "cpus": { + "description": "Number of vCPUs", + "type": "integer", + "minimum": 1, + "maximum": 255, + "default": 1 + }, + "adapters": { + "description": "Number of adapters", + "type": "integer", + "minimum": 0, + "maximum": 275, + "default": 1 + }, + "adapter_type": { + "description": "QEMU adapter type", + "type": "string", + "enum": ["e1000", "i82550", "i82551", "i82557a", "i82557b", "i82557c", "i82558a","i82558b", "i82559a", + "i82559b", "i82559c", "i82559er", "i82562", "i82801", "ne2k_pci", "pcnet", "rtl8139", "virtio", + "virtio-net-pci", "vmxnet3"], + "default": "e1000" + }, + "mac_address": { + "description": "QEMU MAC address", + "type": ["string", "null"], + "anyOf": [ + {"pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"}, + {"pattern": "^$"} + ], + "default": "", + }, + "first_port_name": { + "description": "Optional name of the first networking port example: eth0", + "type": "string", + "default": "" + }, + "port_name_format": { + "description": "Optional formatting of the networking port example: eth{0}", + "type": "string", + "default": "Ethernet{0}" + }, + "port_segment_size": { + "description": "Optional port segment size. A port segment is a block of port. For example Ethernet0/0 Ethernet0/1 is the module 0 with a port segment size of 2", + "type": "integer", + "default": 0 + }, + "console_type": { + "description": "Console type", + "enum": ["telnet", "vnc", "spice", "spice+agent", "none"], + "default": "telnet" + }, + "console_auto_start": { + "description": "Automatically start the console when the node has started", + "type": "boolean", + "default": False + }, + "boot_priority": { + "description": "QEMU boot priority", + "enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"], + "default": "c" + }, + "hda_disk_image": { + "description": "QEMU hda disk image path", + "type": "string", + "default": "" + }, + "hda_disk_interface": { + "description": "QEMU hda interface", + "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], + "default": "ide" + }, + "hdb_disk_image": { + "description": "QEMU hdb disk image path", + "type": "string", + "default": "" + }, + "hdb_disk_interface": { + "description": "QEMU hdb interface", + "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], + "default": "ide" + }, + "hdc_disk_image": { + "description": "QEMU hdc disk image path", + "type": "string", + "default": "" + }, + "hdc_disk_interface": { + "description": "QEMU hdc interface", + "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], + "default": "ide" + }, + "hdd_disk_image": { + "description": "QEMU hdd disk image path", + "type": "string", + "default": "" + }, + "hdd_disk_interface": { + "description": "QEMU hdd interface", + "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], + "default": "ide" + }, + "cdrom_image": { + "description": "QEMU cdrom image path", + "type": "string", + "default": "" + }, + "initrd": { + "description": "QEMU initrd path", + "type": "string", + "default": "" + }, + "kernel_image": { + "description": "QEMU kernel image path", + "type": "string", + "default": "" + }, + "bios_image": { + "description": "QEMU bios image path", + "type": "string", + "default": "" + }, + "kernel_command_line": { + "description": "QEMU kernel command line", + "type": "string", + "default": "" + }, + "legacy_networking": { + "description": "Use QEMU legagy networking commands (-net syntax)", + "type": "boolean", + "default": False + }, + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], + "default": "power_off" + }, + "cpu_throttling": { + "description": "Percentage of CPU allowed for QEMU", + "minimum": 0, + "maximum": 800, + "type": "integer", + "default": 0 + }, + "process_priority": { + "description": "Process priority for QEMU", + "enum": ["realtime", "very high", "high", "normal", "low", "very low"], + "default": "normal" + }, + "options": { + "description": "Additional QEMU options", + "type": "string", + "default": "" + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA +} + +QEMU_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +QEMU_TEMPLATE_PROPERTIES["category"]["default"] = "guest" +QEMU_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "{name}-{0}" +QEMU_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/qemu_guest.svg" + +QEMU_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A Qemu template object", + "type": "object", + "properties": QEMU_TEMPLATE_PROPERTIES, + "additionalProperties": False +} diff --git a/gns3server/schemas/template.py b/gns3server/schemas/template.py new file mode 100644 index 00000000..2914911f --- /dev/null +++ b/gns3server/schemas/template.py @@ -0,0 +1,107 @@ +# -*- 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 copy + +BASE_TEMPLATE_PROPERTIES = { + "template_id": { + "description": "Template UUID", + "type": "string", + "minLength": 36, + "maxLength": 36, + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, + "template_type": { + "description": "Type of node", + "enum": ["cloud", "ethernet_hub", "ethernet_switch", "docker", "dynamips", "vpcs", "traceng", + "virtualbox", "vmware", "iou", "qemu"] + }, + "name": { + "description": "Template name", + "type": "string", + "minLength": 1, + }, + "compute_id": { + "description": "Compute identifier", + "type": "string" + }, + "default_name_format": { + "description": "Default name format", + "type": "string", + "minLength": 1 + }, + "symbol": { + "description": "Symbol of the template", + "type": "string", + "minLength": 1 + }, + "category": { + "description": "Template category", + "anyOf": [ + {"type": "integer"}, # old category support + {"enum": ["router", "switch", "guest", "firewall"]} + ] + }, + "builtin": { + "description": "Template is builtin", + "type": "boolean" + }, +} + +TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A template object", + "type": "object", + "properties": BASE_TEMPLATE_PROPERTIES, + "required": ["name", "template_type", "template_id", "category", "compute_id", "default_name_format", "symbol", "builtin"] +} + +TEMPLATE_CREATE_SCHEMA = copy.deepcopy(TEMPLATE_OBJECT_SCHEMA) + +# create schema +# these properties are not required to create a template +TEMPLATE_CREATE_SCHEMA["required"].remove("template_id") +TEMPLATE_CREATE_SCHEMA["required"].remove("category") +TEMPLATE_CREATE_SCHEMA["required"].remove("default_name_format") +TEMPLATE_CREATE_SCHEMA["required"].remove("symbol") +TEMPLATE_CREATE_SCHEMA["required"].remove("builtin") + +# update schema +TEMPLATE_UPDATE_SCHEMA = copy.deepcopy(TEMPLATE_OBJECT_SCHEMA) +del TEMPLATE_UPDATE_SCHEMA["required"] + +TEMPLATE_USAGE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to use a Template instance", + "type": "object", + "properties": { + "x": { + "description": "X position", + "type": "integer" + }, + "y": { + "description": "Y position", + "type": "integer" + }, + "compute_id": { + "description": "If the template don't have a default compute use this compute", + "type": ["null", "string"] + } + }, + "additionalProperties": False, + "required": ["x", "y"] +} diff --git a/gns3server/schemas/topology.py b/gns3server/schemas/topology.py index bf9fc1cf..21d5e6da 100644 --- a/gns3server/schemas/topology.py +++ b/gns3server/schemas/topology.py @@ -23,6 +23,8 @@ from gns3server.schemas.compute import COMPUTE_OBJECT_SCHEMA from gns3server.schemas.drawing import DRAWING_OBJECT_SCHEMA from gns3server.schemas.link import LINK_OBJECT_SCHEMA from gns3server.schemas.node import NODE_OBJECT_SCHEMA +from gns3server.schemas.project import VARIABLES_OBJECT_SCHEMA +from gns3server.schemas.project import SUPPLIER_OBJECT_SCHEMA TOPOLOGY_SCHEMA = { @@ -89,10 +91,20 @@ TOPOLOGY_SCHEMA = { "type": "boolean", "description": "Show the grid on the drawing area" }, + "grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for nodes" + }, + "drawing_grid_size": { + "type": "integer", + "description": "Grid size for the drawing area for drawings" + }, "show_interface_labels": { "type": "boolean", "description": "Show interface labels on the drawing area" }, + "supplier": SUPPLIER_OBJECT_SCHEMA, + "variables": VARIABLES_OBJECT_SCHEMA, "topology": { "description": "The topology content", "type": "object", diff --git a/gns3server/schemas/traceng.py b/gns3server/schemas/traceng.py new file mode 100644 index 00000000..d95fd042 --- /dev/null +++ b/gns3server/schemas/traceng.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2018 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 . + + +TRACENG_CREATE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to create a new TraceNG instance", + "type": "object", + "properties": { + "name": { + "description": "TraceNG VM name", + "type": "string", + "minLength": 1, + }, + "node_id": { + "description": "Node UUID", + "oneOf": [ + {"type": "string", + "minLength": 36, + "maxLength": 36, + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"} + ] + }, + "console": { + "description": "Console TCP port", + "minimum": 1, + "maximum": 65535, + "type": ["integer", "null"] + }, + "console_type": { + "description": "Console type", + "enum": ["none"] + }, + "ip_address": { + "description": "Source IP address for tracing", + "type": ["string"] + }, + "default_destination": { + "description": "Default destination IP address or hostname for tracing", + "type": ["string"] + } + }, + "additionalProperties": False, + "required": ["name"] +} + +TRACENG_UPDATE_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to update a TraceNG instance", + "type": "object", + "properties": { + "name": { + "description": "TraceNG VM name", + "type": ["string", "null"], + "minLength": 1, + }, + "console": { + "description": "Console TCP port", + "minimum": 1, + "maximum": 65535, + "type": ["integer", "null"] + }, + "console_type": { + "description": "Console type", + "enum": ["none"] + }, + "ip_address": { + "description": "Source IP address for tracing", + "type": ["string"] + }, + "default_destination": { + "description": "Default destination IP address or hostname for tracing", + "type": ["string"] + } + }, + "additionalProperties": False, +} + +TRACENG_START_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Request validation to start a TraceNG instance", + "type": "object", + "properties": { + "destination": { + "description": "Host or IP address to trace", + "type": ["string"] + } + }, +} + +TRACENG_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "TraceNG instance", + "type": "object", + "properties": { + "name": { + "description": "TraceNG VM name", + "type": "string", + "minLength": 1, + }, + "node_id": { + "description": "Node UUID", + "type": "string", + "minLength": 36, + "maxLength": 36, + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, + "node_directory": { + "description": "Path to the VM working directory", + "type": "string" + }, + "status": { + "description": "VM status", + "enum": ["started", "stopped", "suspended"] + }, + "console": { + "description": "Console TCP port", + "minimum": 1, + "maximum": 65535, + "type": ["integer", "null"] + }, + "console_type": { + "description": "Console type", + "enum": ["none"] + }, + "project_id": { + "description": "Project UUID", + "type": "string", + "minLength": 36, + "maxLength": 36, + "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" + }, + "command_line": { + "description": "Last command line used by GNS3 to start TraceNG", + "type": "string" + }, + "ip_address": { + "description": "Source IP address for tracing", + "type": ["string"] + }, + "default_destination": { + "description": "Default destination IP address or hostname for tracing", + "type": ["string"] + } + }, + "additionalProperties": False, + "required": ["name", "node_id", "status", "console", "console_type", "project_id", "command_line", "ip_address", "default_destination"] +} diff --git a/gns3server/schemas/traceng_template.py b/gns3server/schemas/traceng_template.py new file mode 100644 index 00000000..5c574685 --- /dev/null +++ b/gns3server/schemas/traceng_template.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES + + +TRACENG_TEMPLATE_PROPERTIES = { + "ip_address": { + "description": "Source IP address for tracing", + "type": ["string"], + "minLength": 1 + }, + "default_destination": { + "description": "Default destination IP address or hostname for tracing", + "type": ["string"], + "minLength": 1 + }, + "console_type": { + "description": "Console type", + "enum": ["none"], + "default": "none" + }, +} + +TRACENG_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +TRACENG_TEMPLATE_PROPERTIES["category"]["default"] = "guest" +TRACENG_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "TraceNG{0}" +TRACENG_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/traceng.svg" + +TRACENG_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A TraceNG template object", + "type": "object", + "properties": TRACENG_TEMPLATE_PROPERTIES, + "additionalProperties": False +} diff --git a/gns3server/schemas/virtualbox.py b/gns3server/schemas/virtualbox.py index 769d373f..6e2039f7 100644 --- a/gns3server/schemas/virtualbox.py +++ b/gns3server/schemas/virtualbox.py @@ -16,6 +16,9 @@ # along with this program. If not, see . +from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA + + VBOX_CREATE_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Request validation to create a new VirtualBox VM instance", @@ -40,6 +43,10 @@ VBOX_CREATE_SCHEMA = { "type": "string", "minLength": 1, }, + "usage": { + "description": "How to use the VirtualBox VM", + "type": "string", + }, "vmname": { "description": "VirtualBox VM name (in VirtualBox itself)", "type": "string", @@ -64,11 +71,11 @@ VBOX_CREATE_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "ram": { "description": "Amount of RAM", @@ -80,10 +87,11 @@ VBOX_CREATE_SCHEMA = { "description": "Headless mode", "type": "boolean" }, - "acpi_shutdown": { - "description": "ACPI shutdown", - "type": "boolean" - } + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA }, "additionalProperties": False, "required": ["name", "vmname"], @@ -114,6 +122,10 @@ VBOX_OBJECT_SCHEMA = { "maxLength": 36, "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" }, + "usage": { + "description": "How to use the VirtualBox VM", + "type": "string", + }, "vmname": { "description": "VirtualBox VM name (in VirtualBox itself)", "type": "string", @@ -131,9 +143,9 @@ VBOX_OBJECT_SCHEMA = { "description": "Headless mode", "type": "boolean" }, - "acpi_shutdown": { - "description": "ACPI shutdown", - "type": "boolean" + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], }, "adapters": { "description": "Number of adapters", @@ -154,11 +166,11 @@ VBOX_OBJECT_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "ram": { "description": "Amount of RAM", @@ -169,7 +181,8 @@ VBOX_OBJECT_SCHEMA = { "linked_clone": { "description": "Whether the VM is a linked clone or not", "type": "boolean" - } + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA }, "additionalProperties": False, } diff --git a/gns3server/schemas/virtualbox_template.py b/gns3server/schemas/virtualbox_template.py new file mode 100644 index 00000000..1160b056 --- /dev/null +++ b/gns3server/schemas/virtualbox_template.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES +from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA + + +VIRTUALBOX_TEMPLATE_PROPERTIES = { + "vmname": { + "description": "VirtualBox VM name (in VirtualBox itself)", + "type": "string", + "minLength": 1, + }, + "usage": { + "description": "How to use the VirtualBox VM", + "type": "string", + "default": "" + }, + "ram": { + "description": "Amount of RAM", + "minimum": 0, + "maximum": 65535, + "type": "integer", + "default": 256 + }, + "linked_clone": { + "description": "Whether the VM is a linked clone or not", + "type": "boolean", + "default": False + }, + "adapters": { + "description": "Number of adapters", + "type": "integer", + "minimum": 0, + "maximum": 36, # maximum given by the ICH9 chipset in VirtualBox + "default": 1 + }, + "use_any_adapter": { + "description": "Allow GNS3 to use any VirtualBox adapter", + "type": "boolean", + "default": False + }, + "adapter_type": { + "description": "VirtualBox adapter type", + "enum": ["PCnet-PCI II (Am79C970A)", + "PCNet-FAST III (Am79C973)", + "Intel PRO/1000 MT Desktop (82540EM)", + "Intel PRO/1000 T Server (82543GC)", + "Intel PRO/1000 MT Server (82545EM)", + "Paravirtualized Network (virtio-net)"], + "default": "Intel PRO/1000 MT Desktop (82540EM)" + }, + "first_port_name": { + "description": "Optional name of the first networking port example: eth0", + "type": "string", + "default": "" + }, + "port_name_format": { + "description": "Optional formatting of the networking port example: eth{0}", + "type": "string", + "default": "Ethernet{0}" + }, + "port_segment_size": { + "description": "Optional port segment size. A port segment is a block of port. For example Ethernet0/0 Ethernet0/1 is the module 0 with a port segment size of 2", + "type": "integer", + "default": 0 + }, + "headless": { + "description": "Headless mode", + "type": "boolean", + "default": False + }, + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], + "default": "power_off" + }, + "console_type": { + "description": "Console type", + "enum": ["telnet", "none"], + "default": "none" + }, + "console_auto_start": { + "description": "Automatically start the console when the node has started", + "type": "boolean", + "default": False + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA +} + +VIRTUALBOX_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +VIRTUALBOX_TEMPLATE_PROPERTIES["category"]["default"] = "guest" +VIRTUALBOX_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "{name}-{0}" +VIRTUALBOX_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/vbox_guest.svg" + +VIRTUALBOX_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A VirtualBox template object", + "type": "object", + "properties": VIRTUALBOX_TEMPLATE_PROPERTIES, + "required": ["vmname"], + "additionalProperties": False +} diff --git a/gns3server/schemas/vmware.py b/gns3server/schemas/vmware.py index 72a009fe..d849d10a 100644 --- a/gns3server/schemas/vmware.py +++ b/gns3server/schemas/vmware.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA + VMWARE_CREATE_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", @@ -37,6 +39,10 @@ VMWARE_CREATE_SCHEMA = { "type": "string", "minLength": 1, }, + "usage": { + "description": "How to use the VMware VM", + "type": "string", + }, "vmx_path": { "description": "Path to the vmx file", "type": "string", @@ -46,19 +52,19 @@ VMWARE_CREATE_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "headless": { "description": "Headless mode", "type": "boolean" }, - "acpi_shutdown": { - "description": "ACPI shutdown", - "type": "boolean" + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], }, "adapters": { "description": "Number of adapters", @@ -74,7 +80,8 @@ VMWARE_CREATE_SCHEMA = { "use_any_adapter": { "description": "Allow GNS3 to use any VMware adapter", "type": "boolean", - } + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA }, "additionalProperties": False, "required": ["name", "vmx_path", "linked_clone"], @@ -91,6 +98,10 @@ VMWARE_OBJECT_SCHEMA = { "type": "string", "minLength": 1, }, + "usage": { + "description": "How to use the VMware VM", + "type": "string", + }, "node_id": { "description": "Node UUID", "type": "string", @@ -122,9 +133,9 @@ VMWARE_OBJECT_SCHEMA = { "description": "Headless mode", "type": "boolean" }, - "acpi_shutdown": { - "description": "ACPI shutdown", - "type": "boolean" + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], }, "adapters": { "description": "Number of adapters", @@ -145,16 +156,17 @@ VMWARE_OBJECT_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "linked_clone": { "description": "Whether the VM is a linked clone or not", "type": "boolean" - } + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA }, "additionalProperties": False } diff --git a/gns3server/schemas/vmware_template.py b/gns3server/schemas/vmware_template.py new file mode 100644 index 00000000..f9a65d30 --- /dev/null +++ b/gns3server/schemas/vmware_template.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES +from .custom_adapters import CUSTOM_ADAPTERS_ARRAY_SCHEMA + + +VMWARE_TEMPLATE_PROPERTIES = { + "vmx_path": { + "description": "Path to the vmx file", + "type": "string", + "minLength": 1, + }, + "usage": { + "description": "How to use the VMware VM", + "type": "string", + "default": "" + }, + "linked_clone": { + "description": "Whether the VM is a linked clone or not", + "type": "boolean", + "default": False + }, + "first_port_name": { + "description": "Optional name of the first networking port example: eth0", + "type": "string", + "default": "" + }, + "port_name_format": { + "description": "Optional formatting of the networking port example: eth{0}", + "type": "string", + "default": "Ethernet{0}" + }, + "port_segment_size": { + "description": "Optional port segment size. A port segment is a block of port. For example Ethernet0/0 Ethernet0/1 is the module 0 with a port segment size of 2", + "type": "integer", + "default": 0 + }, + "adapters": { + "description": "Number of adapters", + "type": "integer", + "minimum": 0, + "maximum": 10, # maximum adapters support by VMware VMs, + "default": 1 + }, + "adapter_type": { + "description": "VMware adapter type", + "enum": ["default", "e1000", "e1000e", "flexible", "vlance", "vmxnet", "vmxnet2", "vmxnet3"], + "default": "e1000" + }, + "use_any_adapter": { + "description": "Allow GNS3 to use any VMware adapter", + "type": "boolean", + "default": False + }, + "headless": { + "description": "Headless mode", + "type": "boolean", + "default": False + }, + "on_close": { + "description": "Action to execute on the VM is closed", + "enum": ["power_off", "shutdown_signal", "save_vm_state"], + "default": "power_off" + }, + "console_type": { + "description": "Console type", + "enum": ["telnet", "none"], + "default": "none" + }, + "console_auto_start": { + "description": "Automatically start the console when the node has started", + "type": "boolean", + "default": False + }, + "custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA +} + +VMWARE_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +VMWARE_TEMPLATE_PROPERTIES["category"]["default"] = "guest" +VMWARE_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "{name}-{0}" +VMWARE_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/vmware_guest.svg" + +VMWARE_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A VMware template object", + "type": "object", + "properties": VMWARE_TEMPLATE_PROPERTIES, + "required": ["vmx_path"], + "additionalProperties": False +} diff --git a/gns3server/schemas/vpcs.py b/gns3server/schemas/vpcs.py index 4e05dd9d..0de28c82 100644 --- a/gns3server/schemas/vpcs.py +++ b/gns3server/schemas/vpcs.py @@ -44,7 +44,7 @@ VPCS_CREATE_SCHEMA = { }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "startup_script": { "description": "Content of the VPCS startup script", @@ -73,7 +73,7 @@ VPCS_UPDATE_SCHEMA = { }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, }, "additionalProperties": False, @@ -108,11 +108,11 @@ VPCS_OBJECT_SCHEMA = { "description": "Console TCP port", "minimum": 1, "maximum": 65535, - "type": "integer" + "type": ["integer", "null"] }, "console_type": { "description": "Console type", - "enum": ["telnet"] + "enum": ["telnet", "none"] }, "project_id": { "description": "Project UUID", diff --git a/gns3server/schemas/vpcs_template.py b/gns3server/schemas/vpcs_template.py new file mode 100644 index 00000000..e0726b24 --- /dev/null +++ b/gns3server/schemas/vpcs_template.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 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 copy +from .template import BASE_TEMPLATE_PROPERTIES + + +VPCS_TEMPLATE_PROPERTIES = { + "base_script_file": { + "description": "Script file", + "type": "string", + "minLength": 1, + "default": "vpcs_base_config.txt" + }, + "console_type": { + "description": "Console type", + "enum": ["telnet", "none"], + "default": "telnet" + }, + "console_auto_start": { + "description": "Automatically start the console when the node has started", + "type": "boolean", + "default": False + }, +} + +VPCS_TEMPLATE_PROPERTIES.update(copy.deepcopy(BASE_TEMPLATE_PROPERTIES)) +VPCS_TEMPLATE_PROPERTIES["category"]["default"] = "guest" +VPCS_TEMPLATE_PROPERTIES["default_name_format"]["default"] = "PC{0}" +VPCS_TEMPLATE_PROPERTIES["symbol"]["default"] = ":/symbols/vpcs_guest.svg" + +VPCS_TEMPLATE_OBJECT_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "A VPCS template object", + "type": "object", + "properties": VPCS_TEMPLATE_PROPERTIES, + "additionalProperties": False +} diff --git a/gns3server/static/.gitkeep b/gns3server/static/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/gns3server/static/web-ui/.gitkeep b/gns3server/static/web-ui/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/gns3server/static/web-ui/3rdpartylicenses.txt b/gns3server/static/web-ui/3rdpartylicenses.txt new file mode 100644 index 00000000..319f3df2 --- /dev/null +++ b/gns3server/static/web-ui/3rdpartylicenses.txt @@ -0,0 +1,2351 @@ +@angular/animations +MIT + +@angular/cdk +MIT +The MIT License + +Copyright (c) 2019 Google LLC. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +@angular/common +MIT + +@angular/core +MIT + +@angular/forms +MIT + +@angular/material +MIT +The MIT License + +Copyright (c) 2019 Google LLC. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +@angular/material/button + +@angular/material/card + +@angular/material/checkbox + +@angular/material/core + +@angular/material/dialog + +@angular/material/divider + +@angular/material/expansion + +@angular/material/form-field + +@angular/material/icon + +@angular/material/list + +@angular/material/menu + +@angular/material/progress-bar + +@angular/material/progress-spinner + +@angular/material/radio + +@angular/material/select + +@angular/material/snack-bar + +@angular/material/sort + +@angular/material/stepper + +@angular/material/table + +@angular/material/tabs + +@angular/material/toolbar + +@angular/material/tooltip + +@angular/platform-browser +MIT + +@angular/router +MIT + +angular-persistence +MIT +MIT License + +Copyright (c) 2017 Scott O'Bryan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +angular2-hotkeys +MIT +The MIT License (MIT) + +Copyright (c) 2016 Nick Richardson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +angular2-indexeddb +MIT +The MIT License (MIT) + +Copyright (c) 2016 Gil Fink and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +bootstrap +MIT +The MIT License (MIT) + +Copyright (c) 2011-2019 Twitter, Inc. +Copyright (c) 2011-2019 The Bootstrap Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +css-tree +MIT +Copyright (C) 2016 by Roman Dvornov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +d3-array +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-axis +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-brush +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-chord +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-collection +BSD-3-Clause +Copyright 2010-2016, Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-color +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-contour +BSD-3-Clause +Copyright 2012-2017 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-dispatch +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-drag +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-dsv +BSD-3-Clause +Copyright 2013-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-ease +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +Copyright 2001 Robert Penner +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-force +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-format +BSD-3-Clause +Copyright 2010-2015 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-geo +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This license applies to GeographicLib, versions 1.12 and later. + +Copyright (c) 2008-2012, Charles Karney + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +d3-hierarchy +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-interpolate +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-ng2-service +MIT +The MIT License (MIT) + +Copyright (c) 2018 Thomas Wanzek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +d3-path +BSD-3-Clause +Copyright 2015-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-polygon +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-quadtree +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-random +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-scale +BSD-3-Clause +Copyright 2010-2015 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-scale-chromatic +BSD-3-Clause +Copyright 2010-2018 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Apache-Style Software License for ColorBrewer software and ColorBrewer Color +Schemes + +Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania State +University. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + + +d3-selection +BSD-3-Clause +Copyright (c) 2010-2018, Michael Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* The name Michael Bostock may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-selection-multi +BSD-3-Clause +Copyright (c) 2010-2016, Michael Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* The name Michael Bostock may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-shape +BSD-3-Clause +Copyright 2010-2015 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-time +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-time-format +BSD-3-Clause +Copyright 2010-2017 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-timer +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-transition +BSD-3-Clause +Copyright (c) 2010-2015, Michael Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* The name Michael Bostock may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +TERMS OF USE - EASING EQUATIONS + +Open source under the BSD License. + +Copyright 2001 Robert Penner +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +- Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +d3-voronoi +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Copyright (C) 2010-2013 Raymond Hill +https://github.com/gorhill/Javascript-Voronoi + +Licensed under The MIT License +http://en.wikipedia.org/wiki/MIT_License + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +d3-zoom +BSD-3-Clause +Copyright 2010-2016 Mike Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author nor the names of contributors may be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +hammerjs +MIT +The MIT License (MIT) + +Copyright (C) 2011-2014 by Jorik Tangelder (Eight Media) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +mousetrap +Apache-2.0 WITH LLVM-exception + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +--- Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + + +ng2-file-upload +MIT +The MIT License (MIT) + +Copyright (c) 2015-2017 Dmitriy Shekhovtsov +Copyright (c) 2015-1017 Valor Software + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +ngx-electron +MIT + +notosans-fontface +Apache-2.0 + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +raven-js +BSD-2-Clause +Copyright (c) 2018 Sentry (https://sentry.io) and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + + 3. Neither the name of the Sentry nor the names of its contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +rxjs +Apache-2.0 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +rxjs-compat +Apache-2.0 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +source-map +BSD-3-Clause + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +tslib +Apache-2.0 +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + + +uuid +MIT +The MIT License (MIT) + +Copyright (c) 2010-2016 Robert Kieffer and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +zone.js +MIT +The MIT License + +Copyright (c) 2016-2018 Google, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/gns3server/static/web-ui/MaterialIcons-Regular.012cf6a10129e2275d79.woff b/gns3server/static/web-ui/MaterialIcons-Regular.012cf6a10129e2275d79.woff new file mode 100644 index 00000000..b648a3ee Binary files /dev/null and b/gns3server/static/web-ui/MaterialIcons-Regular.012cf6a10129e2275d79.woff differ diff --git a/gns3server/static/web-ui/MaterialIcons-Regular.570eb83859dc23dd0eec.woff2 b/gns3server/static/web-ui/MaterialIcons-Regular.570eb83859dc23dd0eec.woff2 new file mode 100644 index 00000000..9fa21125 Binary files /dev/null and b/gns3server/static/web-ui/MaterialIcons-Regular.570eb83859dc23dd0eec.woff2 differ diff --git a/gns3server/static/web-ui/MaterialIcons-Regular.a37b0c01c0baf1888ca8.ttf b/gns3server/static/web-ui/MaterialIcons-Regular.a37b0c01c0baf1888ca8.ttf new file mode 100644 index 00000000..7015564a Binary files /dev/null and b/gns3server/static/web-ui/MaterialIcons-Regular.a37b0c01c0baf1888ca8.ttf differ diff --git a/gns3server/static/web-ui/MaterialIcons-Regular.e79bfd88537def476913.eot b/gns3server/static/web-ui/MaterialIcons-Regular.e79bfd88537def476913.eot new file mode 100644 index 00000000..70508eba Binary files /dev/null and b/gns3server/static/web-ui/MaterialIcons-Regular.e79bfd88537def476913.eot differ diff --git a/gns3server/static/web-ui/NotoSans-Bold.2ebcb523dec0ce7b98d0.eot b/gns3server/static/web-ui/NotoSans-Bold.2ebcb523dec0ce7b98d0.eot new file mode 100644 index 00000000..51202686 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Bold.2ebcb523dec0ce7b98d0.eot differ diff --git a/gns3server/static/web-ui/NotoSans-Bold.6a1f7cfe6252b44b6ea1.ttf b/gns3server/static/web-ui/NotoSans-Bold.6a1f7cfe6252b44b6ea1.ttf new file mode 100644 index 00000000..1db7886e Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Bold.6a1f7cfe6252b44b6ea1.ttf differ diff --git a/gns3server/static/web-ui/NotoSans-Bold.b85bf848c28799f5ad34.woff2 b/gns3server/static/web-ui/NotoSans-Bold.b85bf848c28799f5ad34.woff2 new file mode 100644 index 00000000..546cbefe Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Bold.b85bf848c28799f5ad34.woff2 differ diff --git a/gns3server/static/web-ui/NotoSans-Bold.c5802f2add9b067f419c.woff b/gns3server/static/web-ui/NotoSans-Bold.c5802f2add9b067f419c.woff new file mode 100644 index 00000000..a0d383ef Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Bold.c5802f2add9b067f419c.woff differ diff --git a/gns3server/static/web-ui/NotoSans-Bold.c65fb6ac34e7d7fd7ca1.svg b/gns3server/static/web-ui/NotoSans-Bold.c65fb6ac34e7d7fd7ca1.svg new file mode 100644 index 00000000..8751ddad --- /dev/null +++ b/gns3server/static/web-ui/NotoSans-Bold.c65fb6ac34e7d7fd7ca1.svg @@ -0,0 +1,12223 @@ + + + + +Created by FontForge 20170910 at Tue Sep 19 23:59:12 2017 + By Jimmy Wärting +Copyright 2015 Google Inc. All Rights Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gns3server/static/web-ui/NotoSans-BoldItalic.04cda025221e2faff092.svg b/gns3server/static/web-ui/NotoSans-BoldItalic.04cda025221e2faff092.svg new file mode 100644 index 00000000..35a41051 --- /dev/null +++ b/gns3server/static/web-ui/NotoSans-BoldItalic.04cda025221e2faff092.svg @@ -0,0 +1,12576 @@ + + + + +Created by FontForge 20170910 at Tue Sep 19 23:59:12 2017 + By Jimmy Wärting +Copyright 2015 Google Inc. All Rights Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gns3server/static/web-ui/NotoSans-BoldItalic.5a241c76c24e463ef9bc.woff2 b/gns3server/static/web-ui/NotoSans-BoldItalic.5a241c76c24e463ef9bc.woff2 new file mode 100644 index 00000000..ea9405d1 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-BoldItalic.5a241c76c24e463ef9bc.woff2 differ diff --git a/gns3server/static/web-ui/NotoSans-BoldItalic.b825226429966b6a83ec.woff b/gns3server/static/web-ui/NotoSans-BoldItalic.b825226429966b6a83ec.woff new file mode 100644 index 00000000..126bffcd Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-BoldItalic.b825226429966b6a83ec.woff differ diff --git a/gns3server/static/web-ui/NotoSans-BoldItalic.c55a24627ac4712e5fb9.ttf b/gns3server/static/web-ui/NotoSans-BoldItalic.c55a24627ac4712e5fb9.ttf new file mode 100644 index 00000000..385e6acb Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-BoldItalic.c55a24627ac4712e5fb9.ttf differ diff --git a/gns3server/static/web-ui/NotoSans-BoldItalic.df692395d4040e085ef9.eot b/gns3server/static/web-ui/NotoSans-BoldItalic.df692395d4040e085ef9.eot new file mode 100644 index 00000000..801abed1 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-BoldItalic.df692395d4040e085ef9.eot differ diff --git a/gns3server/static/web-ui/NotoSans-Italic.0b0b9b2b7159c9bc6463.woff2 b/gns3server/static/web-ui/NotoSans-Italic.0b0b9b2b7159c9bc6463.woff2 new file mode 100644 index 00000000..ddd83164 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Italic.0b0b9b2b7159c9bc6463.woff2 differ diff --git a/gns3server/static/web-ui/NotoSans-Italic.154da4697acc779b55af.ttf b/gns3server/static/web-ui/NotoSans-Italic.154da4697acc779b55af.ttf new file mode 100644 index 00000000..dc93fea6 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Italic.154da4697acc779b55af.ttf differ diff --git a/gns3server/static/web-ui/NotoSans-Italic.157af96cae049006e0cc.svg b/gns3server/static/web-ui/NotoSans-Italic.157af96cae049006e0cc.svg new file mode 100644 index 00000000..eead3405 --- /dev/null +++ b/gns3server/static/web-ui/NotoSans-Italic.157af96cae049006e0cc.svg @@ -0,0 +1,12589 @@ + + + + +Created by FontForge 20170910 at Tue Sep 19 23:59:24 2017 + By Jimmy Wärting +Copyright 2015 Google Inc. All Rights Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gns3server/static/web-ui/NotoSans-Italic.2ca6e82f8250c3d3d406.eot b/gns3server/static/web-ui/NotoSans-Italic.2ca6e82f8250c3d3d406.eot new file mode 100644 index 00000000..76747c29 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Italic.2ca6e82f8250c3d3d406.eot differ diff --git a/gns3server/static/web-ui/NotoSans-Italic.669a7edd16f586e69dfc.woff b/gns3server/static/web-ui/NotoSans-Italic.669a7edd16f586e69dfc.woff new file mode 100644 index 00000000..9e0e70bb Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Italic.669a7edd16f586e69dfc.woff differ diff --git a/gns3server/static/web-ui/NotoSans-Regular.0695760218a052feda99.woff b/gns3server/static/web-ui/NotoSans-Regular.0695760218a052feda99.woff new file mode 100644 index 00000000..aafa87a5 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Regular.0695760218a052feda99.woff differ diff --git a/gns3server/static/web-ui/NotoSans-Regular.21f6235482ecdf67217d.ttf b/gns3server/static/web-ui/NotoSans-Regular.21f6235482ecdf67217d.ttf new file mode 100644 index 00000000..0a01a062 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Regular.21f6235482ecdf67217d.ttf differ diff --git a/gns3server/static/web-ui/NotoSans-Regular.327e30c20b77c3d422c2.eot b/gns3server/static/web-ui/NotoSans-Regular.327e30c20b77c3d422c2.eot new file mode 100644 index 00000000..bea73b82 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Regular.327e30c20b77c3d422c2.eot differ diff --git a/gns3server/static/web-ui/NotoSans-Regular.505ad3dfb5803359b0cc.svg b/gns3server/static/web-ui/NotoSans-Regular.505ad3dfb5803359b0cc.svg new file mode 100644 index 00000000..85c5c356 --- /dev/null +++ b/gns3server/static/web-ui/NotoSans-Regular.505ad3dfb5803359b0cc.svg @@ -0,0 +1,12169 @@ + + + + +Created by FontForge 20170910 at Tue Sep 19 23:59:25 2017 + By Jimmy Wärting +Copyright 2015 Google Inc. All Rights Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gns3server/static/web-ui/NotoSans-Regular.e50c34178d20d5fa4ab3.woff2 b/gns3server/static/web-ui/NotoSans-Regular.e50c34178d20d5fa4ab3.woff2 new file mode 100644 index 00000000..38f15986 Binary files /dev/null and b/gns3server/static/web-ui/NotoSans-Regular.e50c34178d20d5fa4ab3.woff2 differ diff --git a/gns3server/static/web-ui/assets/favicon.ico b/gns3server/static/web-ui/assets/favicon.ico new file mode 100644 index 00000000..4d4ac85d Binary files /dev/null and b/gns3server/static/web-ui/assets/favicon.ico differ diff --git a/gns3server/static/web-ui/assets/gns3_icon.svg b/gns3server/static/web-ui/assets/gns3_icon.svg new file mode 100644 index 00000000..2a9b63d4 --- /dev/null +++ b/gns3server/static/web-ui/assets/gns3_icon.svg @@ -0,0 +1,88 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/gns3server/static/web-ui/assets/icons/mac/icon.icns b/gns3server/static/web-ui/assets/icons/mac/icon.icns new file mode 100644 index 00000000..ad2d9280 Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/mac/icon.icns differ diff --git a/gns3server/static/web-ui/assets/icons/png/1024x1024.png b/gns3server/static/web-ui/assets/icons/png/1024x1024.png new file mode 100644 index 00000000..d44d3e7f Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/png/1024x1024.png differ diff --git a/gns3server/static/web-ui/assets/icons/png/128x128.png b/gns3server/static/web-ui/assets/icons/png/128x128.png new file mode 100644 index 00000000..91ddc9f8 Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/png/128x128.png differ diff --git a/gns3server/static/web-ui/assets/icons/png/16x16.png b/gns3server/static/web-ui/assets/icons/png/16x16.png new file mode 100644 index 00000000..4412f733 Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/png/16x16.png differ diff --git a/gns3server/static/web-ui/assets/icons/png/24x24.png b/gns3server/static/web-ui/assets/icons/png/24x24.png new file mode 100644 index 00000000..dc16196e Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/png/24x24.png differ diff --git a/gns3server/static/web-ui/assets/icons/png/256x256.png b/gns3server/static/web-ui/assets/icons/png/256x256.png new file mode 100644 index 00000000..f66fcac0 Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/png/256x256.png differ diff --git a/gns3server/static/web-ui/assets/icons/png/32x32.png b/gns3server/static/web-ui/assets/icons/png/32x32.png new file mode 100644 index 00000000..2cbe7457 Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/png/32x32.png differ diff --git a/gns3server/static/web-ui/assets/icons/png/48x48.png b/gns3server/static/web-ui/assets/icons/png/48x48.png new file mode 100644 index 00000000..ed03c8fd Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/png/48x48.png differ diff --git a/gns3server/static/web-ui/assets/icons/png/512x512.png b/gns3server/static/web-ui/assets/icons/png/512x512.png new file mode 100644 index 00000000..64a64e3d Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/png/512x512.png differ diff --git a/gns3server/static/web-ui/assets/icons/png/64x64.png b/gns3server/static/web-ui/assets/icons/png/64x64.png new file mode 100644 index 00000000..2a52f494 Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/png/64x64.png differ diff --git a/gns3server/static/web-ui/assets/icons/win/icon.ico b/gns3server/static/web-ui/assets/icons/win/icon.ico new file mode 100644 index 00000000..d3e3a5a7 Binary files /dev/null and b/gns3server/static/web-ui/assets/icons/win/icon.ico differ diff --git a/gns3server/static/web-ui/assets/logo-header.png b/gns3server/static/web-ui/assets/logo-header.png new file mode 100644 index 00000000..1942c020 Binary files /dev/null and b/gns3server/static/web-ui/assets/logo-header.png differ diff --git a/gns3server/static/web-ui/assets/resources/images/filter-capture.svg b/gns3server/static/web-ui/assets/resources/images/filter-capture.svg new file mode 100644 index 00000000..aa95a12c --- /dev/null +++ b/gns3server/static/web-ui/assets/resources/images/filter-capture.svg @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gns3server/static/web-ui/assets/resources/images/filter.svg b/gns3server/static/web-ui/assets/resources/images/filter.svg new file mode 100644 index 00000000..a67a6f9c --- /dev/null +++ b/gns3server/static/web-ui/assets/resources/images/filter.svg @@ -0,0 +1,708 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gns3server/static/web-ui/assets/resources/images/inspect.svg b/gns3server/static/web-ui/assets/resources/images/inspect.svg new file mode 100644 index 00000000..f2573ffc --- /dev/null +++ b/gns3server/static/web-ui/assets/resources/images/inspect.svg @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gns3server/static/web-ui/favicon.ico b/gns3server/static/web-ui/favicon.ico new file mode 100644 index 00000000..8081c7ce Binary files /dev/null and b/gns3server/static/web-ui/favicon.ico differ diff --git a/gns3server/static/web-ui/index.html b/gns3server/static/web-ui/index.html new file mode 100644 index 00000000..ca24bfe4 --- /dev/null +++ b/gns3server/static/web-ui/index.html @@ -0,0 +1,40 @@ + + + + + GNS3 Web UI + + + + + + + + + + + + + + diff --git a/gns3server/static/web-ui/main.d7e59714b81de1a1004d.js b/gns3server/static/web-ui/main.d7e59714b81de1a1004d.js new file mode 100644 index 00000000..198b75d1 --- /dev/null +++ b/gns3server/static/web-ui/main.d7e59714b81de1a1004d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{"+/L5":function(n,e,t){var l=t("t1UP").isCustomProperty,o=t("vd7W").TYPE,r=o.Identifier,i=o.Colon,a=o.ExclamationMark,u=o.Solidus,s=o.Asterisk,d=o.DollarSign,c=o.HyphenMinus,p=o.Semicolon,f=o.PlusSign,h=o.NumberSign;function m(n){return this.Raw(n,a,p,!1,!0)}function v(n){return this.Raw(n,a,p,!1,!1)}function g(){var n=this.scanner.currentToken,e=this.Value();return"Raw"!==e.type&&!1===this.scanner.eof&&this.scanner.tokenType!==p&&this.scanner.tokenType!==a&&!1===this.scanner.isBalanceEdge(n)&&this.scanner.error(),e}n.exports={name:"Declaration",structure:{important:[Boolean,String],property:String,value:["Value","Raw"]},parse:function(){var n,e=this.scanner.tokenStart,t=this.scanner.currentToken,o=(function(){var n=this.scanner.tokenStart,e=0;switch(this.scanner.tokenType){case s:case d:case f:case h:e=1;break;case u:e=this.scanner.lookupType(1)===u?2:1}return this.scanner.lookupType(e)===c&&e++,e&&this.scanner.skip(e),this.scanner.eat(r),this.scanner.substrToCursor(n)}).call(this),b=l(o),y=b?this.parseCustomProperty:this.parseValue,_=b?v:m,w=!1;return this.scanner.skipSC(),this.scanner.eat(i),b||this.scanner.skipSC(),n=y?this.parseWithFallback(g,_):_.call(this,this.scanner.currentToken),this.scanner.tokenType===a&&(w=function(n){n.eat(a),n.skipSC();var e=n.consume(r);return"important"===e||e}(this.scanner),this.scanner.skipSC()),!1===this.scanner.eof&&this.scanner.tokenType!==p&&!1===this.scanner.isBalanceEdge(t)&&this.scanner.error(),{type:"Declaration",loc:this.getLocation(e,this.scanner.tokenStart),important:w,property:o,value:n}},generate:function(n){this.chunk(n.property),this.chunk(":"),this.node(n.value),n.important&&this.chunk(!0===n.important?"!important":"!"+n.important)},walkContext:"declaration"}},"+Kd2":function(n,e,t){var l=t("vd7W").TYPE,o=l.Identifier,r=l.Comma,i=l.Semicolon,a=l.HyphenMinus,u=l.ExclamationMark;n.exports=function(){var n=this.createList();this.scanner.skipSC();var e=this.scanner.tokenStart;return this.scanner.eat(a),this.scanner.source.charCodeAt(this.scanner.tokenStart)!==a&&this.scanner.error("HyphenMinus is expected"),this.scanner.eat(o),n.push({type:"Identifier",loc:this.getLocation(e,this.scanner.tokenStart),name:this.scanner.substrToCursor(e)}),this.scanner.skipSC(),this.scanner.tokenType===r&&(n.push(this.Operator()),n.push(this.parseCustomProperty?this.Value(null):this.Raw(this.scanner.currentToken,u,i,!1,!1))),n}},"+gEr":function(n,e,t){"use strict";t.d(e,"a",function(){return i}),t.d(e,"b",function(){return a});var l=t("mrSG"),o=t("MGBS"),r=t("zotm"),i={leading:!0,trailing:!1};function a(n,e){return void 0===e&&(e=i),function(t){return t.lift(new u(n,e.leading,e.trailing))}}var u=function(){function n(n,e,t){this.durationSelector=n,this.leading=e,this.trailing=t}return n.prototype.call=function(n,e){return e.subscribe(new s(n,this.durationSelector,this.leading,this.trailing))},n}(),s=function(n){function e(e,t,l,o){var r=n.call(this,e)||this;return r.destination=e,r.durationSelector=t,r._leading=l,r._trailing=o,r._hasValue=!1,r}return l.__extends(e,n),e.prototype._next=function(n){this._hasValue=!0,this._sendValue=n,this._throttled||(this._leading?this.send():this.throttle(n))},e.prototype.send=function(){var n=this._sendValue;this._hasValue&&(this.destination.next(n),this.throttle(n)),this._hasValue=!1,this._sendValue=null},e.prototype.throttle=function(n){var e=this.tryDurationSelector(n);e&&this.add(this._throttled=Object(r.a)(this,e))},e.prototype.tryDurationSelector=function(n){try{return this.durationSelector(n)}catch(e){return this.destination.error(e),null}},e.prototype.throttlingDone=function(){var n=this._throttled,e=this._trailing;n&&n.unsubscribe(),this._throttled=null,e&&this.send()},e.prototype.notifyNext=function(n,e,t,l,o){this.throttlingDone()},e.prototype.notifyComplete=function(){this.throttlingDone()},e}(o.a)},"+ryv":function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var l=t("CcnG");e.HotkeyOptions=new l.InjectionToken("HotkeyOptions")},"+tJ4":function(n,e,t){"use strict";t.d(e,"a",function(){return l});var l=function(n){return function(e){for(var t=0,l=n.length;t=0}},"/BcF":function(n,e){n.exports={name:"Selector",structure:{children:[["TypeSelector","IdSelector","ClassSelector","AttributeSelector","PseudoClassSelector","PseudoElementSelector","Combinator","WhiteSpace"]]},parse:function(){var n=this.readSequence(this.scope.Selector);return null===this.getFirstListNode(n)&&this.scanner.error("Selector is expected"),{type:"Selector",loc:this.getLocationFromList(n),children:n}},generate:function(n){this.children(n)}}},"/PH2":function(n,e,t){"use strict";t.d(e,"a",function(){return i});var l=t("mrSG"),o=t("MGBS"),r=t("zotm");function i(){for(var n=[],e=0;e0){var i=r.indexOf(t);-1!==i&&r.splice(i,1)}},e.prototype.notifyComplete=function(){},e.prototype._next=function(n){if(0===this.toRespond.length){var e=[n].concat(this.values);this.project?this._tryProject(e):this.destination.next(e)}},e.prototype._tryProject=function(n){var e;try{e=this.project.apply(this,n)}catch(t){return void this.destination.error(t)}this.destination.next(e)},e}(o.a)},"/WYv":function(n,e,t){"use strict";function l(n){return!!n&&"function"!=typeof n.subscribe&&"function"==typeof n.then}t.d(e,"a",function(){return l})},"/ojb":function(n,e,t){"use strict";t.d(e,"a",function(){return i});var l=t("mrSG"),o=t("FFOo"),r=t("T1DM");function i(n,e){return void 0===e&&(e=r.a),function(t){return t.lift(new a(n,e))}}var a=function(){function n(n,e){this.period=n,this.scheduler=e}return n.prototype.call=function(n,e){return e.subscribe(new u(n,this.period,this.scheduler))},n}(),u=function(n){function e(e,t,l){var o=n.call(this,e)||this;return o.period=t,o.scheduler=l,o.hasValue=!1,o.add(l.schedule(s,t,{subscriber:o,period:t})),o}return l.__extends(e,n),e.prototype._next=function(n){this.lastValue=n,this.hasValue=!0},e.prototype.notifyNext=function(){this.hasValue&&(this.hasValue=!1,this.destination.next(this.lastValue))},e}(o.a);function s(n){var e=n.period;n.subscriber.notifyNext(),this.schedule(n,e)}},0:function(n,e,t){n.exports=t("zUnb")},"0/uQ":function(n,e,t){"use strict";t.d(e,"a",function(){return i});var l=t("6blF"),o=t("Fxb1"),r=t("i4X3");function i(n,e){return e?Object(r.a)(n,e):n instanceof l.a?n:new l.a(Object(o.a)(n))}},"06ho":function(n,e){n.exports={name:"Value",structure:{children:[[]]},parse:function(){var n=this.scanner.tokenStart,e=this.readSequence(this.scope.Value);return{type:"Value",loc:this.getLocation(n,this.scanner.tokenStart),children:e}},generate:function(n){this.children(n)}}},"0GsU":function(n,e,t){"use strict";t.d(e,"a",function(){return a});var l=t("mrSG"),o=t("MGBS"),r=t("rPjj"),i=t("zotm");function a(n){return function(e){return e.lift(new u(n))}}var u=function(){function n(n){this.notifier=n}return n.prototype.call=function(n,e){return e.subscribe(new s(n,this.notifier))},n}(),s=function(n){function e(e,t){var l=n.call(this,e)||this;l.hasValue=!1;var o=new r.a(l,void 0,void 0);return l.add(o),l.innerSubscription=o,Object(i.a)(l,t,void 0,void 0,o),l}return l.__extends(e,n),e.prototype._next=function(e){this.hasValue&&n.prototype._next.call(this,e)},e.prototype.notifyNext=function(n,e,t,l,o){this.hasValue=!0,this.innerSubscription&&this.innerSubscription.unsubscribe()},e.prototype.notifyComplete=function(){},e}(o.a)},"0mNj":function(n,e,t){"use strict";t.d(e,"a",function(){return r});var l=t("mrSG"),o=t("FFOo");function r(n){return function(e){return e.lift(new i(n))}}var i=function(){function n(n){this.total=n}return n.prototype.call=function(n,e){return e.subscribe(new a(n,this.total))},n}(),a=function(n){function e(e,t){var l=n.call(this,e)||this;return l.total=t,l.count=0,l}return l.__extends(e,n),e.prototype._next=function(n){++this.count>this.total&&this.destination.next(n)},e}(o.a)},"0zd0":function(n,e,t){"use strict";t.d(e,"a",function(){return a});var l=t("T1DM"),o=t("3U0i"),r=t("ceCD"),i=t("XlPw");function a(n,e){return void 0===e&&(e=l.a),Object(r.a)(n,Object(i.a)(new o.a),e)}},"14Nl":function(n,e,t){"use strict";t.d(e,"a",function(){return i});var l=t("mrSG"),o=t("FFOo"),r=t("b7mW");function i(n){return function(e){return e.lift(new a(n))}}var a=function(){function n(n){if(this._skipCount=n,this._skipCount<0)throw new r.a}return n.prototype.call=function(n,e){return e.subscribe(0===this._skipCount?new o.a(n):new u(n,this._skipCount))},n}(),u=function(n){function e(e,t){var l=n.call(this,e)||this;return l._skipCount=t,l._count=0,l._ring=new Array(t),l}return l.__extends(e,n),e.prototype._next=function(n){var e=this._skipCount,t=this._count++;if(t";break;case"Property":o="<'"+e.name+"'>";break;case"Keyword":o=e.name;break;case"AtKeyword":o="@"+e.name;break;case"Function":o=e.name+"(";break;case"String":case"Token":o=e.value;break;case"Comma":o=",";break;default:throw new Error("Unknown node type `"+e.type+"`")}return l(o,e)}(n,o,l)}},"2WpN":function(n,e,t){"use strict";t.d(e,"a",function(){return i});var l=t("mrSG"),o=t("FFOo"),r=t("pugT");function i(n){return function(e){return e.lift(new a(n))}}var a=function(){function n(n){this.callback=n}return n.prototype.call=function(n,e){return e.subscribe(new u(n,this.callback))},n}(),u=function(n){function e(e,t){var l=n.call(this,e)||this;return l.add(new r.a(t)),l}return l.__extends(e,n),e}(o.a)},"2ePl":function(n,e,t){"use strict";t.d(e,"a",function(){return l});var l=function(n){return n&&"number"==typeof n.length&&"function"!=typeof n}},"2pxp":function(n,e){n.exports={parse:function(){return this.createSingleNodeList(this.SelectorList())}}},"2yAJ":function(n,e){function t(n,e){var t=(65535&n)+(65535&e);return(n>>16)+(e>>16)+(t>>16)<<16|65535&t}function l(n,e,l,o,r,i){return t((a=t(t(e,n),t(o,i)))<<(u=r)|a>>>32-u,l);var a,u}function o(n,e,t,o,r,i,a){return l(e&t|~e&o,n,e,r,i,a)}function r(n,e,t,o,r,i,a){return l(e&o|t&~o,n,e,r,i,a)}function i(n,e,t,o,r,i,a){return l(e^t^o,n,e,r,i,a)}function a(n,e,t,o,r,i,a){return l(t^(e|~o),n,e,r,i,a)}function u(n,e){var l,u,s,d,c;n[e>>5]|=128<>>9<<4)]=e;var p=1732584193,f=-271733879,h=-1732584194,m=271733878;for(l=0;l>5]>>>e%32&255);return t}function d(n){var e,t=[];for(t[(n.length>>2)-1]=void 0,e=0;e>5]|=(255&n.charCodeAt(e/8))<>>4&15)+"0123456789abcdef".charAt(15&e);return l}function p(n){return unescape(encodeURIComponent(n))}function f(n){return function(n){return s(u(d(n),8*n.length))}(p(n))}function h(n,e){return function(n,e){var t,l,o=d(n),r=[],i=[];for(r[15]=i[15]=void 0,o.length>16&&(o=u(o,8*n.length)),t=0;t<16;t+=1)r[t]=909522486^o[t],i[t]=1549556828^o[t];return l=u(r.concat(d(e)),512+8*e.length),s(u(i.concat(l),640))}(p(n),p(e))}n.exports=function(n,e,t){return e?t?h(e,n):c(h(e,n)):t?f(n):c(f(n))}},"2yWD":function(n,e,t){var l=t("XDwu");n.exports={SyntaxParseError:function(n,e,t){var o=l("SyntaxParseError",n);return o.input=e,o.offset=t,o.rawMessage=n,o.message=o.rawMessage+"\n "+o.input+"\n--"+new Array((o.offset||o.input.length)+1).join("-")+"^",o}}},"31qQ":function(n,e,t){"use strict";t.d(e,"a",function(){return i});var l=t("mrSG"),o=t("MGBS"),r=t("zotm");function i(){return function(n){return n.lift(new a)}}var a=function(){function n(){}return n.prototype.call=function(n,e){return e.subscribe(new u(n))},n}(),u=function(n){function e(e){var t=n.call(this,e)||this;return t.hasCompleted=!1,t.hasSubscription=!1,t}return l.__extends(e,n),e.prototype._next=function(n){this.hasSubscription||(this.hasSubscription=!0,this.add(Object(r.a)(this,n)))},e.prototype._complete=function(){this.hasCompleted=!0,this.hasSubscription||this.destination.complete()},e.prototype.notifyComplete=function(n){this.remove(n),this.hasSubscription=!1,this.hasCompleted&&this.destination.complete()},e}(o.a)},"33Dm":function(n,e,t){var l=t("vd7W").TYPE,o=l.WhiteSpace,r=l.Comment,i=l.Identifier,a=l.LeftParenthesis;n.exports={name:"MediaQuery",structure:{children:[["Identifier","MediaFeature","WhiteSpace"]]},parse:function(){this.scanner.skipSC();var n=this.createList(),e=null,t=null;n:for(;!this.scanner.eof;){switch(this.scanner.tokenType){case r:this.scanner.next();continue;case o:t=this.WhiteSpace();continue;case i:e=this.Identifier();break;case a:e=this.MediaFeature();break;default:break n}null!==t&&(n.push(t),t=null),n.push(e)}return null===e&&this.scanner.error("Identifier or parenthesis is expected"),{type:"MediaQuery",loc:this.getLocationFromList(n),children:n}},generate:function(n){this.children(n)}}},"3J/R":function(n,e,t){"use strict";t.d(e,"a",function(){return r});var l=t("26FU"),o=t("xlPZ");function r(n){return function(e){return Object(o.a)(new l.a(n))(e)}}},"3U0i":function(n,e,t){"use strict";function l(){return Error.call(this),this.message="Timeout has occurred",this.name="TimeoutError",this}t.d(e,"a",function(){return o}),l.prototype=Object.create(Error.prototype);var o=l},"3fWJ":function(n,e,t){"use strict";function l(){return Error.call(this),this.message="no elements in sequence",this.name="EmptyError",this}t.d(e,"a",function(){return o}),l.prototype=Object.create(Error.prototype);var o=l},"3lFr":function(n,e,t){e.SourceMapGenerator=t("TTsC").SourceMapGenerator,e.SourceMapConsumer=t("NSjB").SourceMapConsumer,e.SourceNode=t("5EiF").SourceNode},"41IB":function(n,e,t){"use strict";t.d(e,"a",function(){return r});var l=t("mrSG"),o=t("FFOo");function r(){return function(n){return n.lift(new i)}}var i=function(){function n(){}return n.prototype.call=function(n,e){return e.subscribe(new a(n))},n}(),a=function(n){function e(e){return n.call(this,e)||this}return l.__extends(e,n),e.prototype._next=function(n){n.observe(this.destination)},e}(o.a)},"4HHr":function(n,e,t){"use strict";var l=Object.prototype.hasOwnProperty,o=function(){};function r(n){return"function"==typeof n?n:o}function i(n,e){return function(t,l,o){t.type===e&&n.call(this,t,l,o)}}function a(n,e){var t=e.structure,o=[];for(var r in t)if(!1!==l.call(t,r)){var i=t[r],a={name:r,type:!1,nullable:!1};Array.isArray(t[r])||(i=[t[r]]);for(var u=0;u=0;--e)t[e]===n&&t.splice(e,1)},v.uninstall=function(){e&&(r.onerror=n,e=!1,n=void 0),t=[]},v}(),o.computeStackTrace=function(){function n(n){if(void 0!==n.stack&&n.stack){for(var e,t,l,o=/^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,r=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,i=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,u=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,d=/\((\S*)(?::(\d+))(?::(\d+))\)/,c=n.stack.split("\n"),p=[],f=(/^(.*) is undefined$/.exec(n.message),0),h=c.length;f eval")>-1&&(e=u.exec(t[3]))?(t[3]=e[1],t[4]=e[2],t[5]=null):0!==f||t[5]||void 0===n.columnNumber||(p[0].column=n.columnNumber+1),l={url:t[3],func:t[1]||a,args:t[2]?t[2].split(","):[],line:t[4]?+t[4]:null,column:t[5]?+t[5]:null}}if(!l.func&&l.line&&(l.func=a),l.url&&"blob:"===l.url.substr(0,5)){var v=new XMLHttpRequest;if(v.open("GET",l.url,!1),v.send(null),200===v.status){var g=v.responseText||"",b=(g=g.slice(-300)).match(/\/\/# sourceMappingURL=(.*)$/);if(b){var y=b[1];"~"===y.charAt(0)&&(y=("undefined"==typeof document||null==document.location?"":document.location.origin?document.location.origin:document.location.protocol+"//"+document.location.hostname+(document.location.port?":"+document.location.port:""))+y.slice(1)),l.url=y.slice(0,-4)}}}p.push(l)}return p.length?{name:n.name,message:n.message,url:s(),stack:p}:null}}function e(n,e,t,l){var o={url:e,line:t};if(o.url&&o.line){if(n.incomplete=!1,o.func||(o.func=a),n.stack.length>0&&n.stack[0].url===o.url){if(n.stack[0].line===o.line)return!1;if(!n.stack[0].line&&n.stack[0].func===o.func)return n.stack[0].line=o.line,!1}return n.stack.unshift(o),n.partial=!0,!0}return n.incomplete=!0,!1}function t(n,r){for(var i,u,d=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,c=[],p={},f=!1,h=t.caller;h&&!f;h=h.caller)if(h!==l&&h!==o.report){if(u={url:null,func:a,line:null,column:null},h.name?u.func=h.name:(i=d.exec(h.toString()))&&(u.func=i[1]),void 0===u.func)try{u.func=i.input.substring(0,i.input.indexOf("{"))}catch(v){}p[""+h]?f=!0:p[""+h]=!0,c.push(u)}r&&c.splice(0,r);var m={name:n.name,message:n.message,url:s(),stack:c};return e(m,n.sourceURL||n.fileName,n.line||n.lineNumber),m}function l(e,l){var r=null;l=null==l?0:+l;try{if(r=n(e))return r}catch(i){if(o.debug)throw i}try{if(r=t(e,l+1))return r}catch(i){if(o.debug)throw i}return{name:e.name,message:e.message,url:s()}}return l.augmentStackTraceWithInitialElement=e,l.computeStackTraceFromStackProp=n,l}(),n.exports=o},"4fRq":function(n,e){var t="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(t){var l=new Uint8Array(16);n.exports=function(){return t(l),l}}else{var o=new Array(16);n.exports=function(){for(var n,e=0;e<16;e++)0==(3&e)&&(n=4294967296*Math.random()),o[e]=n>>>((3&e)<<3)&255;return o}}},"4njK":function(n,e){n.exports={name:"Raw",structure:{value:String},parse:function(n,e,t,l,o){var r,i=this.scanner.getTokenStart(n);return this.scanner.skip(this.scanner.getRawLength(n,e,t,l)),r=o&&this.scanner.tokenStart>i?this.scanner.getOffsetExcludeWS():this.scanner.tokenStart,{type:"Raw",loc:this.getLocation(i,r),value:this.scanner.source.substring(i,r)}},generate:function(n){this.chunk(n.value)}}},"4vYp":function(n){n.exports={generic:!0,types:{"absolute-size":"xx-small | x-small | small | medium | large | x-large | xx-large","alpha-value":" | ","angle-percentage":" | ","animateable-feature":"scroll-position | contents | ",attachment:"scroll | fixed | local","auto-repeat":"repeat( [ auto-fill | auto-fit ] , [ ? ]+ ? )","auto-track-list":"[ ? [ | ] ]* ? [ ? [ | ] ]* ?","baseline-position":"[ first | last ]? baseline","basic-shape":" | | | ","bg-image":"none | ","bg-layer":" || [ / ]? || || || || ","bg-position":"[ [ left | center | right | top | bottom | ] | [ left | center | right | ] [ top | center | bottom | ] | [ center | [ left | right ] ? ] && [ center | [ top | bottom ] ? ] ]","bg-size":"[ | auto ]{1,2} | cover | contain","blur()":"blur( )","blend-mode":"normal | multiply | screen | overlay | darken | lighten | color-dodge | color-burn | hard-light | soft-light | difference | exclusion | hue | saturation | color | luminosity",box:"border-box | padding-box | content-box","br-style":"none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset","br-width":" | thin | medium | thick","brightness()":"brightness( )","calc()":"calc( )","calc-sum":" [ [ '+' | '-' ] ]*","calc-product":" [ '*' | '/' ]*","calc-value":" | | | ( )","cf-final-image":" | ","cf-mixing-image":"? && ","circle()":"circle( [ ]? [ at ]? )","clip-source":"",color:" | | | | | | currentcolor | ","color-stop":" ?","color-stop-list":"#{2,}","common-lig-values":"[ common-ligatures | no-common-ligatures ]","composite-style":"clear | copy | source-over | source-in | source-out | source-atop | destination-over | destination-in | destination-out | destination-atop | xor","compositing-operator":"add | subtract | intersect | exclude","contextual-alt-values":"[ contextual | no-contextual ]","content-distribution":"space-between | space-around | space-evenly | stretch","content-list":"[ | contents | | | | counter( , <'list-style-type'>? ) ]+","content-position":"center | start | end | flex-start | flex-end","content-replacement":"","contrast()":"contrast( [ ] )","counter-style":" | symbols( )","counter-style-name":"","cross-fade()":"cross-fade( , ? )","cubic-bezier-timing-function":"ease | ease-in | ease-out | ease-in-out | cubic-bezier( , , , )","deprecated-system-color":"ActiveBorder | ActiveCaption | AppWorkspace | Background | ButtonFace | ButtonHighlight | ButtonShadow | ButtonText | CaptionText | GrayText | Highlight | HighlightText | InactiveBorder | InactiveCaption | InactiveCaptionText | InfoBackground | InfoText | Menu | MenuText | Scrollbar | ThreeDDarkShadow | ThreeDFace | ThreeDHighlight | ThreeDLightShadow | ThreeDShadow | Window | WindowFrame | WindowText","discretionary-lig-values":"[ discretionary-ligatures | no-discretionary-ligatures ]","display-box":"contents | none","display-inside":"flow | flow-root | table | flex | grid | subgrid | ruby","display-internal":"table-row-group | table-header-group | table-footer-group | table-row | table-cell | table-column-group | table-column | table-caption | ruby-base | ruby-text | ruby-base-container | ruby-text-container","display-legacy":"inline-block | inline-list-item | inline-table | inline-flex | inline-grid","display-listitem":"? && [ flow | flow-root ]? && list-item","display-outside":"block | inline | run-in","drop-shadow()":"drop-shadow( {2,3} ? )","east-asian-variant-values":"[ jis78 | jis83 | jis90 | jis04 | simplified | traditional ]","east-asian-width-values":"[ full-width | proportional-width ]","element()":"element( )","ellipse()":"ellipse( [ {2} ]? [ at ]? )","ending-shape":"circle | ellipse","explicit-track-list":"[ ? ]+ ?","family-name":" | +","feature-tag-value":" [ | on | off ]?","feature-value-name":"","fill-rule":"nonzero | evenodd","filter-function":" | | | | | | | | | ","filter-function-list":"[ | ]+","final-bg-layer":"<'background-color'> || || [ / ]? || || || || ","fit-content()":"fit-content( [ | ] )","fixed-breadth":"","fixed-repeat":"repeat( [ ] , [ ? ]+ ? )","fixed-size":" | minmax( , ) | minmax( , )","font-variant-css21":"[ normal | small-caps ]","frames-timing-function":"frames( )","frequency-percentage":" | ","generic-family":"serif | sans-serif | cursive | fantasy | monospace | -apple-system","generic-name":"serif | sans-serif | cursive | fantasy | monospace","geometry-box":" | fill-box | stroke-box | view-box",gradient:"<-legacy-gradient> | | | | ","grayscale()":"grayscale( )","grid-line":"auto | | [ && ? ] | [ span && [ || ] ]","historical-lig-values":"[ historical-ligatures | no-historical-ligatures ]","hsl()":"hsl( [ / ]? ) | hsl( , , , ? )","hsla()":"hsla( [ / ]? ) | hsla( , , , ? )",hue:" | ","hue-rotate()":"hue-rotate( )",image:" | | | | | ","image()":"image( [ [ | ]? , ? ]! )","image-set()":"image-set( # )","image-set-option":"[ | ] ","inflexible-breadth":" | | min-content | max-content | auto","inset()":"inset( {1,4} [ round <'border-radius'> ]? )","invert()":"invert( )","keyframes-name":" | ","keyframe-selector":"from | to | ","leader()":"leader( )","leader-type":"dotted | solid | space | ","length-percentage":" | ","line-names":"'[' * ']'","line-name-list":"[ | ]+","linear-gradient()":"linear-gradient( [ | to ]? , )","mask-layer":" || [ / ]? || || || [ | no-clip ] || || ","mask-position":"[ | left | center | right ] [ | top | center | bottom ]?","mask-reference":"none | | ","mask-source":"","masking-mode":"alpha | luminance | match-source","matrix()":"matrix( [, ]{5} )","matrix3d()":"matrix3d( [, ]{15} )","media-type":"","mf-boolean":"","mf-name":"","minmax()":"minmax( [ | | | min-content | max-content | auto ] , [ | | | min-content | max-content | auto ] )","named-color":"transparent | aliceblue | antiquewhite | aqua | aquamarine | azure | beige | bisque | black | blanchedalmond | blue | blueviolet | brown | burlywood | cadetblue | chartreuse | chocolate | coral | cornflowerblue | cornsilk | crimson | cyan | darkblue | darkcyan | darkgoldenrod | darkgray | darkgreen | darkgrey | darkkhaki | darkmagenta | darkolivegreen | darkorange | darkorchid | darkred | darksalmon | darkseagreen | darkslateblue | darkslategray | darkslategrey | darkturquoise | darkviolet | deeppink | deepskyblue | dimgray | dimgrey | dodgerblue | firebrick | floralwhite | forestgreen | fuchsia | gainsboro | ghostwhite | gold | goldenrod | gray | green | greenyellow | grey | honeydew | hotpink | indianred | indigo | ivory | khaki | lavender | lavenderblush | lawngreen | lemonchiffon | lightblue | lightcoral | lightcyan | lightgoldenrodyellow | lightgray | lightgreen | lightgrey | lightpink | lightsalmon | lightseagreen | lightskyblue | lightslategray | lightslategrey | lightsteelblue | lightyellow | lime | limegreen | linen | magenta | maroon | mediumaquamarine | mediumblue | mediumorchid | mediumpurple | mediumseagreen | mediumslateblue | mediumspringgreen | mediumturquoise | mediumvioletred | midnightblue | mintcream | mistyrose | moccasin | navajowhite | navy | oldlace | olive | olivedrab | orange | orangered | orchid | palegoldenrod | palegreen | paleturquoise | palevioletred | papayawhip | peachpuff | peru | pink | plum | powderblue | purple | rebeccapurple | red | rosybrown | royalblue | saddlebrown | salmon | sandybrown | seagreen | seashell | sienna | silver | skyblue | slateblue | slategray | slategrey | snow | springgreen | steelblue | tan | teal | thistle | tomato | turquoise | violet | wheat | white | whitesmoke | yellow | yellowgreen | <-non-standard-color>","namespace-prefix":"","number-percentage":" | ","numeric-figure-values":"[ lining-nums | oldstyle-nums ]","numeric-fraction-values":"[ diagonal-fractions | stacked-fractions ]","numeric-spacing-values":"[ proportional-nums | tabular-nums ]","opacity()":"opacity( [ ] )","overflow-position":"unsafe | safe","outline-radius":"","perspective()":"perspective( )","polygon()":"polygon( ? , [ ]# )",position:"[ [ left | center | right ] || [ top | center | bottom ] | [ left | center | right | ] [ top | center | bottom | ]? | [ [ left | right ] ] && [ [ top | bottom ] ] ]",quote:"open-quote | close-quote | no-open-quote | no-close-quote","radial-gradient()":"radial-gradient( [ || ]? [ at ]? , )","relative-size":"larger | smaller","repeat-style":"repeat-x | repeat-y | [ repeat | space | round | no-repeat ]{1,2}","repeating-linear-gradient()":"repeating-linear-gradient( [ | to ]? , )","repeating-radial-gradient()":"repeating-radial-gradient( [ || ]? [ at ]? , )","rgb()":"rgb( {3} [ / ]? ) | rgb( {3} [ / ]? ) | rgb( #{3} , ? ) | rgb( #{3} , ? )","rgba()":"rgba( {3} [ / ]? ) | rgba( {3} [ / ]? ) | rgba( #{3} , ? ) | rgba( #{3} , ? )","rotate()":"rotate( )","rotate3d()":"rotate3d( , , , )","rotateX()":"rotateX( )","rotateY()":"rotateY( )","rotateZ()":"rotateZ( )","saturate()":"saturate( )","scale()":"scale( [, ]? )","scale3d()":"scale3d( , , )","scaleX()":"scaleX( )","scaleY()":"scaleY( )","scaleZ()":"scaleZ( )","self-position":"center | start | end | self-start | self-end | flex-start | flex-end","shape-radius":" | closest-side | farthest-side","skew()":"skew( [, ]? )","skewX()":"skewX( )","skewY()":"skewY( )","sepia()":"sepia( )",shadow:"inset? && {2,4} && ?","shadow-t":"[ {2,3} && ? ]",shape:"rect( [ [ , , , ] | [ ] ] )","shape-box":" | margin-box","side-or-corner":"[ left | right ] || [ top | bottom ]","single-animation":"