Compare commits

...
119 Commits
Author SHA1 Message Date
grossmj 369fcaa512 Release v2.2.53 2025-01-21 11:52:11 +10:00
grossmj 7b7d3d676f Bundle web-ui v2.2.53 2025-01-21 11:43:11 +10:00
grossmj d1186b2acc Sync appliances 2025-01-21 11:29:28 +10:00
grossmj bd58196817 Add more information when patching .vbox file. Ref https://github.com/GNS3/gns3-gui/issues/3542 2025-01-20 13:22:22 +10:00
grossmj ccc8974d92 Fix tests 2024-12-30 16:14:33 +07:00
grossmj 0090ff3722 Increase timeout to run compute HTTP queries. Fixes #2461 2024-12-30 16:10:04 +07:00
grossmj 2c727c6bd2 Use 'allow_methods="*"' in aiohttp_cors.ResourceOptions(). Fixes #2459 2024-12-30 11:06:19 +07:00
grossmj 13b0caef4f Upgrade dependencies 2024-12-30 10:49:35 +07:00
grossmj 8ed1fa6ad5 Merge branch 'master' into 2.2 2024-12-28 18:03:39 +07:00
Jeremy Grossmann a689a55937 Merge pull request #2467 from GNS3/update-remote-install-script
Use iptables to block IOU home call
2024-12-28 18:01:25 +07:00
grossmj 1c0b0ae423 Remove blocking IOU phone home call. 2024-12-28 18:00:22 +07:00
grossmj ad7813d04b Use iptables to block IOU home call 2024-12-28 17:50:59 +07:00
Jeremy Grossmann 685bf88005 Merge pull request #2457 from GNS3/update-remote-install-script
Update remote install script
2024-12-22 22:07:33 +07:00
grossmj a1090a3da8 Fallback when cannot use deb822 format 2024-12-22 21:52:18 +07:00
grossmj c8e5b41f39 Add compatibility for earlier Ubuntu versions 2024-12-22 21:29:05 +07:00
grossmj 94b5d3e636 Update remote-install.sh to support a custom repository and the deb822 source format 2024-12-22 20:26:24 +07:00
grossmj df56955bf0 Use license instead of licence 2024-12-17 15:01:01 +07:00
grossmj 423d3fd82b Fix tests 2024-12-16 18:30:30 +07:00
grossmj 86fbae00e1 Fix issue with iourc_path 2024-12-16 18:16:42 +07:00
grossmj 91e9fa1cbc Fix tests 2024-12-16 18:13:51 +07:00
grossmj 6314dd3c35 Fix: do not use the iourc file if IOU licence check is not enabled 2024-12-16 18:07:02 +07:00
Jeremy Grossmann e94b55e3bf Merge pull request #2452 from GNS3/release/v2.2.52
release/v2.2.52
2024-12-02 11:36:09 +10:00
grossmj 6c521b5f7a Development on 2.2.53.dev1 2024-12-02 11:33:59 +10:00
grossmj a8014da10b Release v2.2.52 2024-12-02 11:14:23 +10:00
grossmj f6080013e3 Bundle web-ui v2.2.52 2024-12-02 11:09:30 +10:00
grossmj fc54c6e496 Sync appliances 2024-12-02 11:02:47 +10:00
Jeremy Grossmann 04cd107651 Merge pull request #2448 from GNS3/bugfix/3664
Fix listing images
2024-11-28 12:45:37 +10:00
grossmj 19cabdfde6 Use log.debug for some messages in images.py 2024-11-28 12:42:50 +10:00
grossmj af7fbe6bb4 Fix tests 2024-11-27 15:18:49 +10:00
grossmj 3d58b437b4 Remove restrictions based on file extension when listing images and fix ELF header checks 2024-11-27 14:51:34 +10:00
grossmj 83921a45df Fix use project name instead of ID for fast duplication when running local server. Fixes #2446 2024-11-26 12:07:06 +10:00
Jeremy Grossmann 11c9802268 Merge pull request #2443 from GNS3/feature/upgrade-resource-files
Overwrite user resources when the originals have changed
2024-11-10 18:30:13 +10:00
grossmj a60e0d424d Overwrite user resources when the originals have changed.
Excepting configs and disks which can be customized.
2024-11-09 12:17:06 +10:00
grossmj db1fb29c63 Relax setuptools requirement to allow for easier Debian packaging on Ubuntu Focal & Jammy 2024-11-08 12:46:55 +10:00
Jeremy Grossmann 1a6a729736 Merge pull request #2442 from Xatrekak/master
Fixed issues with installing on Ubuntu 24.04 via remote-install.sh
2024-11-08 10:02:43 +10:00
Dustin 77c356c82c Update remote-install.sh
Fixes for Ubuntu 24.04
2024-11-07 18:15:52 -05:00
Dustin b4819b5500 Update remote-install.sh
Fixing changes for Ubuntu 24.04
2024-11-07 17:44:42 -05:00
grossmj a5f0dba5cf Development on 2.2.52.dev1 2024-11-07 23:13:31 +10:00
Jeremy Grossmann 11a9451098 Merge pull request #2440 from GNS3/release/v2.2.51
release/v2.2.51
2024-11-07 23:13:03 +10:00
grossmj 754680d8e9 Release v2.2.51 2024-11-07 15:08:27 +10:00
grossmj 05773ce189 Sync appliances 2024-11-07 15:06:06 +10:00
grossmj aeae9deb01 Merge remote-tracking branch 'origin/2.2' into 2.2 2024-11-07 14:53:23 +10:00
grossmj f3749e83ec Catch error when cannot resize Docker container TTY. 2024-11-07 14:52:59 +10:00
Jeremy Grossmann c2db4e8542 Merge pull request #2439 from GNS3/bugfix/2438
Fix disk interface is being overriden when set to none
2024-11-07 14:52:08 +10:00
grossmj 52a7696618 Fix tests 2024-11-07 14:48:57 +10:00
grossmj 7bf17392dd Do not use "ide" if there is a disk image and no interface type has been explicitly configured. 2024-11-07 14:37:26 +10:00
grossmj fb06eb3c0c Remove old debug message 2024-10-31 13:07:09 +10:00
grossmj 753135a80d Merge branch 'master' into 2.2 2024-10-28 17:32:34 +10:00
grossmj c05e1cb8e7 Use @locking when sending uBridge commands. Ref https://github.com/GNS3/gns3-gui/issues/3651 2024-10-28 13:02:04 +10:00
grossmj 48b7e6ca50 Fix run Docker containers with user namespaces enabled. Fixes #2414 2024-10-26 19:03:05 +10:00
grossmj dbe2b8a5fb Python 3.13 support 2024-10-26 18:38:07 +10:00
grossmj 80487eb62d Upgrade dependencies 2024-10-26 18:22:40 +10:00
grossmj 6e66b26b88 Fix errors in init.sh. Fixes #2431 2024-10-22 12:18:28 +10:00
grossmj 9990666076 Development on 2.2.51.dev1 2024-10-21 13:24:14 +10:00
Jeremy Grossmann 97e5a5edc3 Merge pull request #2430 from GNS3/2.2
Release v2.2.50
2024-10-21 13:21:24 +10:00
grossmj 2b5c6ce8fb Release v2.2.50 2024-10-21 12:14:18 +10:00
grossmj 0aac62d03a Bundle web-ui v2.2.50 2024-10-21 12:08:42 +10:00
grossmj 4058abf16e Sync appliances 2024-10-21 11:54:02 +10:00
grossmj 4357410b10 Do not run tests on Windows (temporarily) 2024-10-19 17:13:13 +10:00
grossmj 734365b216 Fix win10pcap installation in tests 2024-10-19 17:04:10 +10:00
grossmj abb7cc2075 Install win10pcap in tests 2024-10-19 17:00:32 +10:00
grossmj c273a78560 Upgrade pytest to v8.3.3 2024-10-19 16:33:54 +10:00
grossmj 718269e5b3 Fix syntax error in testing.yml 2024-10-19 16:23:46 +10:00
grossmj 19fd7d2193 Install Windows dependencies in GH Actions 2024-10-19 16:22:29 +10:00
grossmj e62ffb1b87 Fix testing on Windows with GH Actions 2024-10-19 16:12:06 +10:00
grossmj 42808161bf Replace AppVeyor testing with GH Actions 2024-10-19 16:07:53 +10:00
Jeremy Grossmann 45ee662c56 Merge pull request #2428 from GNS3/bugfix/2427
Symbolic links support for project export/import
2024-10-19 15:54:41 +10:00
grossmj 24bfc205db Symbolic links support for project export/import 2024-10-19 15:49:23 +10:00
grossmj cb46c0fbcc Merge remote-tracking branch 'origin/2.2' into 2.2 2024-10-14 17:48:42 +10:00
grossmj 35256901b5 Add comment to indicate sentry-sdk is optional. Ref https://github.com/GNS3/gns3-server/issues/2423 2024-10-14 17:46:53 +10:00
Jeremy Grossmann 6933c3d938 Merge pull request #2420 from GNS3/bugfix/2419
Fix issues with recent busybox versions
2024-10-01 17:37:44 +07:00
grossmj 8af71ee291 Formatting 2024-10-01 17:35:11 +07:00
grossmj c0be6875c2 Fix issues with recent busybox versions
* `busybox --install` does not exist
* `sleep` does not take float values (e.g. 0.5).
2024-10-01 17:31:29 +07:00
Jeremy Grossmann a1922ef067 Merge pull request #2413 from z5241248/master
Duplicate faster
2024-09-29 19:44:49 +07:00
grossmj cafdb2522b Add / update docstrings 2024-09-29 19:42:06 +07:00
grossmj f7996d5e98 Fix tests 2024-09-27 20:05:06 +07:00
grossmj 996dad2f5c Support to reset MAC addresses for Docker nodes and some adjustments for fast duplication. 2024-09-26 18:41:23 +07:00
Jeremy Grossmann 1332e940fd Merge branch '2.2' into master 2024-09-26 16:26:56 +07:00
grossmj 19bd953d31 Update README.md to change the minimum required Python version. 2024-09-26 16:25:26 +07:00
赵昕彧 3a896b6964 Duplicate faster - 2 2024-09-26 08:26:08 +08:00
grossmj 441f0fb1b5 Merge remote-tracking branch 'z5241248/master' into fork/z5241248/master 2024-09-25 19:45:44 +07:00
grossmj a02b57698a Add missing imports 2024-09-25 19:45:14 +07:00
Jeremy Grossmann 7582107ae5 Merge branch '2.2' into master 2024-09-25 19:41:40 +07:00
赵昕彧 2dbde5df22 Copying project files directly, rather than copying them in an import-export fashion, can make copying projects many times faster 2024-09-25 20:27:46 +08:00
grossmj 7b5d123ad8 Improve error message when a project cannot be parsed. 2024-09-23 13:23:03 +07:00
Jeremy Grossmann d1a7474ef6 Merge pull request #2418 from GNS3/revert-2417-backport-aux-console-support
Revert "Backport auxiliary console support for Qemu, Docker and Dynamips nodes"
2024-09-23 13:15:34 +07:00
Jeremy Grossmann af6f34b2ca Revert "Backport auxiliary console support for Qemu, Docker and Dynamips nodes" 2024-09-23 13:10:58 +07:00
Jeremy Grossmann f1294cf267 Merge pull request #2417 from GNS3/backport-aux-console-support
Backport auxiliary console support for Qemu, Docker and Dynamips nodes
2024-09-22 21:44:31 +07:00
grossmj 74782d413f Change method to allocate AUX console for existing Dynamips nodes 2024-09-22 21:41:10 +07:00
grossmj c41c11eb34 Backport auxiliary console support for Qemu, Docker and Dynamips nodes 2024-09-22 18:29:04 +07:00
Jeremy Grossmann 1f09a3e6bc Merge pull request #2416 from GNS3/bugfix/2414
Run Docker containers with user namespaces enabled
2024-09-19 11:01:11 +07:00
grossmj 22f022cc22 Fix for running Docker containers with user namespaces enabled 2024-09-19 10:40:22 +07:00
grossmj 8429494280 Test base MAC address for Docker VMs 2024-09-19 10:19:07 +07:00
grossmj ddd6235acd Merge branch 'master' into 2.2 2024-09-18 17:14:21 +07:00
Jeremy Grossmann bcc148bbd2 Merge pull request #2415 from GNS3/docker-mac-address
Support for custom MAC addresses in Docker containers
2024-09-18 04:05:18 -06:00
grossmj 3792901dc7 Support for configuring MAC address in Docker containers 2024-09-18 16:30:22 +07:00
赵昕彧 5ffe5fd9b3 Copying project files directly, rather than copying them in an import-export fashion, can make copying projects many times faster 2024-08-23 14:31:21 +08:00
grossmj 69a5b16bad Upgrade aiohttp to v3.10.3 2024-08-11 01:34:30 +02:00
grossmj 21a5c5d3f2 Development on 2.2.50.dev1 2024-08-06 20:33:54 +02:00
Jeremy Grossmann 225779bc11 Merge pull request #2409 from GNS3/2.2
Release v2.2.49
2024-08-06 20:32:41 +02:00
grossmj b1209155f5 Release v2.2.49 2024-08-06 12:55:15 +02:00
grossmj 7cebb9472a Bundle web-ui v2.2.49 2024-08-06 12:41:06 +02:00
grossmj 00c3b1abc1 Merge remote-tracking branch 'origin/master' into 2.2 2024-08-06 12:37:55 +02:00
grossmj b1c1c0520c Sync appliances 2024-08-06 12:34:07 +02:00
grossmj 2bb26075f0 Forbid -nic and -nicdev in Qemu additional options. Fixes https://github.com/GNS3/gns3-server/issues/2397 2024-08-05 17:51:46 +02:00
grossmj 6746ef39be Upgrade development packages 2024-08-03 12:32:43 +02:00
grossmj 8889eaa439 Upgrade jsonschema and sentry-sdk packages 2024-08-03 12:32:06 +02:00
grossmj 95a4c284bc Update IOU base configs to use "no ip domain lookup". Fixes #2404 2024-07-22 19:07:17 +02:00
grossmj 6951137a25 Development on 2.2.49.dev1 2024-07-13 16:32:13 +02:00
Jeremy Grossmann cccbca3d5e Merge pull request #2401 from GNS3/release/v2.2.48.1
Release v2.2.48.1
2024-07-13 14:43:53 +02:00
Jeremy Grossmann 3f5b0bb514 Merge pull request #2395 from GNS3/2.2
Release v2.2.48
2024-07-09 00:30:55 +02:00
Jeremy Grossmann 35f94b0c73 Merge pull request #2382 from GNS3/update-ga-workflows
Update GitHub Action workflows
2024-05-17 12:22:43 +07:00
grossmj b82b9a64e6 Rename codeql.yml back to codeql-analysis.yml 2024-05-17 12:19:38 +07:00
grossmj 901652aaeb Update GitHub Action workflows 2024-05-17 12:14:47 +07:00
Jeremy Grossmann 6c9a3b634b Merge pull request #2381 from GNS3/release/v2.2.47
Release v2.2.47
2024-05-15 17:06:53 +07:00
Jeremy Grossmann 19142d97bb Merge pull request #2366 from GNS3/bugfix/block-iou-call
Block IOU phone home call using IPtable
2024-04-20 15:53:39 +07:00
grossmj faf7e09ebb Only use iptable to block xml.cisco.com on Ubuntu Focal. 2024-04-20 15:45:28 +07:00
grossmj 4959a51ce7 Block IOU phone home call using IPtable 2024-04-06 13:04:20 +07:00
Jeremy Grossmann 5bab4131e1 Merge pull request #2361 from GNS3/release/v2.2.46
Release v2.2.46
2024-02-26 17:51:46 +08:00
84 changed files with 1833 additions and 1234 deletions

No files matched your search

@@ -10,7 +10,7 @@ jobs:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.4.0
- uses: actions/add-to-project@v1.0.1
with:
project-url: https://github.com/orgs/GNS3/projects/3
github-token: ${{ secrets.ADD_NEW_ISSUES_TO_PROJECT }}
+51 -28
View File
@@ -13,58 +13,81 @@ name: "CodeQL"
on:
push:
branches: [ master ]
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
branches: [ "master" ]
schedule:
- cron: '44 1 * * 3'
- cron: '21 12 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
include:
- language: python
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
@@ -12,11 +12,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: "gh-pages"
- uses: actions/setup-python@v3
- uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Merge changes from 3.0 branch
+19 -5
View File
@@ -13,21 +13,35 @@ on:
jobs:
build:
runs-on: ubuntu-22.04
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
os: ["ubuntu-latest"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
#include:
# only test with Python 3.10 on Windows
# - os: windows-latest
# python-version: "3.10"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f dev-requirements.txt ]; then pip install -r dev-requirements.txt; fi
python -m pip install -r dev-requirements.txt
- name: Install Windows specific dependencies
if: runner.os == 'Windows'
run: |
python -m pip install -r win-requirements.txt
curl -O "http://www.win10pcap.org/download/Win10Pcap-v10.2-5002.msi"
msiexec /i "Win10Pcap-v10.2-5002.msi" /qn /norestart
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
+50
View File
@@ -1,5 +1,55 @@
# Change Log
## 2.2.53 21/01/2025
* Bundle web-ui v2.2.53
* Add more information when patching .vbox file. Ref https://github.com/GNS3/gns3-gui/issues/3542
* Increase timeout to run compute HTTP queries. Fixes #2461
* Use 'allow_methods="*"' in aiohttp_cors.ResourceOptions(). Fixes #2459
* Upgrade dependencies
* Update remote-install.sh to support a custom repository and the deb822 source format
* Fix: do not use the iourc file if IOU licence check is not enabled
## 2.2.52 02/12/2024
* Bundle web-ui v2.2.52
* Remove restrictions based on file extension when listing images and fix ELF header checks
* Fix use project name instead of ID for fast duplication when running local server. Fixes #2446
* Overwrite user resources when the originals have changed.
* Relax setuptools requirement to allow for easier Debian packaging on Ubuntu Focal & Jammy
## 2.2.51 07/11/2024
* Catch error when cannot resize Docker container TTY.
* Do not use "ide" if there is a disk image and no interface type has been explicitly configured.
* Use @locking when sending uBridge commands. Ref https://github.com/GNS3/gns3-gui/issues/3651
* Fix run Docker containers with user namespaces enabled. Fixes #2414
* Python 3.13 support
* Upgrade dependencies
* Fix errors in init.sh. Fixes #2431
## 2.2.50 21/10/2024
* Bundle web-ui v2.2.50
* Symbolic links support for project export/import
* Add comment to indicate sentry-sdk is optional. Ref https://github.com/GNS3/gns3-server/issues/2423
* Fix issues with recent busybox versions
* Support to reset MAC addresses for Docker nodes and some adjustments for fast duplication.
* Update README.md to change the minimum required Python version.
* Faster project duplication for local projects (no remote compute)
* Improve error message when a project cannot be parsed.
* Fix for running Docker containers with user namespaces enabled
* Support for configuring MAC address in Docker containers
* Upgrade aiohttp to v3.10.3
## 2.2.49 06/08/2024
* Bundle web-ui v2.2.49
* Forbid -nic and -nicdev in Qemu additional options. Fixes https://github.com/GNS3/gns3-server/issues/2397
* Upgrade jsonschema and sentry-sdk packages
* Update IOU base configs to use "no ip domain lookup". Fixes #2404
## 2.2.48.1 12/07/2024
* Bundle web-ui v2.2.48.1
+1 -1
View File
@@ -79,7 +79,7 @@ must be connected to the Internet in order to install the dependencies.
Dependencies:
- Python 3.6, setuptools and the ones listed
- Python >= 3.8, setuptools and the ones listed
[here](https://github.com/GNS3/gns3-server/blob/master/requirements.txt)
The following commands will install some of these dependencies:
-22
View File
@@ -1,22 +0,0 @@
version: '{build}-{branch}'
image: Visual Studio 2022
platform: x64
environment:
PYTHON: "C:\\Python38-x64"
DISTUTILS_USE_SDK: "1"
API_TOKEN:
secure: VEKn4bYH3QO0ixtQW5ni4Enmn8cS1NlZV246ludBDgQ=
install:
- cinst nmap
- "%PYTHON%\\python.exe -m pip install -U pip setuptools" # upgrade pip & setuptools first
- "%PYTHON%\\python.exe -m pip install -r dev-requirements.txt"
- "%PYTHON%\\python.exe -m pip install -r win-requirements.txt"
build: off
test_script:
- "%PYTHON%\\python.exe -m pytest -v"
+4 -4
View File
@@ -1,6 +1,6 @@
-rrequirements.txt
pytest==7.2.0
flake8==5.0.4
pytest-timeout==2.1.0
pytest-aiohttp==1.0.4
pytest==8.3.3
flake8==7.1.0
pytest-timeout==2.3.1
pytest-aiohttp==1.0.5
+6 -6
View File
@@ -30,24 +30,24 @@
"version": "9.2",
"md5sum": "c5bc76e8c95ac9f810a3482c80a54cc7",
"filesize": 563347456,
"download_url": "https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/",
"direct_download_url": "https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-9.2-20230513.x86_64.qcow2"
"download_url": "https://vault.almalinux.org/9.2/cloud/x86_64/images/",
"direct_download_url": "https://vault.almalinux.org/9.2/cloud/x86_64/images/AlmaLinux-9-GenericCloud-9.2-20230513.x86_64.qcow2"
},
{
"filename": "AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2",
"version": "8.8",
"md5sum": "3958c5fc25770ef63cf97aa5d93f0a0b",
"filesize": 565444608,
"download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/",
"direct_download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2"
"download_url": "https://vault.almalinux.org/8.8/cloud/x86_64/images/",
"direct_download_url": "https://vault.almalinux.org/8.8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2"
},
{
"filename": "AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2",
"version": "8.7",
"md5sum": "b2b8c7fd3b6869362f3f8ed47549c804",
"filesize": 566231040,
"download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/",
"direct_download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2"
"download_url": "https://vault.almalinux.org/8.7/cloud/x86_64/images/",
"direct_download_url": "https://vault.almalinux.org/8.7/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2"
},
{
"filename": "almalinux-cloud-init-data.iso",
+56
View File
@@ -0,0 +1,56 @@
{
"appliance_id": "edbaa01e-2032-4ee2-bb9f-dd5c4d84c270",
"name": "Alpine Cloud Guest",
"category": "guest",
"description": "Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox.",
"vendor_name": "Alpine Linux Development Team",
"vendor_url": "http://alpinelinux.org",
"vendor_logo_url": "https://raw.githubusercontent.com/GNS3/gns3-registry/master/vendor-logos/Alpine Linux.png",
"documentation_url": "http://wiki.alpinelinux.org",
"product_name": "Alpine Linux",
"product_url": "https://www.alpinelinux.org/cloud/",
"registry_version": 4,
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "\nUsername: alpine\nPassword: alpine",
"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": "generic_alpine-3.21.2-x86_64-bios-cloudinit-r0.qcow2",
"version": "3.21.2",
"md5sum": "b40825dff2867e0ffaffbc4c87674462",
"filesize": 189726720,
"download_url": "https://www.alpinelinux.org/cloud/",
"direct_download_url": "https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/cloud/generic_alpine-3.21.2-x86_64-bios-cloudinit-r0.qcow2"
},
{
"filename": "alpine-cloud-init-data.iso",
"version": "1.0",
"md5sum": "b1b4b16cc3bf0250c0fa377c19c97683",
"filesize": 374784,
"download_url": "https://github.com/GNS3/gns3-registry/tree/master/cloud-init/alpine-cloud",
"direct_download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/alpine-cloud/alpine-cloud-init-data.iso"
}
],
"versions": [
{
"name": "3.21.2",
"images": {
"hda_disk_image": "generic_alpine-3.21.2-x86_64-bios-cloudinit-r0.qcow2",
"cdrom_image": "alpine-cloud-init-data.iso"
}
}
]
}
+20 -514
View File
@@ -2,14 +2,14 @@
"appliance_id": "c90f3ff3-4ed2-4437-9afb-21232fa92015",
"name": "Arista vEOS",
"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.",
"description": "Arista EOS 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.",
"vendor_name": "Arista",
"vendor_url": "http://www.arista.com/",
"documentation_url": "https://www.arista.com/assets/data/docs/Manuals/EOS-4.17.2F-Manual.pdf",
"product_name": "vEOS",
"product_url": "https://eos.arista.com/",
"registry_version": 4,
"status": "experimental",
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "The login is admin, with no password by default",
@@ -29,87 +29,24 @@
},
"images": [
{
"filename": "vEOS64-lab-4.32.0F.vmdk",
"version": "4.32.0F",
"md5sum": "851771260bb18ad3e90fa6956f0c6161",
"filesize": 591724544,
"filename": "vEOS-lab-4.33.1F.qcow2",
"version": "4.33.1F",
"md5sum": "8f662409c0732ed9f682edce63601e8a",
"filesize": 611909632,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.31.3M.vmdk",
"version": "4.31.3M",
"md5sum": "7df107da137f4a4e752014d4f0e94cd3",
"filesize": 577961984,
"filename": "vEOS-lab-4.32.3M.qcow2",
"version": "4.32.3M",
"md5sum": "46fc46f5ed1da8752eed8396f08862f8",
"filesize": 605683712,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.30.6M.vmdk",
"version": "4.30.6M",
"md5sum": "19721aace820b9ebf6d7ae6524803cf5",
"filesize": 553123840,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.29.8M.vmdk",
"version": "4.29.8M",
"md5sum": "131888f74cd63a93894521d40eb4d0b6",
"filesize": 548405248,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.28.11M.vmdk",
"version": "4.28.11M",
"md5sum": "6cac0e7b04a74ee0dc358327a00accfd",
"filesize": 513343488,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS64-lab-4.27.12M.vmdk",
"version": "4.27.12M",
"md5sum": "34c4f785c7fc054cda8754dd13c0d7c7",
"filesize": 496697344,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.32.0F.vmdk",
"version": "4.32.0F",
"md5sum": "584b901a1249717504050e48f74fb8dd",
"filesize": 591396864,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.31.3M.vmdk",
"version": "4.31.3M",
"md5sum": "a2e130697cdf8547006eebebde6eefca",
"filesize": 590086144,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.30.6M.vmdk",
"version": "4.30.6M",
"md5sum": "a4467648bcfa7b19640af8a4ad3153c6",
"filesize": 565968896,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.29.8M.vmdk",
"version": "4.29.8M",
"md5sum": "1952f6114a4376212c525db9ec8efd5f",
"filesize": 558039040,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.28.11M.vmdk",
"version": "4.28.11M",
"md5sum": "5502df24dfc231c45afb33d6018c16d0",
"filesize": 521338880,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.27.12M.vmdk",
"version": "4.27.12M",
"md5sum": "e08a97e7c1977993f947fedeb4c6ddd5",
"filesize": 504299520,
"filename": "vEOS-lab-4.31.6M.qcow2",
"version": "4.31.6M",
"md5sum": "7410110b77472f058322ec4681f8a356",
"filesize": 590479360,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
@@ -118,459 +55,28 @@
"md5sum": "8d7e754efebca1930a93a2587ff7606c",
"filesize": 6291456,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.26.2F.vmdk",
"version": "4.26.2F",
"md5sum": "de8ce9750fddb63bd3f71bccfcd7651e",
"filesize": 475332608,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.25.3M.vmdk",
"version": "4.25.3M",
"md5sum": "2f196969036b4d283e86f15118d59c26",
"filesize": 451543040,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.24.3M.vmdk",
"version": "4.24.3M",
"md5sum": "0a28e44c7ce4a8965f24a4a463a89b7d",
"filesize": 455213056,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.24.2.1F.vmdk",
"version": "4.24.2.1F",
"md5sum": "6bab8b59ce5230e243e56f4127448fc8",
"filesize": 455213056,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.23.4.2M.vmdk",
"version": "4.23.4.2M",
"md5sum": "d21cbef4e39f1e783b13a926cb54a242",
"filesize": 454295552,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.23.0.1F.vmdk",
"version": "4.23.0.1F",
"md5sum": "08d52154aa11a834aef9f42bbf29f977",
"filesize": 439484416,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.22.2.1F.vmdk",
"version": "4.22.2.1F",
"md5sum": "2a425bf8efe569a2bdf0e328f240cd16",
"filesize": 426377216,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.22.0F.vmdk",
"version": "4.22.0F",
"md5sum": "cfcc75c2b8176cfd819afcfd6799b74c",
"filesize": 414121984,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.21.1.1F.vmdk",
"version": "4.21.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",
"md5sum": "aadb6f3dbff28317f68cb4c4502d0db8",
"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",
"md5sum": "b1ee6268dbaf2b2276fd7a5286c7ce2b",
"filesize": 623116288,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.18.1F.vmdk",
"version": "4.18.1F",
"md5sum": "9648c63185f3b793b47528a858ca4364",
"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",
"md5sum": "3b4845edfa77cf9aaeb9c0a005d3e277",
"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",
"md5sum": "b3f7b7cee17f2e66bb38b453a4939fef",
"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",
"md5sum": "cd74bb69c7ee905ac3d33c4d109f3ab7",
"filesize": 516030464,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.14.14M.vmdk",
"version": "4.14.14M",
"md5sum": "d81ba0522f4d7838d96f7985e41cdc47",
"filesize": 422641664,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.13.16M.vmdk",
"version": "4.13.16M",
"md5sum": "5763b2c043830c341c8b1009f4ea9a49",
"filesize": 404684800,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.13.8M.vmdk",
"version": "4.13.8M",
"md5sum": "a47145b9e6e7a24171c0850f8755535e",
"filesize": 409010176,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "Aboot-veos-serial-8.0.0.iso",
"version": "8.0.0",
"md5sum": "488ad1c435d18c69bb8d69c7806457c9",
"filesize": 5242880,
"download_url": "https://www.arista.com/en/support/software-download"
}
],
"versions": [
{
"name": "4.32.0F",
"name": "4.33.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.32.0F.vmdk"
"hdb_disk_image": "vEOS-lab-4.33.1F.qcow2"
}
},
{
"name": "4.31.3M",
"name": "4.32.3M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.31.3M.vmdk"
"hdb_disk_image": "vEOS-lab-4.32.3M.qcow2"
}
},
{
"name": "4.30.6M",
"name": "4.31.6M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.30.6M.vmdk"
}
},
{
"name": "4.29.8M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.29.8M.vmdk"
}
},
{
"name": "4.28.11M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.28.11M.vmdk"
}
},
{
"name": "4.27.12M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS64-lab-4.27.12M.vmdk"
}
},
{
"name": "4.32.0F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.32.0F.vmdk"
}
},
{
"name": "4.31.3M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.31.3M.vmdk"
}
},
{
"name": "4.30.6M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.30.6M.vmdk"
}
},
{
"name": "4.29.8M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.29.8M.vmdk"
}
},
{
"name": "4.28.11M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.28.11M.vmdk"
}
},
{
"name": "4.27.12M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.2.iso",
"hdb_disk_image": "vEOS-lab-4.27.12M.vmdk"
}
},
{
"name": "4.26.2F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.26.2F.vmdk"
}
},
{
"name": "4.25.3M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.25.3M.vmdk"
}
},
{
"name": "4.24.3M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.24.3M.vmdk"
}
},
{
"name": "4.24.2.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.24.2.1F.vmdk"
}
},
{
"name": "4.23.4.2M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.23.4.2M.vmdk"
}
},
{
"name": "4.23.0.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.23.0.1F.vmdk"
}
},
{
"name": "4.22.2.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.22.2.1F.vmdk"
}
},
{
"name": "4.22.0F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.22.0F.vmdk"
}
},
{
"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": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"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": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.18.5M.vmdk"
}
},
{
"name": "4.18.1F",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"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": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"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": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"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": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.15.5M.vmdk"
}
},
{
"name": "4.14.14M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.14.14M.vmdk"
}
},
{
"name": "4.13.16M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.13.16M.vmdk"
}
},
{
"name": "4.13.8M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.13.8M.vmdk"
"hdb_disk_image": "vEOS-lab-4.31.6M.qcow2"
}
}
]
+26
View File
@@ -33,11 +33,23 @@
"md5sum": "cbbbea66a253f1dac0fcf81274dc778d",
"filesize": 87756936
},
{
"filename": "c7200-adventerprisek9-mz.152-4.M11.image",
"version": "152-4.M11",
"md5sum": "9a2005ad09ce1ec6fe7cf9af1e9b099e",
"filesize": 128487680
},
{
"filename": "c7200-adventerprisek9-mz.124-24.T5.image",
"version": "124-24.T5",
"md5sum": "6b89d0d804e1f2bb5b8bda66b5692047",
"filesize": 102345240
},
{
"filename": "c7200-a3jk9s-mz.124-25g.image",
"version": "124-25G",
"md5sum": "9c7cc9b3f3b3571411a7f62faaa2c036",
"filesize": 71528984
}
],
"versions": [
@@ -55,12 +67,26 @@
"image": "c7200-advipservicesk9-mz.152-4.S5.image"
}
},
{
"name": "152-4.M11",
"idlepc": "0x6062e5c0",
"images": {
"image": "c7200-adventerprisek9-mz.152-4.M11.image"
}
},
{
"name": "124-24.T5",
"idlepc": "0x606df838",
"images": {
"image": "c7200-adventerprisek9-mz.124-24.T5.image"
}
},
{
"name": "124-25G",
"idlepc": "0x6066a998",
"images": {
"image": "c7200-a3jk9s-mz.124-25g.image"
}
}
]
}
+14 -1
View File
@@ -12,7 +12,7 @@
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"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.",
"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. Switch to the Telnet console type after the first boot.",
"symbol": ":/symbols/asa.svg",
"first_port_name": "Management0/0",
"port_name_format": "Gi0/{0}",
@@ -26,6 +26,13 @@
"kvm": "require"
},
"images": [
{
"filename": "asav9-22-1-1.qcow2",
"version": "9.22.1.1 CML",
"md5sum": "250a924cdc2370208eaac9d1dc8dc9e3",
"filesize": 379518976,
"download_url": "https://learningnetworkstore.cisco.com/cisco-modeling-labs-personal/cisco-modeling-labs-personal/CML-PERSONAL.html"
},
{
"filename": "asav9-18-2.qcow2",
"version": "9.18.2 CML",
@@ -126,6 +133,12 @@
}
],
"versions": [
{
"name": "9.22.1.1 CML",
"images": {
"hda_disk_image": "asav9-22-1-1.qcow2"
}
},
{
"name": "9.18.2 CML",
"images": {
+28 -2
View File
@@ -24,12 +24,26 @@
"kvm": "require"
},
"images": [
{
"filename": "csr1000v-universalk9.17.03.08a-serial.qcow2",
"version": "17.03.08a",
"md5sum": "6abece87d6db99d9fd6917203e253f91",
"filesize": 1421410304,
"download_url": "https://software.cisco.com/download/home/286323714/type/282046477/release/Amsterdam-17.3.8a"
},
{
"filename": "csr1000v-universalk9.17.03.06-serial.qcow2",
"version": "17.03.06",
"md5sum": "086ab9bef6e66de847af0da3910c60e8",
"filesize": 1422000128,
"download_url": "https://software.cisco.com/download/home/284364978/type/282046477/release/Gibraltar-16.12.3"
"download_url": "https://software.cisco.com/download/home/286323714/type/282046477/release/Amsterdam-17.3.6"
},
{
"filename": "csr1000v-ucmk9.16.12.5-serial.qcow2",
"version": "16.12.05",
"md5sum": "5c0cc217f0f0648407b34b11a1dd5b8e",
"filesize": 844103680,
"download_url": "https://software.cisco.com/download/home/286323714/type/286321980/release/16.12.5"
},
{
"filename": "csr1000v-universalk9.16.12.03-serial.qcow2",
@@ -166,13 +180,25 @@
}
],
"versions": [
{
"name": "17.03.08a",
"images": {
"hda_disk_image": "csr1000v-universalk9.17.03.08a-serial.qcow2"
}
},
{
"name": "17.03.06",
"images": {
"hda_disk_image": "csr1000v-universalk9.17.03.06-serial.qcow2"
}
},
{
{
"name": "16.12.05",
"images": {
"hda_disk_image": "csr1000v-ucmk9.16.12.5-serial.qcow2"
}
},
{
"name": "16.12.3",
"images": {
"hda_disk_image": "csr1000v-universalk9.16.12.03-serial.qcow2"
+16 -4
View File
@@ -13,13 +13,19 @@
"iou": {
"ethernet_adapters": 4,
"serial_adapters": 0,
"nvram": 128,
"ram": 256,
"nvram": 512,
"ram": 512,
"startup_config": "iou_l2_base_startup-config.txt"
},
"images": [
{
"filename": "x86_64_crb_linux_l2-adventerprisek9-ms.bin",
"filename": "x86_64_crb_linux_l2-adventerprisek9-ms.iol",
"version": "17.15.1",
"md5sum": "6c587cdfd5056078e70b3f6c26800d66",
"filesize": 243251976
},
{
"filename": "x86_64_crb_linux_l2-adventerprisek9-ms",
"version": "17.12.1",
"md5sum": "2b5055e4cef8fd257416d74a94adb626",
"filesize": 240355720
@@ -44,10 +50,16 @@
}
],
"versions": [
{
"name": "17.15.1",
"images": {
"image": "x86_64_crb_linux_l2-adventerprisek9-ms.iol"
}
},
{
"name": "17.12.1",
"images": {
"image": "x86_64_crb_linux_l2-adventerprisek9-ms.bin"
"image": "x86_64_crb_linux_l2-adventerprisek9-ms"
}
},
{
+16 -4
View File
@@ -13,13 +13,19 @@
"iou": {
"ethernet_adapters": 2,
"serial_adapters": 2,
"nvram": 128,
"ram": 256,
"nvram": 512,
"ram": 512,
"startup_config": "iou_l3_base_startup-config.txt"
},
"images": [
{
"filename": "x86_64_crb_linux-adventerprisek9-ms.bin",
"filename": "x86_64_crb_linux-adventerprisek9-ms.iol",
"version": "17.15.1",
"md5sum": "5d584f6cfbeaadc87d55f613da1049ed",
"filesize": 292001512
},
{
"filename": "x86_64_crb_linux-adventerprisek9-ms",
"version": "17.12.1",
"md5sum": "4a2fce8de21d1831fbceffd155e41ae7",
"filesize": 288947184
@@ -44,10 +50,16 @@
}
],
"versions": [
{
"name": "17.15.1",
"images": {
"image": "x86_64_crb_linux-adventerprisek9-ms.iol"
}
},
{
"name": "17.12.1",
"images": {
"image": "x86_64_crb_linux-adventerprisek9-ms.bin"
"image": "x86_64_crb_linux-adventerprisek9-ms"
}
},
{
+29 -1
View File
@@ -28,7 +28,21 @@
"options": ""
},
"images": [
{
{
"filename": "MFG_CTVM_8_10_196_0.iso",
"version": "8.10.196.0",
"md5sum": "6093aca44dcf45c999f83e62dc9aeea2",
"filesize": 650809344,
"download_url": "https://software.cisco.com/download/release.html?mdfid=284464214&flowid=&softwareid=280926587&release=8.10.196.0"
},
{
"filename": "MFG_CTVM_8_5_182_0.iso",
"version": "8.5.182.0",
"md5sum": "1cf3c57c2b123e739ab4662ea0abbc34",
"filesize": 388579328,
"download_url": "https://software.cisco.com/download/home/284464214/type/280926587/release/8.5.182.0"
},
{
"filename": "MFG_CTVM_8_3_102_0.iso",
"version": "8.3.102.0",
"md5sum": "7f6b7968b5bed04b5ecc119b6ba4e41c",
@@ -73,6 +87,20 @@
}
],
"versions": [
{
"name": "8.10.196.0",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "MFG_CTVM_8_10_196_0.iso"
}
},
{
"name": "8.5.182.0",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "MFG_CTVM_8_5_182_0.iso"
}
},
{
"name": "8.3.102.0",
"images": {
+3 -3
View File
@@ -29,10 +29,10 @@
},
"images": [
{
"filename": "FGT_VM64_KVM-v7.4.4.F-build2573-FORTINET.out.kvm.qcow2",
"filename": "FGT_VM64_KVM-v7.4.4.F-build2662-FORTINET.out.kvm.qcow2",
"version": "7.4.4",
"md5sum": "dfe0e78827ec728631539669001bb23f",
"filesize": 100728832,
"filesize": 102170624,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
@@ -391,7 +391,7 @@
{
"name": "7.4.4",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v7.4.4.F-build2573-FORTINET.out.kvm.qcow2",
"hda_disk_image": "FGT_VM64_KVM-v7.4.4.F-build2662-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
+62
View File
@@ -0,0 +1,62 @@
{
"appliance_id": "ac98ab6f-7966-444b-842f-9507c965b8b7",
"name": "HBCD-PE",
"category": "guest",
"description": "Hiren’s BootCD PE (Preinstallation Environment) is a restored edition of Hiren’s BootCD based on Windows 11 PE x64. ",
"vendor_name": "hirensbootcd.org",
"vendor_url": "https://www.hirensbootcd.org/",
"documentation_url": "https://www.hirensbootcd.org/howtos/",
"product_name": "Hiren’s BootCD PE",
"product_url": "https://www.hirensbootcd.org/",
"registry_version": 4,
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"qemu": {
"adapter_type": "e1000",
"adapters": 1,
"ram": 4096,
"hda_disk_interface": "sata",
"arch": "x86_64",
"console_type": "vnc",
"boot_priority": "c",
"kvm": "require"
},
"images": [
{
"filename": "HBCD_PE_x64.iso",
"version": "1.0.8",
"md5sum": "45baab64b088431bdf3370292e9a74b0",
"filesize": 3291686912,
"download_url": "https://www.hirensbootcd.org/download/",
"direct_download_url": "https://www.hirensbootcd.org/files/HBCD_PE_x64.iso"
},
{
"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": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download"
},
{
"filename": "OVMF-edk2-stable202305.fd",
"version": "stable202305",
"md5sum": "6c4cf1519fec4a4b95525d9ae562963a",
"filesize": 4194304,
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/OVMF-edk2-stable202305.fd.zip/download",
"compression": "zip"
}
],
"versions": [
{
"name": "1.0.8",
"images": {
"bios_image": "OVMF-edk2-stable202305.fd",
"hda_disk_image": "empty30G.qcow2",
"cdrom_image": "HBCD_PE_x64.iso"
}
}
]
}
@@ -0,0 +1,50 @@
{
"appliance_id": "92dbd0e9-144e-4c59-a4a8-97b6a1661818",
"name": "Innovaphone App-Platform",
"category": "guest",
"description": "In addition to telephony, apps for Video Telephony, Chat, Conferencing, Application Sharing and many other functions have become indispensable UCC tools in the area of business communication. Based on the myApps platform and its various components, innovaphone provides a collaborative work and communication platform for enhanced corporate communications \u2013 regardless of the location and the device being used. The innovaphone platform myApps consists of many independent components that work well individually, yet unfold their remarkable performance when combined.",
"vendor_name": "Innovaphone",
"vendor_url": "https://www.innovaphone.com",
"vendor_logo_url": "https://www.innovaphone.com/content/downloads/innovaphone-myapps-logo-short-without-background-screen.png",
"documentation_url": "https://wiki.innovaphone.com/index.php?title=Reference14r2:Concept_App_Platform",
"product_name": "App-Platform",
"product_url": "https://www.innovaphone.com/en/products/myapps/myapps-platform.html",
"registry_version": 4,
"status": "experimental",
"availability": "free-to-try",
"maintainer": "Thomas Marchsteiner",
"maintainer_email": "thomas.marchsteiner@acp.at",
"usage": "Default users console:root/iplinux , ssh:admin/ipapps , Webinterface:pwd \nAfter first boot wait for automatic reboot.\nA static ip can be set via the setip utility. \nLoading another keymap can be done via the loadkeys command. \nThe app-platform-disk1.vmdk file is contained within an ova file. \nIt can be extraced with the tar utility, 7Zip or any other tool which can handle tar files.",
"symbol": "innovaphone-ap-icon.jpg",
"first_port_name": "eth0",
"qemu": {
"adapter_type": "vmxnet3",
"adapters": 1,
"ram": 512,
"cpus": 1,
"hda_disk_interface": "scsi",
"arch": "x86_64",
"console_type": "vnc",
"boot_priority": "d",
"kvm": "allow",
"on_close": "power_off",
"process_priority": "normal"
},
"images": [
{
"filename": "app-platform-disk1_120010.vmdk",
"version": "12.0010",
"md5sum": "d5a5a77f682c2c988b0810935d79a787",
"filesize": 129474560,
"download_url": "https://store.innovaphone.com/"
}
],
"versions": [
{
"images": {
"hda_disk_image": "app-platform-disk1_120010.vmdk"
},
"name": "12.0010"
}
]
}
@@ -0,0 +1,78 @@
{
"appliance_id": "ddf8f7a4-60c0-4c9d-849c-ffc3c9d1d082",
"name": "Innovaphone IPVA",
"category": "guest",
"description": "The innovaphone PBX is a professional IP telephone system. The IPVA is a software-only solution. It appears as and performs as an innovaphone 'hard-box' excluding DSP-, ISDN-/AB-resources.",
"vendor_name": "Innovaphone",
"vendor_url": "https://www.innovaphone.com/",
"vendor_logo_url": "https://www.innovaphone.com/content/downloads/innovaphone-myapps-logo-short-without-background-screen.png",
"documentation_url": "https://wiki.innovaphone.com/index.php?title=Reference15r1:Concept_Innovaphone_Virtual_Appliance_(IPVA)",
"product_name": "IPVA",
"product_url": "https://www.innovaphone.com/en/products/innovaphone-pbx.html",
"registry_version": 4,
"status": "experimental",
"availability": "free-to-try",
"maintainer": "Thomas Marchsteiner",
"maintainer_email": "thomas.marchsteiner@acp.at",
"usage": "Default user admin/ipva \nDefault network configuration: DHCP client on eth0 with fallback to static address 192.168.0.1/24 after timeout. Static address 192.168.1.1/24 on eth1\n The ova in the zip file contains the disk images to run this appliance. Disableing the dhcp client and setting a static IP is possible with the following commands:\n> config change IP0 ETH0 /addr 192.168.0.1 /mask 255.255.255.0 \n> config change DHCP0 /mode off \n> config write \n> config activate \n> reset",
"symbol": "innovaphone-pbx-green.png",
"first_port_name": "eth0",
"port_name_format": "eth{port1}",
"qemu": {
"adapter_type": "vmxnet3",
"adapters": 2,
"ram": 256,
"cpus": 1,
"hda_disk_interface": "ide",
"hdb_disk_interface": "ide",
"hdc_disk_interface": "ide",
"hdd_disk_interface": "ide",
"arch": "x86_64",
"console_type": "vnc",
"boot_priority": "d",
"kvm": "allow",
"on_close": "power_off",
"process_priority": "normal"
},
"images": [
{
"filename": "ipva-qemu-disk1-14r2.vmdk",
"version": "14r2",
"md5sum": "aaa1c3885eee30ca6ffa3827619e8643",
"filesize": 6269952,
"download_url": "https://store.innovaphone.com/"
},
{
"filename": "ipva-qemu-disk2-14r2.vmdk",
"version": "14r2",
"md5sum": "008a8fc6b0b1e5f11a3e7fd6f22ba349",
"filesize": 72192,
"download_url": "https://store.innovaphone.com/"
},
{
"filename": "ipva-qemu-disk3-14r2.vmdk",
"version": "14r2",
"md5sum": "20516731c480e2112b3fb4a4d7f514f2",
"filesize": 68096,
"download_url": "https://store.innovaphone.com/"
},
{
"filename": "ipva-qemu-disk4-14r2.vmdk",
"version": "14r2",
"md5sum": "15d7d79ef8c28bd29b2eceac8405f964",
"filesize": 68096,
"download_url": "https://store.innovaphone.com/"
}
],
"versions": [
{
"images": {
"hda_disk_image": "ipva-qemu-disk1-14r2.vmdk",
"hdb_disk_image": "ipva-qemu-disk2-14r2.vmdk",
"hdc_disk_image": "ipva-qemu-disk3-14r2.vmdk",
"hdd_disk_image": "ipva-qemu-disk4-14r2.vmdk"
},
"name": "14r2"
}
]
}
@@ -12,18 +12,19 @@
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"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",
"usage": "16 GB RAM is the bare minimum; you should use 32/64 GB in production deployments.\nDefault credentials:\n- CLI: admin / abc123\n- WebUI: super / juniper123",
"symbol": "juniper-vqfx.svg",
"port_name_format": "em{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 4,
"ram": 16384,
"cpus": 4,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-smp 4 -nographic"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{
@@ -34,7 +34,7 @@
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+1 -1
View File
@@ -26,7 +26,7 @@
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -enable-kvm"
"options": "-nographic -enable-kvm -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+2 -1
View File
@@ -20,11 +20,12 @@
"adapter_type": "virtio-net-pci",
"adapters": 13,
"ram": 4096,
"cpus": 4,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -enable-kvm -smp cpus=3"
"options": "-nographic -enable-kvm -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+1 -1
View File
@@ -23,7 +23,7 @@
"arch": "x86_64",
"console_type": "vnc",
"kvm": "require",
"options": "-nographic"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+2 -1
View File
@@ -19,11 +19,12 @@
"adapter_type": "virtio-net-pci",
"adapters": 12,
"ram": 1024,
"cpus": 2,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -smp 2"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+1 -1
View File
@@ -25,7 +25,7 @@
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -enable-kvm"
"options": "-nographic -enable-kvm -machine q35,smbios-entry-point-type=32"
},
"images": [
{
+2 -1
View File
@@ -19,11 +19,12 @@
"adapter_type": "vmxnet3",
"adapters": 6,
"ram": 4096,
"cpus": 2,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-smp 2"
"options": "-machine q35,smbios-entry-point-type=32"
},
"images": [
{
+30 -99
View File
@@ -28,149 +28,80 @@
},
"images": [
{
"filename": "chr-7.14.2.img",
"version": "7.14.2",
"md5sum": "531901dac85b67b23011e946a62abc7b",
"filename": "chr-7.16.img",
"version": "7.16",
"md5sum": "a4c2d00a87e73b3129cd66a4e0743c9a",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.14.2/chr-7.14.2.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/7.16/chr-7.16.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.11.2.img",
"version": "7.11.2",
"md5sum": "fbffd097d2c5df41fc3335c3977f782c",
"filename": "chr-7.15.3.img",
"version": "7.15.3",
"md5sum": "5af8c748a0de4e8e8b303180738721a9",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.11.2/chr-7.11.2.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/7.15.3/chr-7.15.3.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.10.1.img",
"version": "7.10.1",
"md5sum": "917729e79b9992562f4160d461b21cac",
"filename": "chr-7.14.3.img",
"version": "7.14.3",
"md5sum": "73f527efef81b529b267a0683cb87617",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.10.1/chr-7.10.1.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/7.14.3/chr-7.14.3.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.7.img",
"version": "7.7",
"md5sum": "efc4fdeb1cc06dc240a14f1215fd59b3",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.7/chr-7.7.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.6.img",
"version": "7.6",
"md5sum": "864482f9efaea9d40910c050318f65b9",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.6/chr-7.6.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.3.1.img",
"version": "7.3.1",
"md5sum": "99f8ea75f8b745a8bf5ca3cc1bd325e3",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.3.1/chr-7.3.1.img.zip",
"compression": "zip"
},
{
"filename": "chr-7.1.5.img",
"version": "7.1.5",
"md5sum": "9c0be05f891df2b1400bdae5e719898e",
"filesize": 134217728,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/7.1.5/chr-7.1.5.img.zip",
"compression": "zip"
},
{
"filename": "chr-6.49.10.img",
"version": "6.49.10",
"md5sum": "49ae1ecfe310aea1df37b824aa13cf84",
"filename": "chr-6.49.17.img",
"version": "6.49.17",
"md5sum": "ad9f4bd8cd4965a403350deeb5d35b96",
"filesize": 67108864,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49.10/chr-6.49.10.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49.17/chr-6.49.17.img.zip",
"compression": "zip"
},
{
"filename": "chr-6.49.6.img",
"version": "6.49.6",
"md5sum": "ae27d38acc9c4dcd875e0f97bcae8d97",
"filename": "chr-6.49.13.img",
"version": "6.49.13",
"md5sum": "18349e1c3209495e571bcbee8a7e3259",
"filesize": 67108864,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49.6/chr-6.49.6.img.zip",
"compression": "zip"
},
{
"filename": "chr-6.48.6.img",
"version": "6.48.6",
"md5sum": "875574a561570227ff8f395aabe478c6",
"filesize": 67108864,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.48.6/chr-6.48.6.img.zip",
"direct_download_url": "https://download.mikrotik.com/routeros/6.49.13/chr-6.49.13.img.zip",
"compression": "zip"
}
],
"versions": [
{
"name": "7.11.2",
"name": "7.16",
"images": {
"hda_disk_image": "chr-7.11.2.img"
"hda_disk_image": "chr-7.16.img"
}
},
{
"name": "7.10.1",
"name": "7.15.3",
"images": {
"hda_disk_image": "chr-7.10.1.img"
"hda_disk_image": "chr-7.15.3.img"
}
},
{
"name": "7.7",
"name": "7.14.3",
"images": {
"hda_disk_image": "chr-7.7.img"
"hda_disk_image": "chr-7.14.3.img"
}
},
{
"name": "7.6",
"name": "6.49.17",
"images": {
"hda_disk_image": "chr-7.6.img"
"hda_disk_image": "chr-6.49.17.img"
}
},
{
"name": "7.3.1",
"name": "6.49.13",
"images": {
"hda_disk_image": "chr-7.3.1.img"
}
},
{
"name": "7.1.5",
"images": {
"hda_disk_image": "chr-7.1.5.img"
}
},
{
"name": "6.49.10",
"images": {
"hda_disk_image": "chr-6.49.10.img"
}
},
{
"name": "6.49.6",
"images": {
"hda_disk_image": "chr-6.49.6.img"
}
},
{
"name": "6.48.6",
"images": {
"hda_disk_image": "chr-6.48.6.img"
"hda_disk_image": "chr-6.49.13.img"
}
}
]
+52
View File
@@ -0,0 +1,52 @@
{
"appliance_id": "00714342-14b2-4281-aa20-9043ca8dc26e",
"name": "NixOS",
"category": "guest",
"description": "NixOS QEMU Appliance for images created with nixos-generator. Automatically sets hostname based on vmname.",
"vendor_name": "NixOS",
"vendor_url": "https://nixos.org/",
"vendor_logo_url": "https://avatars.githubusercontent.com/u/487568",
"documentation_url": "https://github.com/ob7/gns3-nixos-appliance",
"product_name": "NixOS",
"product_url": "https://github.com/NixOS/nixpkgs",
"registry_version": 4,
"status": "experimental",
"availability": "free",
"maintainer": "ob7dev",
"maintainer_email": "dev@ob7.us",
"usage": "For custom NixOS images, create qcow2 VM with: nixos-generate -f qcow -c ./server.nix Import it into GNS3 as image. VM name is passed into QEMU guest with Advanced Options field entry: -fw_cfg name=opt/vm_hostname,string=%vm-name%",
"symbol": ":/symbols/affinity/circle/gray/template.svg",
"first_port_name": "eth0",
"port_name_format": "eth{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 4,
"ram": 256,
"cpus": 1,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "allow",
"options": "-fw_cfg name=opt/vm_hostname,string=%vm-name%",
"on_close": "power_off"
},
"images": [
{
"filename": "nixos-24-11.qcow2",
"version": "24.11",
"md5sum": "2459f05136836dd430402d75cba0f205",
"download_url": "https://github.com/nix-community/nixos-generators",
"filesize": 1749483520,
"download_url": "https://f.ob7.us/gns3/",
"direct_download_url": "http://ob7.us/nixos-24-11.qcow2"
}
],
"versions": [
{
"name": "24.11",
"images": {
"hda_disk_image": "nixos-24-11.qcow2"
}
}
]
}
+13
View File
@@ -25,6 +25,13 @@
"kvm": "require"
},
"images": [
{
"filename": "OPNsense-24.7-nano-amd64.img",
"version": "24.7",
"md5sum": "4f75dc2c948b907cbf73763b1539677c",
"filesize": 3221225472,
"download_url": "https://opnsense.c0urier.net/releases/24.7/"
},
{
"filename": "OPNsense-24.1-nano-amd64.img",
"version": "24.1",
@@ -69,6 +76,12 @@
}
],
"versions": [
{
"name": "24.7",
"images": {
"hda_disk_image": "OPNsense-24.7-nano-amd64.img"
}
},
{
"name": "24.1",
"images": {
+14
View File
@@ -24,6 +24,13 @@
"process_priority": "normal"
},
"images": [
{
"filename": "pfSense-CE-2.7.2-RELEASE-amd64.iso",
"version": "2.7.2",
"md5sum": "50c3e723d68ec74d038041a34fa846f8",
"filesize": 874672128,
"download_url": "https://www.pfsense.org/download/mirror.php?section=downloads"
},
{
"filename": "pfSense-CE-2.7.0-RELEASE-amd64.iso",
"version": "2.7.0",
@@ -76,6 +83,13 @@
}
],
"versions": [
{
"name": "2.7.2",
"images": {
"hda_disk_image": "empty100G.qcow2",
"cdrom_image": "pfSense-CE-2.7.2-RELEASE-amd64.iso"
}
},
{
"name": "2.7.0",
"images": {
+10 -10
View File
@@ -24,17 +24,17 @@
},
"images": [
{
"filename": "ReactOS-0.4.14-release-15-gb6088a6.iso",
"version": "Installer-0.4.14-release-15",
"md5sum": "af4be6b27463446905f155f14232d2b4",
"filename": "ReactOS-0.4.14-release-21-g1302c1b.iso",
"version": "Installer-0.4.14-release-21",
"md5sum": "a30bc9143788c76ed584ffd5d25fddfe",
"filesize": 140509184,
"download_url": "https://reactos.org/download",
"direct_download_url": "https://sourceforge.net/projects/reactos/files/ReactOS/0.4.14/ReactOS-0.4.14-release-21-g1302c1b-iso.zip/download"
},
{
"filename": "ReactOS-0.4.14-release-15-gb6088a6-Live.iso",
"version": "Live-0.4.14-release-15",
"md5sum": "73c1a0169a9a3b8a4feb91f4d00f5e97",
"filename": "ReactOS-0.4.14-release-21-g1302c1b-Live.iso",
"version": "Live-0.4.14-release-21",
"md5sum": "fc362820069adeea088b3a48dcfa3f9e",
"filesize": 267386880,
"download_url": "https://reactos.org/download",
"direct_download_url": "https://sourceforge.net/projects/reactos/files/ReactOS/0.4.14/ReactOS-0.4.14-release-21-g1302c1b-live.zip/download"
@@ -50,17 +50,17 @@
],
"versions": [
{
"name": "Installer-0.4.14-release-15",
"name": "Installer-0.4.14-release-21",
"images": {
"hda_disk_image": "empty30G.qcow2",
"cdrom_image": "ReactOS-0.4.14-release-15-gb6088a6.iso"
"cdrom_image": "ReactOS-0.4.14-release-21-g1302c1b.iso"
}
},
{
"name": "Live-0.4.14-release-15",
"name": "Live-0.4.14-release-21",
"images": {
"hda_disk_image": "empty30G.qcow2",
"cdrom_image": "ReactOS-0.4.14-release-15-gb6088a6-Live.iso"
"cdrom_image": "ReactOS-0.4.14-release-21-g1302c1b-Live.iso"
}
}
]
+27 -3
View File
@@ -13,18 +13,27 @@
"status": "stable",
"maintainer": "Brent Stewart",
"maintainer_email": "brent@stewart.tc",
"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.",
"usage": "Your default account will have sudo privileges. 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.",
"symbol": "securityonion-logo.png",
"qemu": {
"adapter_type": "e1000",
"adapters": 2,
"ram": 3072,
"ram": 4096,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "vnc",
"kvm": "allow"
"kvm": "allow",
"options": "-cpu host"
},
"images": [
{
"filename": "securityonion-2.4.80-20240624.iso",
"version": "2.4.80-20240624",
"md5sum": "139f9762e926f9cb3c4a9528a3752c31",
"filesize": 12391022592,
"download_url": "https://github.com/Security-Onion-Solutions/securityonion/blob/2.4/main/DOWNLOAD_AND_VERIFY_ISO.md",
"direct_download_url": "https://download.securityonion.net/file/securityonion/securityonion-2.4.80-20240624.iso"
},
{
"filename": "securityonion-16.04.7.1.iso",
"version": "16.04.7.1",
@@ -49,6 +58,14 @@
"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"
},
{
"filename": "empty100G.qcow2",
"version": "1.0",
"md5sum": "5d9fec18a980f13002028491259f158d",
"filesize": 198656,
"download_url": "https://github.com/riverbed/Riverbed-Community-Toolkit/raw/master/SteelHead/GNS3",
"direct_download_url": "https://github.com/riverbed/Riverbed-Community-Toolkit/raw/master/SteelHead/GNS3/empty100G.qcow2"
},
{
"filename": "empty30G.qcow2",
"version": "1.0",
@@ -59,6 +76,13 @@
}
],
"versions": [
{
"name": "2.4.80-20240624",
"images": {
"hda_disk_image": "empty100G.qcow2",
"cdrom_image": "securityonion-2.4.80-20240624.iso"
}
},
{
"name": "16.04.7.1",
"images": {
@@ -0,0 +1,50 @@
{
"appliance_id": "60801097-332e-4f40-a63e-8ad62047c01f",
"name": "Stormshield EVA",
"category": "firewall",
"description": "Stormshield EVA (Elastic Virtual Appliance) is a french virtual firewall designed to protect network infrastructures. It offers advanced features such as filtering, intrusion prevention (IPS), VPN management (IPSec/SSL), and access control.",
"vendor_name": "Stormshield",
"vendor_url": "https://www.stormshield.com/",
"vendor_logo_url": "https://www.stormshield.com/wp-content/uploads/stormshield-logo.png",
"documentation_url": "https://www.stormshield.com/fr/ressourcescenter/network-security-elastic-virtual-appliances/",
"product_name": "Stormshield EVA",
"product_url": "https://www.stormshield.com/fr/produits-et-services/produits/protection-des-reseaux/nos-produits/appliances-virtuelles/",
"registry_version": 4,
"status": "stable",
"availability": "service-contract",
"maintainer": "Samy SCANNA",
"maintainer_email": "samy.scanna@outlook.com",
"usage": "After the first boot, the appliance automatically runs the configuration script to set up the password, and network interfaces.",
"symbol": "stormshield.png",
"port_name_format": "port{port1}",
"qemu": {
"adapter_type": "vmxnet3",
"adapters": 8,
"ram": 2048,
"cpus": 1,
"hda_disk_interface": "scsi",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "allow",
"options": "-serial stdio",
"on_close": "shutdown_signal",
"process_priority": "normal"
},
"images": [
{
"filename": "utm-SNS-EVA-4.3.33-kvm.qcow2",
"version": "4.3.33",
"md5sum": "21d94d0e20f2e270f06c5853fd750d5b",
"filesize": 284360704,
"download_url": "https://mystormshield.eu/product/download/"
}
],
"versions": [
{
"images": {
"hda_disk_image": "utm-SNS-EVA-4.3.33-kvm.qcow2"
},
"name": "4.3.33"
}
]
}
+104
View File
@@ -0,0 +1,104 @@
{
"appliance_id": "8c19ccaa-a1d0-4473-94a2-a93b64924d88",
"name": "TrueNAS",
"category": "guest",
"description": "TrueNAS is a family of network-attached storage (NAS) products produced by iXsystems, incorporating both FOSS, as well as commercial offerings. Based on the OpenZFS file system, TrueNAS runs on FreeBSD as well as Linux and is available under the BSD License It is compatible with x86-64 hardware and is also available as turnkey appliances from iXsystems.",
"vendor_name": "iXsystems",
"vendor_url": "https://www.truenas.com/",
"documentation_url": "https://www.truenas.com/docs/",
"product_name": "TrueNAS",
"product_url": "https://www.truenas.com/",
"registry_version": 4,
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "To install TrueNAS SCALE you may have to select the Legacy BIOS option.",
"port_name_format": "eth{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 1,
"ram": 8192,
"hda_disk_interface": "ide",
"hdb_disk_interface": "ide",
"arch": "x86_64",
"console_type": "vnc",
"boot_priority": "cd",
"kvm": "require"
},
"images": [
{
"filename": "TrueNAS-13.0-U6.2.iso",
"version": "CORE 13.0 U6.2",
"md5sum": "8b2882b53af5e9f3ca905c6acdee1690",
"filesize": 1049112576,
"download_url": "https://www.truenas.com/download-truenas-core/",
"direct_download_url": "https://download-core.sys.truenas.net/13.0/STABLE/U6.2/x64/TrueNAS-13.0-U6.2.iso"
},
{
"filename": "TrueNAS-13.3-RELEASE.iso",
"version": "CORE 13.3 RELEASE",
"md5sum": "8bb16cfb06f3f1374a27cf6aebb14ed3",
"filesize": 995567616,
"download_url": "https://www.truenas.com/download-truenas-core/",
"direct_download_url": "https://download-core.sys.truenas.net/13.3/STABLE/RELEASE/x64/TrueNAS-13.3-RELEASE.iso"
},
{
"filename": "TrueNAS-SCALE-24.04.2.2.iso",
"version": "SCALE 24.04.2.2",
"md5sum": "47d9026254a0775800bb2b8ab6d874fd",
"filesize": 1630355456,
"download_url": "https://www.truenas.com/download-truenas-scale/",
"direct_download_url": "https://download.sys.truenas.net/TrueNAS-SCALE-Dragonfish/24.04.2.2/TrueNAS-SCALE-24.04.2.2.iso"
},
{
"filename": "TrueNAS-SCALE-24.10-BETA.1.iso",
"version": "SCALE 24.10-BETA.1",
"md5sum": "cc3d5758d1db3d55ae9c8716f5d43b88",
"filesize": 1491378176,
"download_url": "https://www.truenas.com/download-truenas-scale/",
"direct_download_url": "https://download.sys.truenas.net/TrueNAS-SCALE-ElectricEel-BETA/24.10-BETA.1/TrueNAS-SCALE-24.10-BETA.1.iso"
},
{
"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": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty30G.qcow2/download"
}
],
"versions": [
{
"name": "CORE 13.0 U6.2",
"images": {
"hda_disk_image": "empty30G.qcow2",
"hdb_disk_image": "empty30G.qcow2",
"cdrom_image": "TrueNAS-13.0-U6.2.iso"
}
},
{
"name": "CORE 13.3 RELEASE",
"images": {
"hda_disk_image": "empty30G.qcow2",
"hdb_disk_image": "empty30G.qcow2",
"cdrom_image": "TrueNAS-13.3-RELEASE.iso"
}
},
{
"name": "SCALE 24.04.2.2",
"images": {
"hda_disk_image": "empty30G.qcow2",
"hdb_disk_image": "empty30G.qcow2",
"cdrom_image": "TrueNAS-SCALE-24.04.2.2.iso"
}
},
{
"name": "SCALE 24.10-BETA.1",
"images": {
"hda_disk_image": "empty30G.qcow2",
"hdb_disk_image": "empty30G.qcow2",
"cdrom_image": "TrueNAS-SCALE-24.10-BETA.1.iso"
}
}
]
}
+35 -20
View File
@@ -28,36 +28,44 @@
},
"images": [
{
"filename": "ubuntu-23.04-server-cloudimg-amd64.img",
"version": "Ubuntu 23.04 (Lunar Lobster)",
"md5sum": "369e3b1f68416c39245a8014172406dd",
"filesize": 756678656,
"download_url": "https://cloud-images.ubuntu.com/releases/23.04/release/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/23.04/release/ubuntu-23.04-server-cloudimg-amd64.img"
"filename": "ubuntu-24.10-server-cloudimg-amd64.img",
"version": "Ubuntu 24.10 (Oracular Oriole)",
"md5sum": "f2960f8743efedd0a4968bfcd9451782",
"filesize": 627360256,
"download_url": "https://cloud-images.ubuntu.com/releases/oracular/release-20241009/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/oracular/release-20241009/ubuntu-24.10-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-24.04-server-cloudimg-amd64.img",
"version": "Ubuntu 24.04 LTS (Noble Numbat)",
"md5sum": "a1c8a01953578ad432cbef03db2f3161",
"filesize": 587241984,
"download_url": "https://cloud-images.ubuntu.com/releases/noble/release-20241004/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/noble/release-20241004/ubuntu-24.04-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-22.04-server-cloudimg-amd64.img",
"version": "Ubuntu 22.04 LTS (Jammy Jellyfish)",
"md5sum": "3ce0b84f9592482fb645e8253b979827",
"filesize": 686096384,
"download_url": "https://cloud-images.ubuntu.com/releases/jammy/release",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/jammy/release/ubuntu-22.04-server-cloudimg-amd64.img"
"md5sum": "8f9a70435dc5b0b86cf5d0d4716b6091",
"filesize": 653668352,
"download_url": "https://cloud-images.ubuntu.com/releases/jammy/release-20241002/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/jammy/release-20241002/ubuntu-22.04-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-20.04-server-cloudimg-amd64.img",
"version": "Ubuntu 20.04 LTS (Focal Fossa)",
"md5sum": "044bc979b2238192ee3edb44e2bb6405",
"filesize": 552337408,
"download_url": "https://cloud-images.ubuntu.com/releases/focal/release-20210119.1/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/focal/release-20210119.1/ubuntu-20.04-server-cloudimg-amd64.img"
"md5sum": "1dff90e16acb0167c27ff82e4ac1813a",
"filesize": 627310592,
"download_url": "https://cloud-images.ubuntu.com/releases/focal/release-20240821/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/focal/release-20240821/ubuntu-20.04-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-18.04-server-cloudimg-amd64.img",
"version": "Ubuntu 18.04 LTS (Bionic Beaver)",
"md5sum": "f4134e7fa16d7fa766c7467cbe25c949",
"filesize": 336134144,
"download_url": "https://cloud-images.ubuntu.com/releases/18.04/release-20180426.2/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/18.04/release-20180426.2/ubuntu-18.04-server-cloudimg-amd64.img"
"md5sum": "62fa110eeb0459c1ff166f897aeb9f78",
"filesize": 405667840,
"download_url": "https://cloud-images.ubuntu.com/releases/bionic/release-20230607/",
"direct_download_url": "https://cloud-images.ubuntu.com/releases/bionic/release-20230607/ubuntu-18.04-server-cloudimg-amd64.img"
},
{
"filename": "ubuntu-cloud-init-data.iso",
@@ -70,9 +78,16 @@
],
"versions": [
{
"name": "Ubuntu 23.04 (Lunar Lobster)",
"name": "Ubuntu 24.10 (Oracular Oriole)",
"images": {
"hda_disk_image": "ubuntu-23.04-server-cloudimg-amd64.img",
"hda_disk_image": "ubuntu-24.10-server-cloudimg-amd64.img",
"cdrom_image": "ubuntu-cloud-init-data.iso"
}
},
{
"name": "Ubuntu 24.04 LTS (Noble Numbat)",
"images": {
"hda_disk_image": "ubuntu-24.04-server-cloudimg-amd64.img",
"cdrom_image": "ubuntu-cloud-init-data.iso"
}
},
+1 -1
View File
@@ -14,7 +14,7 @@
"symbol": "linux_guest.svg",
"docker": {
"adapters": 1,
"image": "gns3/ubuntu:focal",
"image": "gns3/ubuntu:noble",
"console_type": "telnet"
}
}
+13
View File
@@ -27,6 +27,13 @@
"options": "-vga qxl"
},
"images": [
{
"filename": "Ubuntu 24.04 (64bit).vmdk",
"version": "24.04",
"md5sum": "7709a5a1cf888c7644d245c42d217918",
"filesize": 6432555008,
"download_url": "https://www.osboxes.org/ubuntu/"
},
{
"filename": "Ubuntu 22.04 (64bit).vmdk",
"version": "22.04",
@@ -57,6 +64,12 @@
}
],
"versions": [
{
"name": "24.04",
"images": {
"hda_disk_image": "Ubuntu 24.04 (64bit).vmdk"
}
},
{
"name": "22.04",
"images": {
@@ -10,8 +10,8 @@
"product_url": "http://www.cisco.com/",
"registry_version": 4,
"status": "experimental",
"maintainer": "Laurent LEVIER",
"maintainer_email": "laurent.levier@orange.com",
"maintainer": "Christopher Uhrig",
"maintainer_email": "christopher.uhrig@telekom.de",
"usage": "Initial username is admin, password is admin as well.",
"first_port_name": "Management0/0",
"port_name_format": "Ge0/{0}",
@@ -39,6 +39,20 @@
"md5sum": "4aa487101d4cdc390f53a6e8b6f45ca7",
"filesize": 328400896,
"download_url": "http://www.cisco.com/"
},
{
"filename": "viptela-edge-20.9.5.1-genericx86-64.qcow2",
"version": "20.9.5.1",
"md5sum": "41d9e981908fd83695de78d6ca5794bd",
"filesize": 409468928,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321047/release/20.9.5.1"
},
{
"filename": "viptela-edge-20.12.4-genericx86-64.qcow2",
"version": "20.12.4",
"md5sum": "9f1aedada5e632c7bc29a51c004f4486",
"filesize": 411762688,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321047/release/20.12.4"
}
],
"versions": [
@@ -53,6 +67,18 @@
"images": {
"hda_disk_image": "viptela-edge-genericx86-64.qcow2"
}
},
{
"name": "20.9.5.1",
"images": {
"hda_disk_image": "viptela-edge-20.9.5.1-genericx86-64.qcow2"
}
},
{
"name": "20.12.4",
"images": {
"hda_disk_image": "viptela-edge-20.12.4-genericx86-64.qcow2"
}
}
]
}
@@ -24,6 +24,20 @@
"options": "-smp 2,maxcpus=2 -cpu host"
},
"images": [
{
"filename": "viptela-smart-20.12.4-genericx86-64.qcow2",
"version": "20.12.4",
"md5sum": "0e7b6468498a89195ab815260bc4cfb6",
"filesize": 411762688,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321043/release/20.12.4"
},
{
"filename": "viptela-smart-20.9.5.1-genericx86-64.qcow2",
"version": "20.9.5.1",
"md5sum": "08e105778bb68f8f24f323dfd263a91a",
"filesize": 409468928,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321043/release/20.9.5.1"
},
{
"filename": "viptela-smart-19.2.0-genericx86-64.qcow2",
"version": "19.2.0",
@@ -31,7 +45,7 @@
"filesize": 328400896,
"download_url": "http://www.cisco.com/"
},
{
{
"filename": "viptela-smart-genericx86-64-disk1.vmdk",
"version": "18.3.7",
"md5sum": "ab9b06c212319336810a4b336ec3dd96",
@@ -51,6 +65,18 @@
"images": {
"hda_disk_image": "viptela-smart-19.2.0-genericx86-64.qcow2"
}
},
{
"name": "20.9.5.1",
"images": {
"hda_disk_image": "viptela-smart-20.9.5.1-genericx86-64.qcow2"
}
},
{
"name": "20.12.4",
"images": {
"hda_disk_image": "viptela-smart-20.12.4-genericx86-64.qcow2"
}
}
]
}
@@ -10,8 +10,8 @@
"product_url": "http://www.cisco.com/",
"registry_version": 4,
"status": "experimental",
"maintainer": "Laurent LEVIER",
"maintainer_email": "laurent.levier@orange.com",
"maintainer": "Christopher Uhrig",
"maintainer_email": "christopher.uhrig@telekom.de",
"usage": "Initial username is admin, password is admin as well.",
"qemu": {
"adapter_type": "vmxnet3",
@@ -25,14 +25,28 @@
"options": "-cpu host -smp 2,maxcpus=2"
},
"images": [
{
{
"filename": "viptela-vmanage-20.12.4-genericx86-64.qcow2",
"version": "20.12.4",
"md5sum": "4e0d4c379623c495a0bb671a76a12f9f",
"filesize": 4951375872,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321039/release/20.12.4"
},
{
"filename": "viptela-vmanage-20.9.5.2-genericx86-64.qcow2",
"version": "20.9.5.2",
"md5sum": "a8a4ebee0274541200f4fe94a739d454",
"filesize": 3133865984,
"download_url": "https://software.cisco.com/download/home/286320995/type/286321039/release/20.9.5.2"
},
{
"filename": "viptela-vmanage-19.2.0-genericx86-64.qcow2",
"version": "19.2.0",
"md5sum": "27ef126f178c6c929a36ad2cf6ed8db7",
"filesize": 1185349632,
"download_url": "http://www.cisco.com/"
},
{
{
"filename": "viptela-vmanage-genericx86-64-disk1.vmdk",
"version": "18.3.7",
"md5sum": "2290c6467c907d9ca9c65793fe898716",
@@ -55,6 +69,20 @@
"hda_disk_image": "viptela-vmanage-19.2.0-genericx86-64.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "20.12.4",
"images": {
"hda_disk_image": "viptela-vmanage-20.12.4-genericx86-64.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "20.9.5.2",
"images": {
"hda_disk_image": "viptela-vmanage-20.9.5.2-genericx86-64.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "18.3.7",
+103 -106
View File
@@ -1,181 +1,178 @@
{
"appliance_id": "f82b74c4-0f30-456f-a582-63daca528502",
"name": "VyOS",
"name": "VyOS Universal Router",
"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.",
"vendor_name": "Linux",
"vendor_url": "https://vyos.net/",
"description": "VyOS is an open-source network operating system that provides a comprehensive suite of features for routing, firewalling, and VPN functionality. VyOS offers a robust and flexible solution for both small-scale and large-scale network environments. It is designed to support enterprise-grade networking with the added benefits of community-driven development and continuous updates.\n\nThe VyOS Universal Router, when used in GNS3, brings the power and versatility of VyOS to network simulation and emulation. GNS3 users can deploy the VyOS Universal Router to create and test complex network topologies in a virtual environment. This appliance provides a rich set of features, including dynamic routing protocols, stateful firewall capabilities, various VPNs, as well as high availability configurations.\n\nThe seamless integration with GNS3 allows network engineers and architects to validate network designs, perform testing and troubleshooting, and enhance their skill sets in a controlled, risk-free environment.",
"vendor_name": "VyOS Inc.",
"vendor_url": "https://vyos.io/",
"vendor_logo_url": "https://raw.githubusercontent.com/GNS3/gns3-registry/master/vendor-logos/VyOS.png",
"documentation_url": "https://docs.vyos.io/",
"product_name": "VyOS",
"product_url": "https://vyos.net/",
"product_name": "VyOS Universal Router",
"product_url": "https://vyos.io/vyos-universal-router",
"registry_version": 4,
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "Default username/password is vyos/vyos.\n\nThe -KVM versions are ready to use, no installation is required.\nThe other images will start the router from the CDROM on initial boot. Login and then type \"install image\" and follow the instructions.",
"availability": "service-contract",
"maintainer": "VyOS Inc.",
"maintainer_email": "support@vyos.io",
"usage": "\nDefault credentials:\nUser: vyos\nPassword: vyos",
"symbol": "vyos.svg",
"port_name_format": "eth{0}",
"qemu": {
"adapter_type": "e1000",
"adapters": 3,
"ram": 512,
"hda_disk_interface": "scsi",
"adapter_type": "virtio-net-pci",
"adapters": 10,
"ram": 2048,
"cpus": 4,
"hda_disk_interface": "virtio",
"arch": "x86_64",
"console_type": "telnet",
"boot_priority": "cd",
"kvm": "allow"
"boot_priority": "c",
"kvm": "require",
"on_close": "shutdown_signal"
},
"images": [
{
"filename": "vyos-1.3.2-amd64.iso",
"filename": "vyos-1.4.0-kvm-amd64.qcow2",
"version": "1.4.0",
"md5sum": "a130e446bc5bf87391981f183ee3694b",
"filesize": 468320256,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.7-qemu-amd64.qcow2",
"version": "1.3.7",
"md5sum": "f4663b1e2df115bfa5c7ec17584514d6",
"filesize": 359792640,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.2-10G-qemu.qcow2",
"version": "1.3.2",
"md5sum": "070743faac800f9e5197058a8b6b3ba1",
"filesize": 334495744,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-3-2-generic-iso-image"
"md5sum": "68ad3fb530213189ac9ed496d5fe7897",
"filesize": 326893568,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.1-S1-amd64.iso",
"filename": "vyos-1.3.1-S1-10G-qemu.qcow2",
"version": "1.3.1-S1",
"md5sum": "781f345e8a4ab9eb9e075ce5c87c8817",
"filesize": 351272960,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-3-1-s1-generic-iso-image"
"md5sum": "d8ed9f82a983295b94b07f8e37c48ed0",
"filesize": 343801856,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.1-amd64.iso",
"filename": "vyos-1.3.1-10G-qemu.qcow2",
"version": "1.3.1",
"md5sum": "b6f57bd0cf9b60cdafa337b08ba4f2bc",
"filesize": 350224384,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-3-1-generic-iso-image"
"md5sum": "482367c833990fb2b9350e3708d33dc9",
"filesize": 342556672,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.3.0-amd64.iso",
"filename": "vyos-1.3.0-10G-qemu.qcow2",
"version": "1.3.0",
"md5sum": "2019bd9c5efa6194e2761de678d0073f",
"filesize": 338690048,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-3-0-generic-iso-image"
},
{
"filename": "vyos-1.2.9-S1-amd64.iso",
"version": "1.2.9-S1",
"md5sum": "3fece6363f9766f862e26d292d0ed5a3",
"filesize": 430964736,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-s1-generic-iso-image",
"direct_download_url": "https://legacy-lts-images.vyos.io/1.2.9-S1/vyos-1.2.9-S1-amd64.iso"
"md5sum": "086e95e992e9b4d014c5f154cd01a6e6",
"filesize": 330956800,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.2.9-S1-10G-qemu.qcow2",
"version": "1.2.9-S1-KVM",
"version": "1.2.9-S1",
"md5sum": "0a70d78b80a3716d42487c02ef44f41f",
"filesize": 426967040,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-s1-for-kvm",
"direct_download_url": "https://legacy-lts-images.vyos.io/1.2.9-S1/vyos-1.2.9-S1-10G-qemu.qcow2"
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.2.9-amd64.iso",
"version": "1.2.9",
"md5sum": "586be23b6256173e174c82d8f1f699a1",
"filesize": 430964736,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-generic-iso-image",
"direct_download_url": "https://legacy-lts-images.vyos.io/1.2.9/vyos-1.2.9-amd64.iso"
},
{
"filename": "vyos-1.2.9-10G-qemu.qcow2",
"version": "1.2.9-KVM",
"md5sum": "76871c7b248c32f75177c419128257ac",
"filesize": 427360256,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-10g-qemu-qcow2",
"direct_download_url": "https://legacy-lts-images.vyos.io/1.2.9/vyos-1.2.9-10G-qemu.qcow2"
},
{
"filename": "vyos-1.2.8-amd64.iso",
"filename": "vyos-1.2.8-10G-qemu.qcow2",
"version": "1.2.8",
"md5sum": "0ad879db903efdbf1c39dc945e165931",
"filesize": 429916160,
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-8-generic-iso-image"
"md5sum": "96c76f619d0f8ea11dc8a3a18ed67b98",
"filesize": 425852928,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.1.8-amd64.iso",
"version": "1.1.8",
"md5sum": "95a141d4b592b81c803cdf7e9b11d8ea",
"filesize": 241172480,
"direct_download_url": "https://legacy-lts-images.vyos.io/vyos-1.1.8-amd64.iso"
"filename": "vyos-1.2.7-qemu.qcow2",
"version": "1.2.7",
"md5sum": "1be4674c970fcdd65067e504baea5d74",
"filesize": 424607744,
"download_url": "https://support.vyos.io/"
},
{
"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"
"filename": "vyos-1.2.6-qemu.qcow2",
"version": "1.2.6",
"md5sum": "d8010d79889ca0ba5cb2634665e548e3",
"filesize": 424607744,
"download_url": "https://support.vyos.io/"
},
{
"filename": "vyos-1.2.5-amd64.qcow2",
"version": "1.2.5",
"md5sum": "110c22309ec480600446fd2fb4f27a0d",
"filesize": 411500544 ,
"download_url": "https://support.vyos.io/"
}
],
"versions": [
{
"name": "1.4.0",
"images": {
"hda_disk_image": "vyos-1.4.0-kvm-amd64.qcow2"
}
},
{
"name": "1.3.7",
"images": {
"hda_disk_image": "vyos-1.3.7-qemu-amd64.qcow2"
}
},
{
"name": "1.3.2",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.3.2-amd64.iso"
"hda_disk_image": "vyos-1.3.2-10G-qemu.qcow2"
}
},
{
"name": "1.3.1-S1",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.3.1-S1-amd64.iso"
"hda_disk_image": "vyos-1.3.1-S1-10G-qemu.qcow2"
}
},
{
"name": "1.3.1",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.3.1-amd64.iso"
"hda_disk_image": "vyos-1.3.1-10G-qemu.qcow2"
}
},
{
"name": "1.3.0",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.3.0-amd64.iso"
"hda_disk_image": "vyos-1.3.0-10G-qemu.qcow2"
}
},
{
"name": "1.2.9-S1",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.2.9-S1-amd64.iso"
}
},
{
"name": "1.2.9-S1-KVM",
"images": {
"hda_disk_image": "vyos-1.2.9-S1-10G-qemu.qcow2"
}
},
{
"name": "1.2.9",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.2.9-amd64.iso"
}
},
{
"name": "1.2.9-KVM",
"images": {
"hda_disk_image": "vyos-1.2.9-10G-qemu.qcow2"
}
},
{
"name": "1.2.8",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.2.8-amd64.iso"
"hda_disk_image": "vyos-1.2.8-10G-qemu.qcow2"
}
},
{
"name": "1.1.8",
"name": "1.2.7",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "vyos-1.1.8-amd64.iso"
"hda_disk_image": "vyos-1.2.7-qemu.qcow2"
}
},
{
"name": "1.2.6",
"images": {
"hda_disk_image": "vyos-1.2.6-qemu.qcow2"
}
},
{
"name": "1.2.5",
"images": {
"hda_disk_image": "vyos-1.2.5-amd64.qcow2"
}
}
]
+5 -6
View File
@@ -406,13 +406,11 @@ class BaseNode:
Stops the telnet proxy.
"""
if self._wrapper_telnet_server:
if self._wrap_console_writer:
self._wrap_console_writer.close()
if sys.version_info >= (3, 7, 0):
try:
await self._wrap_console_writer.wait_closed()
except ConnectionResetError:
pass
await self._wrap_console_writer.wait_closed()
self._wrap_console_writer = None
if self._wrapper_telnet_server:
self._wrapper_telnet_server.close()
await self._wrapper_telnet_server.wait_closed()
self._wrapper_telnet_server = None
@@ -662,6 +660,7 @@ class BaseNode:
path = shutil.which(path)
return path
@locking
async def _ubridge_send(self, command):
"""
Sends a command to uBridge hypervisor.
+63 -7
View File
@@ -33,7 +33,7 @@ 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.utils import macaddress_to_int, int_to_macaddress
from gns3server.ubridge.ubridge_error import UbridgeError, UbridgeNamespaceError
from ..base_node import BaseNode
@@ -83,6 +83,7 @@ class DockerVM(BaseNode):
self._environment = environment
self._cid = None
self._ethernet_adapters = []
self._mac_address = ""
self._temporary_directory = None
self._telnet_servers = []
self._vnc_process = None
@@ -106,6 +107,8 @@ class DockerVM(BaseNode):
else:
self.adapters = adapters
self.mac_address = "" # this will generate a MAC address
log.debug("{module}: {name} [{image}] initialized.".format(module=self.manager.module_name,
name=self.name,
image=self._image))
@@ -119,6 +122,7 @@ class DockerVM(BaseNode):
"project_id": self._project.id,
"image": self._image,
"adapters": self.adapters,
"mac_address": self.mac_address,
"console": self.console,
"console_type": self.console_type,
"console_resolution": self.console_resolution,
@@ -149,6 +153,36 @@ class DockerVM(BaseNode):
def ethernet_adapters(self):
return self._ethernet_adapters
@property
def mac_address(self):
"""
Returns the MAC address for this Docker container.
:returns: adapter type (string)
"""
return self._mac_address
@mac_address.setter
def mac_address(self, mac_address):
"""
Sets the MAC address for this Docker container.
:param mac_address: MAC address
"""
if not mac_address:
# use the node UUID to generate a random MAC address
self._mac_address = "02:42:%s:%s:%s:00" % (self.id[2:4], self.id[4:6], self.id[6:8])
else:
self._mac_address = mac_address
log.info('Docker container "{name}" [{id}]: MAC address changed to {mac_addr}'.format(
name=self._name,
id=self._id,
mac_addr=self._mac_address)
)
@property
def start_command(self):
return self._start_command
@@ -349,6 +383,7 @@ class DockerVM(BaseNode):
"CapAdd": ["ALL"],
"Privileged": True,
"Binds": self._mount_binds(image_infos),
"UsernsMode": "host",
},
"Volumes": {},
"Env": ["container=docker"], # Systemd compliant: https://github.com/GNS3/gns3-server/issues/573
@@ -675,7 +710,10 @@ class DockerVM(BaseNode):
"""
# resize the container TTY.
await self._manager.query("POST", "containers/{}/resize?h={}&w={}".format(self._cid, rows, columns))
try:
await self._manager.query("POST", "containers/{}/resize?h={}&w={}".format(self._cid, rows, columns))
except DockerError as e:
log.warning(f"Could not resize the container TTY: {e}")
async def _start_console(self):
"""
@@ -914,15 +952,33 @@ class DockerVM(BaseNode):
bridge_name = 'bridge{}'.format(adapter_number)
await self._ubridge_send('bridge create {}'.format(bridge_name))
self._bridges.add(bridge_name)
await self._ubridge_send('bridge add_nio_tap bridge{adapter_number} {hostif}'.format(adapter_number=adapter_number,
hostif=adapter.host_ifc))
await self._ubridge_send('bridge add_nio_tap bridge{adapter_number} {hostif}'.format(
adapter_number=adapter_number,
hostif=adapter.host_ifc)
)
mac_address = int_to_macaddress(macaddress_to_int(self._mac_address) + adapter_number)
custom_adapter = self._get_custom_adapter_settings(adapter_number)
custom_mac_address = custom_adapter.get("mac_address")
if custom_mac_address:
mac_address = custom_mac_address
try:
await self._ubridge_send('docker set_mac_addr {ifc} {mac}'.format(ifc=adapter.host_ifc, mac=mac_address))
except UbridgeError:
log.warning("Could not set MAC address %s on interface %s", mac_address, adapter.host_ifc)
log.debug("Move container %s adapter %s to namespace %s", self.name, adapter.host_ifc, self._namespace)
try:
await self._ubridge_send('docker move_to_ns {ifc} {ns} eth{adapter}'.format(ifc=adapter.host_ifc,
ns=self._namespace,
adapter=adapter_number))
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)
else:
log.info("Created adapter %s with MAC address %s in namespace %s", adapter_number, mac_address, self._namespace)
if nio:
await self._connect_nio(adapter_number, nio)
+5 -2
View File
@@ -25,7 +25,10 @@ PATH=/gns3/bin:/tmp/gns3/bin:/sbin:$PATH
# bootstrap busybox commands
if [ ! -d /tmp/gns3/bin ]; then
busybox mkdir -p /tmp/gns3/bin
/gns3/bin/busybox --install -s /tmp/gns3/bin
for applet in `busybox --list`
do
ln -s /gns3/bin/busybox "/tmp/gns3/bin/$applet"
done
fi
# Restore file permission and mount volumes
@@ -75,7 +78,7 @@ ip link set dev lo up
while true
do
grep $GNS3_MAX_ETHERNET /proc/net/dev > /dev/null && break
sleep 0.5
usleep 500000 # wait 0.5 seconds
done
# activate eth interfaces
+22 -12
View File
@@ -390,14 +390,16 @@ class IOUVM(BaseNode):
raise IOUError("The following shared library dependencies cannot be found for IOU image {}: {}".format(self._path,
", ".join(missing_libs)))
async def _check_iou_licence(self):
def _is_iou_license_check_enabled(self):
"""
Checks for a valid IOU key in the iourc file (paranoid mode).
Returns if IOU license check is enabled.
:return: boolean
"""
# license check is sent by the controller
if self.license_check is False:
return
return False
try:
# we allow license check to be disabled server wide
@@ -407,7 +409,14 @@ class IOUVM(BaseNode):
if server_wide_license_check is False:
log.warning("License check is explicitly disabled on this server")
return
return False
return True
async def _check_iou_license(self):
"""
Checks for a valid IOU key in the iourc file (paranoid mode).
"""
config = configparser.ConfigParser()
try:
@@ -511,15 +520,16 @@ class IOUVM(BaseNode):
except OSError as e:
raise IOUError("Could not rename nvram files: {}".format(e))
iourc_path = self.iourc_path
if not iourc_path:
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))
iourc_path = None
if self._is_iou_license_check_enabled():
iourc_path = self.iourc_path
if not iourc_path:
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))
await self._check_iou_license()
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
@@ -531,7 +541,7 @@ class IOUVM(BaseNode):
self._nvram_watcher = FileWatcher(self._nvram_file(), self._nvram_changed, delay=2)
# created a environment variable pointing to the iourc file.
# created an environment variable pointing to the iourc file.
env = os.environ.copy()
if "IOURC" not in os.environ and iourc_path:
env["IOURC"] = iourc_path
+1 -6
View File
@@ -55,7 +55,7 @@ log = logging.getLogger(__name__)
# forbidden additional options
FORBIDDEN_OPTIONS = {"-blockdev", "-drive", "-hda", "-hdb", "-hdc", "-hdd",
"-fsdev", "-virtfs"}
"-fsdev", "-virtfs", "-nic", "-netdev"}
FORBIDDEN_OPTIONS |= {"-" + opt for opt in FORBIDDEN_OPTIONS
if opt.startswith("-") and not opt.startswith("--")}
@@ -1915,11 +1915,6 @@ class QemuVM(BaseNode):
continue
interface = getattr(self, "hd{}_disk_interface".format(drive))
# fail-safe: use "ide" if there is a disk image and no interface type has been explicitly configured
if interface == "none":
interface = "ide"
setattr(self, "hd{}_disk_interface".format(drive), interface)
disk_name = "hd" + drive
if not os.path.isfile(disk_image) or not os.path.exists(disk_image):
if os.path.islink(disk_image):
+37 -20
View File
@@ -218,28 +218,45 @@ class VirtualBoxVM(BaseNode):
"""
Fix the VM uuid in the case of linked clone
"""
if os.path.exists(self._linked_vbox_file()):
try:
tree = ET.parse(self._linked_vbox_file())
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 + "}":
linked_vbox_file = self._linked_vbox_file()
if not os.path.exists(linked_vbox_file):
raise VirtualBoxError("Cannot find VirtualBox linked node file: {}".format(linked_vbox_file))
for image in tree.getroot().findall("{http://www.virtualbox.org/}Image"):
currentSnapshot = machine.get("currentSnapshot")
if 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)
try:
tree = ET.parse(linked_vbox_file)
except ET.ParseError:
raise VirtualBoxError("Cannot modify VirtualBox linked node file. "
"File {} is corrupted.".format(linked_vbox_file))
except OSError as e:
raise VirtualBoxError("Cannot modify VirtualBox linked node file '{}': {}".format(linked_vbox_file, e))
machine.set("uuid", "{" + self.id + "}")
tree.write(self._linked_vbox_file())
machine = tree.getroot().find("{http://www.virtualbox.org/}Machine")
if machine is not None and machine.get("uuid") != "{" + self.id + "}":
for image in tree.getroot().findall("{http://www.virtualbox.org/}Image"):
currentSnapshot = machine.get("currentSnapshot")
if 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"
)
log.info("VirtualBox VM '{name}' [{id}] snapshot file moved from '{current}' to '{new}'".format(
name=self.name,
id=self.id,
current=currentSnapshot,
new=newSnapshot,
))
image.set("uuid", newSnapshot)
log.info("VirtualBox VM '{name}' [{id}] '{vbox_file}' has been patched".format(
name=self.name,
id=self.id,
vbox_file=linked_vbox_file,
))
machine.set("uuid", "{" + self.id + "}")
tree.write(linked_vbox_file)
async def check_hw_virtualization(self):
"""
@@ -458,7 +475,7 @@ class VirtualBoxVM(BaseNode):
async def save_linked_hdds_info(self):
"""
Save linked cloned hard disks information.
Save linked cloned hard disk information.
:returns: disk table information
"""
@@ -15,7 +15,7 @@ no ip icmp rate-limit unreachable
!
! due to some bugs with IOU, try to change the following line to 'ip cef' if your routing does not work
no ip cef
no ip domain-lookup
no ip domain lookup
!
!
!
@@ -14,7 +14,7 @@ no ip icmp rate-limit unreachable
!
! due to some bugs with IOU, try to change the following line to 'ip cef' if your routing does not work
no ip cef
no ip domain-lookup
no ip domain lookup
!
!
ip tcp synwait-time 5
+14 -5
View File
@@ -29,7 +29,7 @@ except ImportError:
from importlib import resources as importlib_resources
from ..config import Config
from ..utils import parse_version
from ..utils import parse_version, md5sum
from ..utils.images import default_images_directory
from .project import Project
@@ -289,12 +289,21 @@ class Controller:
except OSError as e:
log.error(str(e))
@staticmethod
def install_resource_files(dst_path, resource_name):
def install_resource_files(dst_path, resource_name, upgrade_resources=True):
"""
Install files from resources to user's file system
"""
def should_copy(src, dst, upgrade_resources):
if not os.path.exists(dst):
return True
if upgrade_resources is False:
return False
# copy the resource if it is different
return md5sum(src) != md5sum(dst)
if hasattr(sys, "frozen") and sys.platform.startswith("win"):
resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), resource_name))
for filename in os.listdir(resource_path):
@@ -303,7 +312,7 @@ class Controller:
else:
for entry in importlib_resources.files('gns3server').joinpath(resource_name).iterdir():
full_path = os.path.join(dst_path, entry.name)
if entry.is_file() and not os.path.exists(full_path):
if entry.is_file() and should_copy(str(entry), full_path, upgrade_resources):
log.debug(f'Installing {resource_name} resource file "{entry.name}" to "{full_path}"')
shutil.copy(str(entry), os.path.join(dst_path, entry.name))
elif entry.is_dir():
@@ -319,7 +328,7 @@ class Controller:
dst_path = self.configs_path()
log.info(f"Installing base configs in '{dst_path}'")
try:
Controller.install_resource_files(dst_path, "configs")
Controller.install_resource_files(dst_path, "configs", upgrade_resources=False)
except OSError as e:
log.error(f"Could not install base config files to {dst_path}: {e}")
@@ -332,7 +341,7 @@ class Controller:
dst_path = self.disks_path()
log.info(f"Installing built-in disks in '{dst_path}'")
try:
Controller.install_resource_files(dst_path, "disks")
Controller.install_resource_files(dst_path, "disks", upgrade_resources=False)
except OSError as e:
log.error(f"Could not install disk files to {dst_path}: {e}")
+2 -4
View File
@@ -82,7 +82,7 @@ class ApplianceManager:
os.makedirs(appliances_path, exist_ok=True)
return appliances_path
def builtin_appliances_path(self, delete_first=False):
def builtin_appliances_path(self):
"""
Get the built-in appliance storage directory
"""
@@ -91,8 +91,6 @@ class ApplianceManager:
appname = vendor = "GNS3"
resources_path = os.path.expanduser(server_config.get("resources_path", platformdirs.user_data_dir(appname, vendor, roaming=True)))
appliances_dir = os.path.join(resources_path, "appliances")
if delete_first:
shutil.rmtree(appliances_dir, ignore_errors=True)
os.makedirs(appliances_dir, exist_ok=True)
return appliances_dir
@@ -101,7 +99,7 @@ class ApplianceManager:
At startup we copy the built-in appliances files.
"""
dst_path = self.builtin_appliances_path(delete_first=True)
dst_path = self.builtin_appliances_path()
log.info(f"Installing built-in appliances in '{dst_path}'")
from . import Controller
try:
+8 -3
View File
@@ -18,14 +18,19 @@
import ipaddress
import aiohttp
import asyncio
import async_timeout
import socket
import json
import uuid
import sys
import io
from operator import itemgetter
if sys.version_info >= (3, 11):
from asyncio import timeout as asynctimeout
else:
from async_timeout import timeout as asynctimeout
from ..utils import parse_version
from ..utils.asyncio import locking
from ..controller.controller_error import ControllerError
@@ -483,8 +488,8 @@ class Compute:
""" Returns URL for specific path at Compute"""
return self._getUrl(path)
async def _run_http_query(self, method, path, data=None, timeout=20, raw=False):
async with async_timeout.timeout(delay=timeout):
async def _run_http_query(self, method, path, data=None, timeout=120, raw=False):
async with asynctimeout(delay=timeout):
url = self._getUrl(path)
headers = {}
headers['content-type'] = 'application/json'
+14 -14
View File
@@ -70,14 +70,15 @@ async def export_project(zstream, project, temporary_dir, include_images=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)
# check if we can export the file
try:
open(path).close()
except OSError as e:
msg = "Could not export file {}: {}".format(path, e)
log.warning(msg)
project.emit_notification("log.warning", {"message": msg})
continue
if not os.path.islink(path):
try:
# check if we can export the file
open(path).close()
except OSError as e:
msg = "Could not export file {}: {}".format(path, e)
log.warning(msg)
project.emit_notification("log.warning", {"message": msg})
continue
# ignore the .gns3 file
if file.endswith(".gns3"):
continue
@@ -128,7 +129,7 @@ def _patch_mtime(path):
if sys.platform.startswith("win"):
# only UNIX type platforms
return
st = os.stat(path)
st = os.stat(path, follow_symlinks=False)
file_date = datetime.fromtimestamp(st.st_mtime)
if file_date.year < 1980:
new_mtime = file_date.replace(year=1980).timestamp()
@@ -144,10 +145,6 @@ def _is_exportable(path, include_snapshots=False):
if include_snapshots is False and path.endswith("snapshots"):
return False
# 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
@@ -200,13 +197,16 @@ async def _patch_project_file(project, path, zstream, include_images, keep_compu
if not keep_compute_ids:
node["compute_id"] = "local" # To make project portable all node by default run on local
if "properties" in node and node["node_type"] != "docker":
if "properties" in node:
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"] == "docker":
continue
if node["node_type"] == "iou":
if not prop == "path":
continue
+21
View File
@@ -17,6 +17,7 @@
import os
import sys
import stat
import json
import uuid
import shutil
@@ -93,6 +94,7 @@ async def import_project(controller, project_id, stream, location=None, name=Non
try:
with zipfile.ZipFile(stream) as zip_file:
await wait_run_in_executor(zip_file.extractall, path)
_create_symbolic_links(zip_file, path)
except zipfile.BadZipFile:
raise aiohttp.web.HTTPConflict(text="Cannot extract files from GNS3 project (invalid zip)")
@@ -174,6 +176,24 @@ async def import_project(controller, project_id, stream, location=None, name=Non
project = await controller.load_project(dot_gns3_path, load=False)
return project
def _create_symbolic_links(zip_file, path):
"""
Manually create symbolic links (if any) because ZipFile does not support it.
:param zip_file: ZipFile instance
:param path: project location
"""
for zip_info in zip_file.infolist():
if stat.S_ISLNK(zip_info.external_attr >> 16):
symlink_target = zip_file.read(zip_info.filename).decode()
symlink_path = os.path.join(path, zip_info.filename)
try:
# remove the regular file and replace it by a symbolic link
os.remove(symlink_path)
os.symlink(symlink_target, symlink_path)
except OSError as e:
raise aiohttp.web.HTTPConflict(text=f"Cannot create symbolic link: {e}")
def _move_node_file(path, old_id, new_id):
"""
@@ -257,6 +277,7 @@ async def _import_snapshots(snapshots_path, project_name, project_id):
with open(snapshot_path, "rb") as f:
with zipfile.ZipFile(f) as zip_file:
await wait_run_in_executor(zip_file.extractall, tmpdir)
_create_symbolic_links(zip_file, tmpdir)
except OSError as e:
raise aiohttp.web.HTTPConflict(text="Cannot open snapshot '{}': {}".format(os.path.basename(snapshot), e))
except zipfile.BadZipFile:
+8 -2
View File
@@ -26,8 +26,8 @@ import os
from .compute import ComputeConflict, ComputeError
from .ports.port_factory import PortFactory, StandardPortFactory, DynamipsPortFactory
from ..utils.images import images_directories
from ..utils import macaddress_to_int, int_to_macaddress
from ..config import Config
from ..utils.qt import qt_font_to_style
import logging
@@ -663,7 +663,13 @@ class Node:
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))
mac_address = custom_adapter_settings.get("mac_address")
if not mac_address and "mac_address" in self._properties:
mac_address = int_to_macaddress(macaddress_to_int(self._properties["mac_address"]) + adapter_number)
port = PortFactory(port_name, 0, adapter_number, 0, "ethernet", short_name=port_name)
port.mac_address = mac_address
self._ports.append(port)
elif self._node_type in ("ethernet_switch", "ethernet_hub"):
# Basic node we don't want to have adapter number
port_number = 0
+92 -5
View File
@@ -15,6 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import re
import os
import json
@@ -27,6 +28,7 @@ import aiohttp
import aiofiles
import tempfile
import zipfile
import pathlib
from uuid import UUID, uuid4
@@ -42,8 +44,9 @@ from ..utils.application_id import get_next_application_id
from ..utils.asyncio.pool import Pool
from ..utils.asyncio import locking
from ..utils.asyncio import aiozipstream
from ..utils.asyncio import wait_run_in_executor
from .export_project import export_project
from .import_project import import_project
from .import_project import import_project, _move_node_file
import logging
log = logging.getLogger(__name__)
@@ -585,7 +588,7 @@ class Project:
if node_type == "iou":
async with self._iou_id_lock:
# wait for a IOU node to be completely created before adding a new one
# wait for an IOU node to be completely created before adding a new one
# this is important otherwise we allocate the same application ID (used
# to generate MAC addresses) when creating multiple IOU node at the same time
if "properties" in kwargs.keys():
@@ -1037,14 +1040,16 @@ class Project:
"""
Duplicate a project
It's the save as feature of the 1.X. It's implemented on top of the
export / import features. It will generate a gns3p and reimport it.
It's a little slower but we have only one implementation to maintain.
Implemented on top of the export / import features. It will generate a gns3p and reimport it.
NEW: fast duplication is used if possible (when there are no remote computes).
If not, the project is exported and reimported as explained above.
:param name: Name of the new project. A new one will be generated in case of conflicts
:param location: Parent directory of the new project
:param reset_mac_addresses: Reset MAC addresses for the new project
"""
# If the project was not open we open it temporary
previous_status = self._status
if self._status == "closed":
@@ -1052,6 +1057,18 @@ class Project:
self.dump()
assert self._status != "closed"
try:
proj = await self._fast_duplication(name, location, reset_mac_addresses)
if proj:
if previous_status == "closed":
await self.close()
return proj
else:
log.info("Fast duplication failed, fallback to normal duplication")
except Exception as e:
raise aiohttp.web.HTTPConflict(text="Cannot duplicate project: {}".format(str(e)))
try:
begin = time.time()
@@ -1237,3 +1254,73 @@ class Project:
def __repr__(self):
return "<gns3server.controller.Project {} {}>".format(self._name, self._id)
async def _fast_duplication(self, name=None, location=None, reset_mac_addresses=True):
"""
Fast duplication of a project.
Copy the project files directly rather than in an import-export fashion.
:param name: Name of the new project. A new one will be generated in case of conflicts
:param location: Parent directory of the new project
:param reset_mac_addresses: Reset MAC addresses for the new project
"""
# remote replication is not supported with remote computes
for compute in self.computes:
if compute.id != "local":
log.warning("Fast duplication is not supported with remote compute: '{}'".format(compute.id))
return None
# work dir
p_work = pathlib.Path(location or self.path).parent.absolute()
t0 = time.time()
new_project_id = str(uuid.uuid4())
if location:
new_project_path = p_work.joinpath(location)
else:
new_project_path = p_work.joinpath(new_project_id)
# copy dir
await wait_run_in_executor(shutil.copytree, self.path, new_project_path.as_posix(), symlinks=True, ignore_dangling_symlinks=True)
log.info("Project content copied from '{}' to '{}' in {}s".format(self.path, new_project_path, time.time() - t0))
topology = json.loads(new_project_path.joinpath('{}.gns3'.format(self.name)).read_bytes())
project_name = name or topology["name"]
# If the project name is already used we generate a new one
project_name = self.controller.get_free_project_name(project_name)
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"] = False
# change node ID
node_old_to_new = {}
for node in topology["topology"]["nodes"]:
new_node_id = str(uuid.uuid4())
if "node_id" in node:
node_old_to_new[node["node_id"]] = new_node_id
_move_node_file(new_project_path, node["node_id"], new_node_id)
node["node_id"] = new_node_id
if reset_mac_addresses:
if "properties" in node:
for prop, value in node["properties"].items():
# reset the MAC address
if prop in ("mac_addr", "mac_address"):
node["properties"][prop] = None
# change link 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())
# And we dump the updated.gns3
dot_gns3_path = new_project_path.joinpath('{}.gns3'.format(project_name))
topology["project_id"] = new_project_id
with open(dot_gns3_path, "w+") as f:
json.dump(topology, f, indent=4)
os.remove(new_project_path.joinpath('{}.gns3'.format(self.name)))
project = await self.controller.load_project(dot_gns3_path, load=False)
log.info("Project '{}' fast duplicated in {:.4f} seconds".format(project.name, time.time() - t0))
return project
+1 -1
View File
@@ -188,7 +188,7 @@ def load_topology(path):
try:
_check_topology_schema(topo)
except aiohttp.web.HTTPConflict as e:
log.error("Can't load the topology %s", path)
log.error("Can't load the topology %s, please check using the debug mode...", path)
raise e
if changed:
+1 -1
View File
@@ -57,7 +57,7 @@ class CrashReport:
Report crash to a third party service
"""
DSN = "https://9888239d177479b53f1b089ec43f4630@o19455.ingest.us.sentry.io/38482"
DSN = "https://98c55f74bc61432b375d3eb392af9f7d@o19455.ingest.us.sentry.io/38482"
_instance = None
def __init__(self):
@@ -317,7 +317,7 @@ class DockerHandler:
props = [
"name", "console", "aux", "console_type", "console_resolution",
"console_http_port", "console_http_path", "start_command",
"environment", "adapters", "extra_hosts", "extra_volumes"
"environment", "adapters", "mac_address", "custom_adapters", "extra_hosts", "extra_volumes"
]
changed = False
+12
View File
@@ -85,6 +85,12 @@ DOCKER_CREATE_SCHEMA = {
"minimum": 0,
"maximum": 99,
},
"mac_address": {
"description": "Docker container base MAC address",
"type": ["string", "null"],
"minLength": 1,
"pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"
},
"environment": {
"description": "Docker environment variables",
"type": ["string", "null"],
@@ -187,6 +193,12 @@ DOCKER_OBJECT_SCHEMA = {
"minimum": 0,
"maximum": 99,
},
"mac_address": {
"description": "Docker container base MAC address",
"type": ["string", "null"],
"minLength": 1,
"pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"
},
"usage": {
"description": "How to use the Docker container",
"type": "string",
+9
View File
@@ -38,6 +38,15 @@ DOCKER_TEMPLATE_PROPERTIES = {
"maximum": 99,
"default": 1
},
"mac_address": {
"description": "Docker container base MAC address",
"type": ["string", "null"],
"anyOf": [
{"pattern": "^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"},
{"pattern": "^$"}
],
"default": "",
},
"start_command": {
"description": "Docker CMD entry",
"type": "string",
+1 -1
View File
@@ -46,6 +46,6 @@
gtag('config', 'G-0BT7QQV1W1');
</script>
<script src="runtime.415291667f70565cd8ef.js" defer></script><script src="polyfills-es5.865074f5cd9a121111a2.js" nomodule defer></script><script src="polyfills.2f91a039d848e57ff02e.js" defer></script><script src="main.a1204c9aa64b1cc15d28.js" defer></script>
<script src="runtime.415291667f70565cd8ef.js" defer></script><script src="polyfills-es5.865074f5cd9a121111a2.js" nomodule defer></script><script src="polyfills.2f91a039d848e57ff02e.js" defer></script><script src="main.c83939cdfe3af0ec27df.js" defer></script>
</body></html>
@@ -1 +1 @@
(self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[]).push([[179],{98255:function(ue){function q(f){return Promise.resolve().then(function(){var B=new Error("Cannot find module '"+f+"'");throw B.code="MODULE_NOT_FOUND",B})}q.keys=function(){return[]},q.resolve=q,q.id=98255,ue.exports=q},82908:function(ue){ue.exports=function(f,B){(null==B||B>f.length)&&(B=f.length);for(var U=0,V=new Array(B);U<B;U++)V[U]=f[U];return V},ue.exports.default=ue.exports,ue.exports.__esModule=!0},36457:function(ue){ue.exports=function(f){if(Array.isArray(f))return f},ue.exports.default=ue.exports,ue.exports.__esModule=!0},35036:function(ue){ue.exports=function(f,B){var U=null==f?null:"undefined"!=typeof Symbol&&f[Symbol.iterator]||f["@@iterator"];if(null!=U){var N,b,V=[],Z=!0,w=!1;try{for(U=U.call(f);!(Z=(N=U.next()).done)&&(V.push(N.value),!B||V.length!==B);Z=!0);}catch(_){w=!0,b=_}finally{try{!Z&&null!=U.return&&U.return()}finally{if(w)throw b}}return V}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},13969:function(ue){ue.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},ue.exports.default=ue.exports,ue.exports.__esModule=!0},6326:function(ue,q,f){var B=f(36457),U=f(35036),V=f(54850),Z=f(13969);ue.exports=function(N,b){return B(N)||U(N,b)||V(N,b)||Z()},ue.exports.default=ue.exports,ue.exports.__esModule=!0},54850:function(ue,q,f){var B=f(82908);ue.exports=function(V,Z){if(V){if("string"==typeof V)return B(V,Z);var w=Object.prototype.toString.call(V).slice(8,-1);if("Object"===w&&V.constructor&&(w=V.constructor.name),"Map"===w||"Set"===w)return Array.from(V);if("Arguments"===w||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(w))return B(V,Z)}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},26552:function(ue,q,f){ue.exports=f(55590)},61855:function(ue,q,f){"use strict";f.d(q,{ZT:function(){return U},mG:function(){return _},Jh:function(){return I},ev:function(){return R}});var B=function($,ae){return(B=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(se,ce){se.__proto__=ce}||function(se,ce){for(var le in ce)Object.prototype.hasOwnProperty.call(ce,le)&&(se[le]=ce[le])})($,ae)};function U($,ae){if("function"!=typeof ae&&null!==ae)throw new TypeError("Class extends value "+String(ae)+" is not a constructor or null");function se(){this.constructor=$}B($,ae),$.prototype=null===ae?Object.create(ae):(se.prototype=ae.prototype,new se)}function _($,ae,se,ce){return new(se||(se=Promise))(function(oe,Ae){function be(_t){try{qe(ce.next(_t))}catch(yt){Ae(yt)}}function it(_t){try{qe(ce.throw(_t))}catch(yt){Ae(yt)}}function qe(_t){_t.done?oe(_t.value):function(oe){return oe instanceof se?oe:new se(function(Ae){Ae(oe)})}(_t.value).then(be,it)}qe((ce=ce.apply($,ae||[])).next())})}function I($,ae){var ce,le,oe,Ae,se={label:0,sent:function(){if(1&oe[0])throw oe[1];return oe[1]},trys:[],ops:[]};return Ae={next:be(0),throw:be(1),return:be(2)},"function"==typeof Symbol&&(Ae[Symbol.iterator]=function(){return this}),Ae;function be(qe){return function(_t){return function(qe){if(ce)throw new TypeError("Generator is already executing.");for(;se;)try{if(ce=1,le&&(oe=2&qe[0]?le.return:qe[0]?le.throw||((oe=le.return)&&oe.call(le),0):le.next)&&!(oe=oe.call(le,qe[1])).done)return oe;switch(le=0,oe&&(qe=[2&qe[0],oe.value]),qe[0]){case 0:case 1:oe=qe;break;case 4:return se.label++,{value:qe[1],done:!1};case 5:se.label++,le=qe[1],qe=[0];continue;case 7:qe=se.ops.pop(),se.trys.pop();continue;default:if(!(oe=(oe=se.trys).length>0&&oe[oe.length-1])&&(6===qe[0]||2===qe[0])){se=0;continue}if(3===qe[0]&&(!oe||qe[1]>oe[0]&&qe[1]<oe[3])){se.label=qe[1];break}if(6===qe[0]&&se.label<oe[1]){se.label=oe[1],oe=qe;break}if(oe&&se.label<oe[2]){se.label=oe[2],se.ops.push(qe);break}oe[2]&&se.ops.pop(),se.trys.pop();continue}qe=ae.call($,se)}catch(_t){qe=[6,_t],le=0}finally{ce=oe=0}if(5&qe[0])throw qe[1];return{value:qe[0]?qe[1]:void 0,done:!0}}([qe,_t])}}}function R($,ae,se){if(se||2===arguments.length)for(var oe,ce=0,le=ae.length;ce<le;ce++)(oe||!(ce in ae))&&(oe||(oe=Array.prototype.slice.call(ae,0,ce)),oe[ce]=ae[ce]);return $.concat(oe||Array.prototype.slice.call(ae))}},739:function(ue,q,f){"use strict";f.d(q,{l3:function(){return w},_j:function(){return V},LC:function(){return Z},ZN:function(){return O},jt:function(){return b},pV:function(){return T},F4:function(){return S},IO:function(){return k},vP:function(){return I},SB:function(){return A},oB:function(){return D},eR:function(){return v},X$:function(){return N},ZE:function(){return F},k1:function(){return z}});var B=f(14105),U=f(18967),V=function K(){(0,U.Z)(this,K)},Z=function K(){(0,U.Z)(this,K)},w="*";function N(K,j){return{type:7,name:K,definitions:j,options:{}}}function b(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return{type:4,styles:j,timings:K}}function I(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]Line truncated
(self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[]).push([[179],{98255:function(ue){function q(f){return Promise.resolve().then(function(){var B=new Error("Cannot find module '"+f+"'");throw B.code="MODULE_NOT_FOUND",B})}q.keys=function(){return[]},q.resolve=q,q.id=98255,ue.exports=q},82908:function(ue){ue.exports=function(f,B){(null==B||B>f.length)&&(B=f.length);for(var U=0,V=new Array(B);U<B;U++)V[U]=f[U];return V},ue.exports.default=ue.exports,ue.exports.__esModule=!0},36457:function(ue){ue.exports=function(f){if(Array.isArray(f))return f},ue.exports.default=ue.exports,ue.exports.__esModule=!0},35036:function(ue){ue.exports=function(f,B){var U=null==f?null:"undefined"!=typeof Symbol&&f[Symbol.iterator]||f["@@iterator"];if(null!=U){var N,b,V=[],Z=!0,w=!1;try{for(U=U.call(f);!(Z=(N=U.next()).done)&&(V.push(N.value),!B||V.length!==B);Z=!0);}catch(_){w=!0,b=_}finally{try{!Z&&null!=U.return&&U.return()}finally{if(w)throw b}}return V}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},13969:function(ue){ue.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")},ue.exports.default=ue.exports,ue.exports.__esModule=!0},6326:function(ue,q,f){var B=f(36457),U=f(35036),V=f(54850),Z=f(13969);ue.exports=function(N,b){return B(N)||U(N,b)||V(N,b)||Z()},ue.exports.default=ue.exports,ue.exports.__esModule=!0},54850:function(ue,q,f){var B=f(82908);ue.exports=function(V,Z){if(V){if("string"==typeof V)return B(V,Z);var w=Object.prototype.toString.call(V).slice(8,-1);if("Object"===w&&V.constructor&&(w=V.constructor.name),"Map"===w||"Set"===w)return Array.from(V);if("Arguments"===w||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(w))return B(V,Z)}},ue.exports.default=ue.exports,ue.exports.__esModule=!0},26552:function(ue,q,f){ue.exports=f(55590)},61855:function(ue,q,f){"use strict";f.d(q,{ZT:function(){return U},mG:function(){return _},Jh:function(){return I},ev:function(){return R}});var B=function($,ae){return(B=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(se,ce){se.__proto__=ce}||function(se,ce){for(var le in ce)Object.prototype.hasOwnProperty.call(ce,le)&&(se[le]=ce[le])})($,ae)};function U($,ae){if("function"!=typeof ae&&null!==ae)throw new TypeError("Class extends value "+String(ae)+" is not a constructor or null");function se(){this.constructor=$}B($,ae),$.prototype=null===ae?Object.create(ae):(se.prototype=ae.prototype,new se)}function _($,ae,se,ce){return new(se||(se=Promise))(function(oe,Ae){function be(_t){try{qe(ce.next(_t))}catch(yt){Ae(yt)}}function it(_t){try{qe(ce.throw(_t))}catch(yt){Ae(yt)}}function qe(_t){_t.done?oe(_t.value):function(oe){return oe instanceof se?oe:new se(function(Ae){Ae(oe)})}(_t.value).then(be,it)}qe((ce=ce.apply($,ae||[])).next())})}function I($,ae){var ce,le,oe,Ae,se={label:0,sent:function(){if(1&oe[0])throw oe[1];return oe[1]},trys:[],ops:[]};return Ae={next:be(0),throw:be(1),return:be(2)},"function"==typeof Symbol&&(Ae[Symbol.iterator]=function(){return this}),Ae;function be(qe){return function(_t){return function(qe){if(ce)throw new TypeError("Generator is already executing.");for(;se;)try{if(ce=1,le&&(oe=2&qe[0]?le.return:qe[0]?le.throw||((oe=le.return)&&oe.call(le),0):le.next)&&!(oe=oe.call(le,qe[1])).done)return oe;switch(le=0,oe&&(qe=[2&qe[0],oe.value]),qe[0]){case 0:case 1:oe=qe;break;case 4:return se.label++,{value:qe[1],done:!1};case 5:se.label++,le=qe[1],qe=[0];continue;case 7:qe=se.ops.pop(),se.trys.pop();continue;default:if(!(oe=(oe=se.trys).length>0&&oe[oe.length-1])&&(6===qe[0]||2===qe[0])){se=0;continue}if(3===qe[0]&&(!oe||qe[1]>oe[0]&&qe[1]<oe[3])){se.label=qe[1];break}if(6===qe[0]&&se.label<oe[1]){se.label=oe[1],oe=qe;break}if(oe&&se.label<oe[2]){se.label=oe[2],se.ops.push(qe);break}oe[2]&&se.ops.pop(),se.trys.pop();continue}qe=ae.call($,se)}catch(_t){qe=[6,_t],le=0}finally{ce=oe=0}if(5&qe[0])throw qe[1];return{value:qe[0]?qe[1]:void 0,done:!0}}([qe,_t])}}}function R($,ae,se){if(se||2===arguments.length)for(var oe,ce=0,le=ae.length;ce<le;ce++)(oe||!(ce in ae))&&(oe||(oe=Array.prototype.slice.call(ae,0,ce)),oe[ce]=ae[ce]);return $.concat(oe||Array.prototype.slice.call(ae))}},739:function(ue,q,f){"use strict";f.d(q,{l3:function(){return w},_j:function(){return V},LC:function(){return Z},ZN:function(){return O},jt:function(){return b},pV:function(){return T},F4:function(){return S},IO:function(){return k},vP:function(){return I},SB:function(){return A},oB:function(){return D},eR:function(){return v},X$:function(){return N},ZE:function(){return F},k1:function(){return z}});var B=f(14105),U=f(18967),V=function K(){(0,U.Z)(this,K)},Z=function K(){(0,U.Z)(this,K)},w="*";function N(K,j){return{type:7,name:K,definitions:j,options:{}}}function b(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return{type:4,styles:j,timings:K}}function I(K){var j=arguments.length>1&&void 0!==arguments[1]?arguments[1]Line truncated
+12
View File
@@ -23,6 +23,7 @@ import textwrap
import posixpath
import socket
import errno
import hashlib
def force_unix_path(path):
@@ -120,3 +121,14 @@ def is_ipv6_enabled() -> bool:
if e.errno == errno.EADDRINUSE:
return True
raise
def md5sum(filename):
"""
Calculate the MD5 checksum of a file.
"""
hash_md5 = hashlib.md5()
with open(filename, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
+14 -10
View File
@@ -161,14 +161,17 @@ class ZipFile(zipfile.ZipFile):
self._comment = comment
self._didModify = True
async def data_generator(self, path):
async def data_generator(self, path, islink=False):
async with aiofiles.open(path, "rb") as f:
while True:
part = await f.read(self._chunksize)
if not part:
break
yield part
if islink:
yield os.readlink(path).encode()
else:
async with aiofiles.open(path, "rb") as f:
while True:
part = await f.read(self._chunksize)
if not part:
break
yield part
return
async def _run_in_executor(self, task, *args, **kwargs):
@@ -224,12 +227,13 @@ class ZipFile(zipfile.ZipFile):
raise ValueError("either (exclusively) filename or iterable shall be not None")
if filename:
st = os.stat(filename)
st = os.stat(filename, follow_symlinks=False)
isdir = stat.S_ISDIR(st.st_mode)
islink = stat.S_ISLNK(st.st_mode)
mtime = time.localtime(st.st_mtime)
date_time = mtime[0:6]
else:
st, isdir, date_time = None, False, time.localtime()[0:6]
st, isdir, islink, date_time = None, False, False, time.localtime()[0:6]
# Create ZipInfo instance to store file information
if arcname is None:
arcname = filename
@@ -282,7 +286,7 @@ class ZipFile(zipfile.ZipFile):
file_size = 0
if filename:
async for buf in self.data_generator(filename):
async for buf in self.data_generator(filename, islink):
file_size = file_size + len(buf)
CRC = zipfile.crc32(buf, CRC) & 0xffffffff
if cmpr:
+44 -28
View File
@@ -45,7 +45,7 @@ def list_images(emulator_type):
# We limit recursion to path outside the default images directory
# the reason is in the default directory manage file organization and
# it should be flatten to keep things simple
# it should be flat to keep things simple
recurse = True
if os.path.commonprefix([directory, general_images_directory]) == general_images_directory:
recurse = False
@@ -53,37 +53,53 @@ def list_images(emulator_type):
directory = os.path.normpath(directory)
for root, _, filenames in _os_walk(directory, recurse=recurse):
for filename in filenames:
if filename not in files:
if filename.endswith(".md5sum") or filename.startswith("."):
if filename in files:
log.debug("File {} has already been found, skipping...".format(filename))
continue
if filename.endswith(".md5sum") or filename.startswith("."):
continue
files.add(filename)
filesize = os.stat(os.path.join(root, filename)).st_size
if filesize < 7:
log.debug("File {} is too small to be an image, skipping...".format(filename))
continue
try:
with open(os.path.join(root, filename), "rb") as f:
# read the first 7 bytes of the file.
elf_header_start = f.read(7)
if emulator_type == "dynamips" and elf_header_start != b'\x7fELF\x01\x02\x01':
# IOS images must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
log.warning("IOS image {} does not start with a valid ELF magic number, skipping...".format(filename))
continue
elif emulator_type == "iou" and elf_header_start != b'\x7fELF\x02\x01\x01' and elf_header_start != b'\x7fELF\x01\x01\x01':
# IOU images must start with the ELF magic number, be 32-bit or 64-bit, little endian and have an ELF version of 1
log.warning("IOU image {} does not start with a valid ELF magic number, skipping...".format(filename))
continue
elif emulator_type == "qemu" and elf_header_start[:4] == b'\x7fELF':
# QEMU images should not start with an ELF magic number
log.warning("QEMU image {} starts with an ELF magic number, skipping...".format(filename))
continue
elif ((filename.endswith(".image") or filename.endswith(".bin")) and emulator_type == "dynamips") \
or ((filename.endswith(".bin") or filename.startswith("i86bi")) and emulator_type == "iou") \
or (not filename.endswith(".bin") and not filename.endswith(".image") and emulator_type == "qemu"):
files.add(filename)
# It the image is located in the standard directory the path is relative
if os.path.commonprefix([root, default_directory]) != default_directory:
path = os.path.join(root, filename)
else:
path = os.path.relpath(os.path.join(root, filename), default_directory)
# It the image is located in the standard directory the path is relative
if os.path.commonprefix([root, default_directory]) != default_directory:
path = os.path.join(root, filename)
else:
path = os.path.relpath(os.path.join(root, filename), default_directory)
try:
if emulator_type in ["dynamips", "iou"]:
with open(os.path.join(root, filename), "rb") as f:
# read the first 7 bytes of the file.
elf_header_start = f.read(7)
# valid IOU or IOS images must start with the ELF magic number, be 32-bit or 64-bit,
# little endian and have an ELF version of 1
if elf_header_start != b'\x7fELF\x02\x01\x01' and elf_header_start != b'\x7fELF\x01\x01\x01':
continue
images.append(
{
"filename": filename,
"path": force_unix_path(path),
"md5sum": md5sum(os.path.join(root, filename)),
"filesize": filesize
}
)
images.append({
"filename": filename,
"path": force_unix_path(path),
"md5sum": md5sum(os.path.join(root, filename)),
"filesize": os.stat(os.path.join(root, filename)).st_size})
except OSError as e:
log.warning("Can't add image {}: {}".format(path, str(e)))
except OSError as e:
log.warning("Can't add image {}: {}".format(path, str(e)))
return images
+2 -2
View File
@@ -23,8 +23,8 @@
# or negative for a release candidate or beta (after the base version
# number has been incremented)
__version__ = "2.2.48.1"
__version_info__ = (2, 2, 48, -99)
__version__ = "2.2.53"
__version_info__ = (2, 2, 53, 0)
if "dev" in __version__:
try:
+7 -1
View File
@@ -311,7 +311,13 @@ class WebServer:
# Background task started with the server
self._app.on_startup.append(self._on_startup)
resource_options = aiohttp_cors.ResourceOptions(allow_credentials=True, expose_headers="*", allow_headers="*", max_age=0)
resource_options = aiohttp_cors.ResourceOptions(
allow_credentials=True,
expose_headers="*",
allow_headers="*",
allow_methods="*",
max_age=0
)
# Allow CORS for this domains
cors = aiohttp_cors.setup(self._app, defaults={
+8 -8
View File
@@ -1,13 +1,13 @@
jsonschema>=4.22.0,<4.23
aiohttp>=3.9.5,<3.10
jsonschema>=4.23,<4.24
aiohttp>=3.10.10,<3.11
aiohttp-cors>=0.7.0,<0.8
aiofiles>=24.1.0,<25.0
Jinja2>=3.1.4,<3.2
sentry-sdk==2.7.1,<2.8
psutil==6.0.0
async-timeout>=4.0.3,<4.1
Jinja2>=3.1.5,<3.2
sentry-sdk>=2.19.2,<2.20 # optional dependency
psutil>=6.1.1
async-timeout>=5.0.1,<5.1
distro>=1.9.0
py-cpuinfo>=9.0.0,<10.0
platformdirs>=2.4.0
platformdirs>=2.4.0,<3 # platformdirs >=3 conflicts when building Debian packages
importlib-resources>=1.3; python_version < '3.9'
truststore>=0.9.1; python_version >= '3.10'
truststore>=0.10.0; python_version >= '3.10'
+108 -145
View File
@@ -1,6 +1,6 @@
#!/bin/bash
#
# Copyright (C) 2015 GNS3 Technologies Inc.
# Copyright (C) 2024 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,19 +16,20 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Install GNS3 on a remote Ubuntu LTS server
# This create a dedicated user and setup all the package
# and optionnaly a VPN
# Install GNS3 on a remote Ubuntu server
# This creates a dedicated user and setup all the packages
# and optionally a VPN
#
function help {
echo "Usage:" >&2
echo "--with-openvpn: Install OpenVPN" >&2
echo "--with-iou: Install IOU" >&2
echo "--with-i386-repository: Add the i386 repositories required by IOU if they are not already available on the system. Warning: this will replace your source.list in order to use the official Ubuntu mirror" >&2
echo "--with-iou: Install IOU support" >&2
echo "--with-i386-repository: Add the i386 repositories required by IOU i386 images. This is not needed for recent x86_64 IOU images." >&2
echo "--with-welcome: Install GNS3-VM welcome.py script" >&2
echo "--without-kvm: Disable KVM, required if system do not support it (limitation in some hypervisors and cloud providers). Warning: only disable KVM if strictly necessary as this will degrade performance" >&2
echo "--unstable: Use the GNS3 unstable repository"
echo "--unstable: Use the GNS3 unstable repository" >&2
echo "--custom-repository <repository>: Use a custom repository" >&2
echo "--help: This help" >&2
}
@@ -43,15 +44,17 @@ then
exit 1
fi
# Default repository
REPOSITORY="ppa"
# Read the options
USE_VPN=0
USE_IOU=0
I386_REPO=0
DISABLE_KVM=0
UNSTABLE=0
WELCOME_SETUP=0
TEMP=`getopt -o h --long with-openvpn,with-iou,with-i386-repository,with-welcome,without-kvm,unstable,help -n 'gns3-remote-install.sh' -- "$@"`
TEMP=`getopt -o h --long with-openvpn,with-iou,with-i386-repository,with-welcome,without-kvm,unstable,custom-repository:,help -n 'gns3-remote-install.sh' -- "$@"`
if [ $? != 0 ]
then
help
@@ -83,9 +86,13 @@ while true ; do
shift
;;
--unstable)
UNSTABLE=1
REPOSITORY="unstable"
shift
;;
--custom-repository)
REPOSITORY="$2"
shift 2
;;
-h|--help)
help
exit 1
@@ -103,91 +110,93 @@ UBUNTU_CODENAME=`lsb_release -c -s`
log "Add GNS3 repository"
if [ "$UBUNTU_CODENAME" == "trusty" ]
if [ ! -f "/etc/apt/sources.list.d/ubuntu.sources" ]
then
if [ $UNSTABLE == 1 ]
then
cat <<EOFLIST > /etc/apt/sources.list.d/gns3.list
deb http://ppa.launchpad.net/gns3/unstable/ubuntu $UBUNTU_CODENAME main
deb-src http://ppa.launchpad.net/gns3/unstable/ubuntu $UBUNTU_CODENAME main
deb http://ppa.launchpad.net/gns3/qemu/ubuntu $UBUNTU_CODENAME main
deb-src http://ppa.launchpad.net/gns3/qemu/ubuntu $UBUNTU_CODENAME main
EOFLIST
else
cat <<EOFLIST > /etc/apt/sources.list.d/gns3.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys B83AAABFFBD82D21B543C8EA86C22C2EC6A24D7F
cat <<EOFLIST > /etc/apt/sources.list.d/gns3.list
deb http://ppa.launchpad.net/gns3/ppa/ubuntu $UBUNTU_CODENAME main
deb-src http://ppa.launchpad.net/gns3/ppa/ubuntu $UBUNTU_CODENAME main
deb http://ppa.launchpad.net/gns3/qemu/ubuntu $UBUNTU_CODENAME main
deb-src http://ppa.launchpad.net/gns3/qemu/ubuntu $UBUNTU_CODENAME main
EOFLIST
fi
else
if [ $UNSTABLE == 1 ]
then
cat <<EOFLIST > /etc/apt/sources.list.d/gns3.list
deb http://ppa.launchpad.net/gns3/unstable/ubuntu $UBUNTU_CODENAME main
deb-src http://ppa.launchpad.net/gns3/unstable/ubuntu $UBUNTU_CODENAME main
cat <<EOFLIST > /etc/apt/sources.list.d/gns3-ppa.sources
Types: deb
URIs: https://ppa.launchpadcontent.net/gns3/$REPOSITORY/ubuntu/
Suites: $UBUNTU_CODENAME
Components: main
Signed-By:
-----BEGIN PGP PUBLIC KEY BLOCK-----
.
mQINBGY0jSYBEADMH5CvX8ZVX4XzAxdQ2CmF7t86IjFnQgtI18Q19nVnpKEGNyB5
pgotDMzkhGnxuhvz2zE9PZhd8VgkodB81V607d/Dy8FfI7t1BVQhLvJDx0H/q6RE
n2y9WxiuBzTHitoQTCTY3hjcr7AUNFFI64gUqwbkQmYbCWWsYOlDpRSkWKg8P8WK
08RetwTI0Iwoz8j+BkbPlubuImiVfh1TeH23FBuGIwL1r1Cps0wel6JAi+jaU9WG
j8MX3mQYFTAtk7f1lRubqWosB/A4xIu609pF1e1tAkWAGltYAeoFhDn+PfA9KgmV
fvxfVR7zmxp31imTJgXgUFCz+H0Xb3vpve8XsrsHZUP6StJ3+6cFXjNBV6PuO1FT
JWp86a+AYHg7+sUWcoJRZPCTbb/pOcCa0q1ch5qcLkiYEOGK+pYhbPptq6y8IsJW
N6EDNCVvVqVyTJy14FZWoOqxcpUiDOQ+su28j8++V+PMo+FO3SQqwEZwJXk7LF/4
wUipDCUh/WNjDqqgmYLoO+ttiiJPbEw3jtbO+zopbzYpyEC1f06Nz7uz1daOIN3J
etFPzSqWCE7Eq+hoVmAAm8gVmQir3rFJbIGBAvAaOLQEOkUlOlS7AezqUhdyhGER
Zrvc3eNqxY7G61SEHipEJ7/hpcDq0RRWCXHsoQqyHaPje826n2pGkJYt4QARAQAB
tBZMYXVuY2hwYWQgUFBBIGZvciBHTlMziQJOBBMBCgA4FiEEuDqqv/vYLSG1Q8jq
hsIsLsaiTX8FAmY0jSYCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQhsIs
LsaiTX9z9xAAq1uHmRgfYmELS0cr2YEnTWHPVE6s95Qx+0cr5zzNeWfmoAS9uSyl
z8bCm+Q2ZapzU/nOtkozU+RGjgcRRTKMVTyS0PjFX22965xHCRWnw79fPyrYouUw
H2cAT8WSGYEeVAbqhJSns0RnDpXuaxmWE1wT+iitY/QAjeXo22Z2mjv2bFTitKbY
hZbE5Eu8Olc5YHCVI0ofq84/Ii921iMibU6EDMmm/iOnMK2uHGbC59t0YG8Rm7mK
uk6+TpxOULjFeCWSkF2Dr33m8JQmtYZuFUnmqWPuSdBo3J0O1b0qTg+EP9FbDAtj
CoEKT/V1ccMBd3r77o23CGsvpV7bzEU60A+NsU8vb/AkOmouYiF+qaYDFGZDfWhK
p1HFmd1kt7YdgxsmoKoFJkbt1bBdcFJLV0Jcad5sfArg2aFDYf2giMxAw4iQ+9jc
MCuwWxiqWicPqJ5erNTzVfayBkjuZqBDVTO9wmG3DL4QmNosIBS7kq+NGrT8Ql22
FqYfdIZJDlKVtJKHK8eKJSB0dbFawV2h5p/CvQlIm6nthg5FzOyjvCkPkvxvveq+
SuNxFEscumFCgo7j7RMWHW9HWK3TUvMmYLMVjxL8kXyCwknp9GklBQHA/IPxRa/2
eFqqkmVbmNAoMzzw5wqa/BPcFEbgn+E+TFyZqbzp0F4QzPJZFkz16SA=
=xnj5
-----END PGP PUBLIC KEY BLOCK-----
EOFLIST
else
cat <<EOFLIST > /etc/apt/sources.list.d/gns3.list
deb http://ppa.launchpad.net/gns3/ppa/ubuntu $UBUNTU_CODENAME main
deb-src http://ppa.launchpad.net/gns3/ppa/ubuntu $UBUNTU_CODENAME main
EOFLIST
fi
fi
if [ $I386_REPO == 1 ]
then
cat <<EOFLIST2 >> /etc/apt/sources.list
###### Ubuntu Main Repos
deb http://archive.ubuntu.com/ubuntu/ $UBUNTU_CODENAME main universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ $UBUNTU_CODENAME main universe multiverse
log "Updating system packages and installing curl"
apt update
apt install -y curl
###### Ubuntu Update Repos
deb http://archive.ubuntu.com/ubuntu/ ${UBUNTU_CODENAME}-security main universe multiverse
deb http://archive.ubuntu.com/ubuntu/ ${UBUNTU_CODENAME}-updates main universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ ${UBUNTU_CODENAME}-security main universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ ${UBUNTU_CODENAME}-updates main universe multiverse
EOFLIST2
fi
log "Upgrading packages"
apt upgrade --yes --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys A2E3EF7B
log "Installing the GNS3 server and its dependencies"
apt install -y gns3-server
log "Update system packages"
apt-get update
log "Upgrade packages"
apt-get upgrade --yes --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"
log "Install GNS3 packages"
apt-get install -y gns3-server
log "Create user GNS3 with /opt/gns3 as home directory"
log "Creating user GNS3 with /opt/gns3 as home directory"
if [ ! -d "/opt/gns3" ]
then
useradd -m -d /opt/gns3 gns3
fi
log "Add GNS3 to the ubridge group"
log "Adding GNS3 to the ubridge group"
usermod -aG ubridge gns3
log "Install docker"
log "Installing Docker"
if [ ! -f "/usr/bin/docker" ]
then
curl -sSL https://get.docker.com | bash
fi
log "Add GNS3 to the docker group"
log "Adding GNS3 to the docker group"
usermod -aG docker gns3
if [ $USE_IOU == 1 ]
then
log "Setup IOU"
dpkg --add-architecture i386
apt-get update
log "Setting up IOU support"
if [ $I386_REPO == 1 ]
then
log "Enabling i386 architecture for IOU support"
dpkg --add-architecture i386
apt update
fi
apt-get install -y gns3-iou
apt install -y gns3-iou
# Force the host name to gns3vm
echo gns3vm > /etc/hostname
@@ -196,21 +205,18 @@ then
# Force hostid for IOU
dd if=/dev/zero bs=4 count=1 of=/etc/hostid
# Block iou call. The server is down
echo "127.0.0.254 xml.cisco.com" | tee --append /etc/hosts
fi
log "Add gns3 to the kvm group"
log "Adding gns3 to the kvm group"
usermod -aG kvm gns3
log "Setup GNS3 server"
log "Setting up the GNS3 server configuration"
mkdir -p /etc/gns3
cat <<EOFC > /etc/gns3/gns3_server.conf
[Server]
host = 0.0.0.0
port = 3080
port = 3080
images_path = /opt/gns3/images
projects_path = /opt/gns3/projects
appliances_path = /opt/gns3/appliances
@@ -224,52 +230,15 @@ EOFC
if [ $DISABLE_KVM == 1 ]
then
log "Disable KVM support"
log "Disabling KVM support"
sed -i 's/hardware_acceleration = True/hardware_acceleration = False/g' /etc/gns3/gns3_server.conf
fi
chown -R gns3:gns3 /etc/gns3
chmod -R 700 /etc/gns3
if [ "$UBUNTU_CODENAME" == "trusty" ]
then
cat <<EOFI > /etc/init/gns3.conf
description "GNS3 server"
author "GNS3 Team"
start on filesystem or runlevel [2345]
stop on runlevel [016]
respawn
console log
script
exec start-stop-daemon --start --make-pidfile --pidfile /var/run/gns3.pid --chuid gns3 --exec "/usr/bin/gns3server"
end script
pre-start script
echo "" > /var/log/upstart/gns3.log
echo "[`date`] GNS3 Starting"
end script
pre-stop script
echo "[`date`] GNS3 Stopping"
end script
EOFI
chown root:root /etc/init/gns3.conf
chmod 644 /etc/init/gns3.conf
log "Start GNS3 service"
set +e
service gns3 stop
set -e
service gns3 start
else
# Install systemd service
cat <<EOFI > /lib/systemd/system/gns3.service
log "Installing the GNS3 systemd service"
cat <<EOFI > /lib/systemd/system/gns3.service
[Unit]
Description=GNS3 server
After=network-online.target
@@ -292,15 +261,15 @@ LimitNOFILE=16384
[Install]
WantedBy=multi-user.target
EOFI
chmod 755 /lib/systemd/system/gns3.service
chown root:root /lib/systemd/system/gns3.service
log "Start GNS3 service"
systemctl enable gns3
systemctl start gns3
fi
chmod 755 /lib/systemd/system/gns3.service
chown root:root /lib/systemd/system/gns3.service
log "GNS3 installed with success"
log "Starting the GNS3 service"
systemctl enable gns3
systemctl start gns3
log "GNS3 has been installed with success"
if [ $WELCOME_SETUP == 1 ]
then
@@ -309,11 +278,9 @@ gns3 ALL = (ALL) NOPASSWD: /usr/bin/apt-key
gns3 ALL = (ALL) NOPASSWD: /usr/bin/apt-get
gns3 ALL = (ALL) NOPASSWD: /usr/sbin/reboot
EOFI
NEEDRESTART_MODE=a apt-get install -y net-tools
NEEDRESTART_MODE=a apt-get install -y python3-pip
NEEDRESTART_MODE=a apt-get install -y dialog
pip install --no-input --upgrade pip
pip install --no-input pythondialog
NEEDRESTART_MODE=a apt install -y net-tools
NEEDRESTART_MODE=a apt install -y dialog
NEEDRESTART_MODE=a apt install -y python3-dialog
#Pull down welcome script from repo
curl https://raw.githubusercontent.com/GNS3/gns3-server/master/scripts/welcome.py > /usr/local/bin/welcome.py
@@ -340,19 +307,15 @@ fi
if [ $USE_VPN == 1 ]
then
log "Setup VPN"
log "Setting up OpenVPN"
log "Change GNS3 to listen on VPN interface"
log "Changing the GNS3 server configuration to listen on VPN interface"
sed -i 's/host = 0.0.0.0/host = 172.16.253.1/' /etc/gns3/gns3_server.conf
log "Install packages for OpenVPN"
log "Installing the OpenVPN packages"
apt-get install -y \
openvpn \
uuid \
dnsutils \
nginx-light
apt install -y openvpn uuid dnsutils nginx-light
MY_IP_ADDR=$(dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short -4 | sed 's/"//g')
@@ -360,7 +323,7 @@ log "IP detected: $MY_IP_ADDR"
UUID=$(uuid)
log "Update motd"
log "Updating motd"
cat <<EOFMOTD > /etc/update-motd.d/70-openvpn
#!/bin/sh
@@ -371,7 +334,7 @@ echo "http://$MY_IP_ADDR:8003/$UUID/$HOSTNAME.ovpn"
echo ""
echo "And add it to your openvpn client."
echo ""
echo "apt-get remove nginx-light to disable the HTTP server."
echo "apt remove nginx-light to disable the HTTP server."
echo "And remove this file with rm /etc/update-motd.d/70-openvpn"
EOFMOTD
chmod 755 /etc/update-motd.d/70-openvpn
@@ -381,7 +344,7 @@ mkdir -p /etc/openvpn/
[ -d /dev/net ] || mkdir -p /dev/net
[ -c /dev/net/tun ] || mknod /dev/net/tun c 10 200
log "Create keys"
log "Creating OpenVPN keys"
[ -f /etc/openvpn/dh.pem ] || openssl dhparam -out /etc/openvpn/dh.pem 2048
[ -f /etc/openvpn/key.pem ] || openssl genrsa -out /etc/openvpn/key.pem 2048
@@ -389,7 +352,7 @@ chmod 600 /etc/openvpn/key.pem
[ -f /etc/openvpn/csr.pem ] || openssl req -new -key /etc/openvpn/key.pem -out /etc/openvpn/csr.pem -subj /CN=OpenVPN/
[ -f /etc/openvpn/cert.pem ] || openssl x509 -req -in /etc/openvpn/csr.pem -out /etc/openvpn/cert.pem -signkey /etc/openvpn/key.pem -days 24855
log "Create client configuration"
log "Creating OpenVPN client configuration"
cat <<EOFCLIENT > /root/client.ovpn
client
nobind
@@ -431,7 +394,7 @@ status openvpn-status-1194.log
log-append /var/log/openvpn-udp1194.log
EOFUDP
log "Setup HTTP server for serving client certificate"
log "Setting up an HTTP server for serving client certificate"
mkdir -p /usr/share/nginx/openvpn/$UUID
cp /root/client.ovpn /usr/share/nginx/openvpn/$UUID/$HOSTNAME.ovpn
touch /usr/share/nginx/openvpn/$UUID/index.html
@@ -448,7 +411,7 @@ EOFNGINX
service nginx stop
service nginx start
log "Restart OpenVPN and GNS3"
log "Restarting OpenVPN and GNS3"
set +e
service openvpn stop
@@ -456,15 +419,15 @@ service openvpn start
service gns3 stop
service gns3 start
log "Download http://$MY_IP_ADDR:8003/$UUID/$HOSTNAME.ovpn to setup your OpenVPN client after rebooting the server"
log "Please download http://$MY_IP_ADDR:8003/$UUID/$HOSTNAME.ovpn to setup your OpenVPN client after rebooting the server"
fi
if [ $WELCOME_SETUP == 1 ]
then
NEEDRESTART_MODE=a apt-get update
NEEDRESTART_MODE=a apt-get upgrade
python3 -c 'import sys; sys.path.append("/usr/local/bin/"); import welcome; ws = welcome.Welcome_dialog(); ws.repair_remote_install()'
cd /opt/gns3
su gns3
NEEDRESTART_MODE=a apt update
NEEDRESTART_MODE=a apt upgrade
python3 -c 'import sys; sys.path.append("/usr/local/bin/"); import welcome; ws = welcome.Welcome_dialog(); ws.repair_remote_install()'
cd /opt/gns3
su gns3
fi
+6 -8
View File
@@ -16,16 +16,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import os
import shutil
import subprocess
from setuptools import setup, find_packages
from setuptools.command.test import test as TestCommand
# we only support Python 3 version >= 3.7
if len(sys.argv) >= 2 and sys.argv[1] == "install" and sys.version_info < (3, 7):
raise SystemExit("Python 3.7 or higher is required")
# we only support Python 3 version >= 3.8
if len(sys.argv) >= 2 and sys.argv[1] == "install" and sys.version_info < (3, 8):
raise SystemExit("Python 3.8 or higher is required")
class PyTest(TestCommand):
@@ -67,8 +64,8 @@ setup(
include_package_data=True,
zip_safe=False,
platforms="any",
python_requires='>=3.7',
setup_requires=["setuptools>=17.1"],
python_requires=">=3.8",
setup_requires=["setuptools>=45.2"],
classifiers=[
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
@@ -86,6 +83,7 @@ setup(
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
],
)
+63 -16
View File
@@ -48,6 +48,7 @@ async def vm(compute_project, manager):
vm = DockerVM("test", str(uuid.uuid4()), compute_project, manager, "ubuntu:latest")
vm._cid = "e90e34656842"
vm.allocate_aux = False
vm.mac_address = '02:42:3d:b7:93:00'
return vm
@@ -60,6 +61,7 @@ def test_json(vm, compute_project):
'project_id': compute_project.id,
'node_id': vm.id,
'adapters': 1,
'mac_address': '02:42:3d:b7:93:00',
'console': vm.console,
'console_type': 'telnet',
'console_resolution': '1024x768',
@@ -105,7 +107,8 @@ async def test_create(compute_project, manager):
"{}:/gns3:ro".format(Docker.resources_path()),
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network"))
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -143,7 +146,8 @@ async def test_create_with_tag(compute_project, manager):
"{}:/gns3:ro".format(Docker.resources_path()),
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network"))
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -185,7 +189,8 @@ async def test_create_vnc(compute_project, manager):
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network")),
"/tmp/.X11-unix/X{0}:/tmp/.X11-unix/X{0}:ro".format(vm._display)
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -314,7 +319,8 @@ async def test_create_start_cmd(compute_project, manager):
"{}:/gns3:ro".format(Docker.resources_path()),
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network"))
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"Entrypoint": ["/gns3/init.sh"],
@@ -412,7 +418,8 @@ async def test_create_image_not_available(compute_project, manager):
"{}:/gns3:ro".format(Docker.resources_path()),
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network"))
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -455,7 +462,8 @@ async def test_create_with_user(compute_project, manager):
"{}:/gns3:ro".format(Docker.resources_path()),
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network"))
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -538,7 +546,8 @@ async def test_create_with_extra_volumes_duplicate_1_image(compute_project, mana
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network")),
"{}:/gns3volumes/vol/1".format(os.path.join(vm.working_dir, "vol", "1")),
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -577,7 +586,8 @@ async def test_create_with_extra_volumes_duplicate_2_user(compute_project, manag
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network")),
"{}:/gns3volumes/vol/1".format(os.path.join(vm.working_dir, "vol", "1")),
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -616,7 +626,8 @@ async def test_create_with_extra_volumes_duplicate_3_subdir(compute_project, man
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network")),
"{}:/gns3volumes/vol".format(os.path.join(vm.working_dir, "vol")),
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -655,7 +666,8 @@ async def test_create_with_extra_volumes_duplicate_4_backslash(compute_project,
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network")),
"{}:/gns3volumes/vol".format(os.path.join(vm.working_dir, "vol")),
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -693,7 +705,8 @@ async def test_create_with_extra_volumes_duplicate_5_subdir_issue_1595(compute_p
"{}:/gns3:ro".format(Docker.resources_path()),
"{}:/gns3volumes/etc".format(os.path.join(vm.working_dir, "etc")),
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -731,7 +744,8 @@ async def test_create_with_extra_volumes_duplicate_6_subdir_issue_1595(compute_p
"{}:/gns3:ro".format(Docker.resources_path()),
"{}:/gns3volumes/etc".format(os.path.join(vm.working_dir, "etc")),
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -777,7 +791,8 @@ async def test_create_with_extra_volumes(compute_project, manager):
"{}:/gns3volumes/vol/1".format(os.path.join(vm.working_dir, "vol", "1")),
"{}:/gns3volumes/vol/2".format(os.path.join(vm.working_dir, "vol", "2")),
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -1025,7 +1040,8 @@ async def test_update(vm):
"{}:/gns3:ro".format(Docker.resources_path()),
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network"))
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -1093,7 +1109,8 @@ async def test_update_running(vm):
"{}:/gns3:ro".format(Docker.resources_path()),
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network"))
],
"Privileged": True
"Privileged": True,
"UsernsMode": "host"
},
"Volumes": {},
"NetworkDisabled": True,
@@ -1185,7 +1202,37 @@ async def test_add_ubridge_connection(vm):
call.send('bridge start bridge0')
]
assert 'bridge0' in vm._bridges
# We need to check any_order ortherwise mock is confused by asyncio
# We need to check any_order otherwise mock is confused by asyncio
vm._ubridge_hypervisor.assert_has_calls(calls, any_order=True)
async def test_add_ubridge_connections_with_base_mac_address(vm):
vm._ubridge_hypervisor = MagicMock()
vm._namespace = 42
vm.adapters = 2
vm.mac_address = "02:42:42:42:42:00"
nio_params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"}
nio = vm.manager.create_nio(nio_params)
await vm._add_ubridge_connection(nio, 0)
nio = vm.manager.create_nio(nio_params)
await vm._add_ubridge_connection(nio, 1)
calls = [
call.send('bridge create bridge0'),
call.send('bridge create bridge1'),
call.send('docker set_mac_addr tap-gns3-e0 02:42:42:42:42:00'),
call.send('docker set_mac_addr tap-gns3-e0 02:42:42:42:42:01')
]
# We need to check any_order otherwise mock is confused by asyncio
vm._ubridge_hypervisor.assert_has_calls(calls, any_order=True)
+13 -12
View File
@@ -96,7 +96,7 @@ async def test_start(vm):
mock_process = MagicMock()
vm._check_requirements = AsyncioMagicMock(return_value=True)
vm._check_iou_licence = AsyncioMagicMock(return_value=True)
vm._check_iou_license = AsyncioMagicMock(return_value=True)
vm._start_ubridge = AsyncioMagicMock(return_value=True)
vm._ubridge_send = AsyncioMagicMock()
@@ -108,7 +108,7 @@ async def test_start(vm):
assert vm.command_line == ' '.join(mock_exec.call_args[0])
assert vm._check_requirements.called
assert vm._check_iou_licence.called
assert vm._check_iou_license.called
assert vm._start_ubridge.called
vm._ubridge_send.assert_any_call("iol_bridge delete IOL-BRIDGE-513")
vm._ubridge_send.assert_any_call("iol_bridge create IOL-BRIDGE-513 513")
@@ -123,7 +123,8 @@ async def test_start_with_iourc(vm, tmpdir):
mock_process = MagicMock()
vm._check_requirements = AsyncioMagicMock(return_value=True)
vm._check_iou_licence = AsyncioMagicMock(return_value=True)
vm._is_iou_license_check_enabled = AsyncioMagicMock(return_value=True)
vm._check_iou_license = AsyncioMagicMock(return_value=True)
vm._start_ioucon = AsyncioMagicMock(return_value=True)
vm._start_ubridge = AsyncioMagicMock(return_value=True)
vm._ubridge_send = AsyncioMagicMock()
@@ -158,7 +159,7 @@ async def test_stop(vm):
process = MagicMock()
vm._check_requirements = AsyncioMagicMock(return_value=True)
vm._check_iou_licence = AsyncioMagicMock(return_value=True)
vm._check_iou_license = AsyncioMagicMock(return_value=True)
vm._start_ioucon = AsyncioMagicMock(return_value=True)
vm._start_ubridge = AsyncioMagicMock(return_value=True)
vm._ubridge_send = AsyncioMagicMock()
@@ -183,7 +184,7 @@ async def test_reload(vm, fake_iou_bin):
process = MagicMock()
vm._check_requirements = AsyncioMagicMock(return_value=True)
vm._check_iou_licence = AsyncioMagicMock(return_value=True)
vm._check_iou_license = AsyncioMagicMock(return_value=True)
vm._start_ioucon = AsyncioMagicMock(return_value=True)
vm._start_ubridge = AsyncioMagicMock(return_value=True)
vm._ubridge_send = AsyncioMagicMock()
@@ -376,42 +377,42 @@ def test_get_legacy_vm_workdir():
async def test_invalid_iou_file(vm, iourc_file):
hostname = socket.gethostname()
await vm._check_iou_licence()
await vm._check_iou_license()
# Missing ;
with pytest.raises(IOUError):
with open(iourc_file, "w+") as f:
f.write("[license]\n{} = aaaaaaaaaaaaaaaa".format(hostname))
await vm._check_iou_licence()
await vm._check_iou_license()
# Key too short
with pytest.raises(IOUError):
with open(iourc_file, "w+") as f:
f.write("[license]\n{} = aaaaaaaaaaaaaa;".format(hostname))
await vm._check_iou_licence()
await vm._check_iou_license()
# Invalid hostname
with pytest.raises(IOUError):
with open(iourc_file, "w+") as f:
f.write("[license]\nbla = aaaaaaaaaaaaaa;")
await vm._check_iou_licence()
await vm._check_iou_license()
# Missing licence section
with pytest.raises(IOUError):
with open(iourc_file, "w+") as f:
f.write("[licensetest]\n{} = aaaaaaaaaaaaaaaa;")
await vm._check_iou_licence()
await vm._check_iou_license()
# Broken config file
with pytest.raises(IOUError):
with open(iourc_file, "w+") as f:
f.write("[")
await vm._check_iou_licence()
await vm._check_iou_license()
# Missing file
with pytest.raises(IOUError):
os.remove(iourc_file)
await vm._check_iou_licence()
await vm._check_iou_license()
def test_iourc_content(vm):
+14 -3
View File
@@ -353,16 +353,23 @@ async def test_set_platform(compute_project, manager):
async def test_disk_options(vm, tmpdir, fake_qemu_img_binary):
vm._hda_disk_image = str(tmpdir / "test.qcow2")
vm._hda_disk_interface = "ide"
vm._hdb_disk_image = str(tmpdir / "test2.qcow2")
open(vm._hda_disk_image, "w+").close()
open(vm._hdb_disk_image, "w+").close()
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM._find_disk_file_format", return_value="qcow2"):
with (asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM._find_disk_file_format", return_value="qcow2")):
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
options = await vm._disk_options()
assert process.called
args, kwargs = process.call_args
assert args == (fake_qemu_img_binary, "create", "-o", "backing_file={}".format(vm._hda_disk_image), "-F", "qcow2", "-f", "qcow2", os.path.join(vm.working_dir, "hda_disk.qcow2"))
assert args == (fake_qemu_img_binary, "create", "-o", "backing_file={}".format(vm._hda_disk_image), "-F", "qcow2", "-f", "qcow2", os.path.join(vm.working_dir, "hda_disk.qcow2")) or \
args == (fake_qemu_img_binary, "create", "-o", "backing_file={}".format(vm._hdb_disk_image), "-F", "qcow2", "-f", "qcow2", os.path.join(vm.working_dir, "hdb_disk.qcow2"))
assert options == ['-drive', 'file=' + os.path.join(vm.working_dir, "hda_disk.qcow2") + ',if=ide,index=0,media=disk,id=drive0']
assert options == [
'-drive', 'file=' + os.path.join(vm.working_dir, "hda_disk.qcow2") + ',if=ide,index=0,media=disk,id=drive0',
'-drive', 'file=' + os.path.join(vm.working_dir, "hdb_disk.qcow2") + ',if=none,index=1,media=disk,id=drive1',
]
async def test_cdrom_option(vm, tmpdir, fake_qemu_img_binary):
@@ -440,9 +447,13 @@ async def test_tpm_option(vm, tmpdir, fake_qemu_img_binary):
async def test_disk_options_multiple_disk(vm, tmpdir, fake_qemu_img_binary):
vm._hda_disk_image = str(tmpdir / "test0.qcow2")
vm._hda_disk_interface = "ide"
vm._hdb_disk_image = str(tmpdir / "test1.qcow2")
vm._hdb_disk_interface = "ide"
vm._hdc_disk_image = str(tmpdir / "test2.qcow2")
vm._hdc_disk_interface = "ide"
vm._hdd_disk_image = str(tmpdir / "test3.qcow2")
vm._hdd_disk_interface = "ide"
open(vm._hda_disk_image, "w+").close()
open(vm._hdb_disk_image, "w+").close()
open(vm._hdc_disk_image, "w+").close()
+8 -8
View File
@@ -239,12 +239,12 @@ async def test_list_images(qemu, tmpdir):
os.makedirs(tmp_images_dir, exist_ok=True)
for image in fake_images:
with open(os.path.join(tmp_images_dir, image), "w+") as f:
f.write("1")
f.write("1234567")
with patch("gns3server.utils.images.default_images_directory", return_value=str(tmp_images_dir)):
assert sorted(await qemu.list_images(), key=lambda k: k['filename']) == [
{"filename": "a.qcow2", "path": "a.qcow2", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1},
{"filename": "b.qcow2", "path": "b.qcow2", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1}
{"filename": "a.qcow2", "path": "a.qcow2", "md5sum": "fcea920f7412b5da7be0cf42b8c93759", "filesize": 7},
{"filename": "b.qcow2", "path": "b.qcow2", "md5sum": "fcea920f7412b5da7be0cf42b8c93759", "filesize": 7}
]
@@ -255,19 +255,19 @@ async def test_list_images_recursives(qemu, tmpdir):
fake_images = ["a.qcow2", "b.qcow2", ".blu.qcow2", "a.qcow2.md5sum"]
for image in fake_images:
with open(os.path.join(tmp_images_dir, image), "w+") as f:
f.write("1")
f.write("1234567")
os.makedirs(os.path.join(tmp_images_dir, "c"))
fake_images = ["c.qcow2", "c.qcow2.md5sum"]
for image in fake_images:
with open(os.path.join(tmp_images_dir, "c", image), "w+") as f:
f.write("1")
f.write("1234567")
with patch("gns3server.utils.images.default_images_directory", return_value=str(tmp_images_dir)):
assert sorted(await qemu.list_images(), key=lambda k: k['filename']) == [
{"filename": "a.qcow2", "path": "a.qcow2", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1},
{"filename": "b.qcow2", "path": "b.qcow2", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1},
{"filename": "c.qcow2", "path": force_unix_path(os.path.sep.join(["c", "c.qcow2"])), "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1}
{"filename": "a.qcow2", "path": "a.qcow2", "md5sum": "fcea920f7412b5da7be0cf42b8c93759", "filesize": 7},
{"filename": "b.qcow2", "path": "b.qcow2", "md5sum": "fcea920f7412b5da7be0cf42b8c93759", "filesize": 7},
{"filename": "c.qcow2", "path": force_unix_path(os.path.sep.join(["c", "c.qcow2"])), "md5sum": "fcea920f7412b5da7be0cf42b8c93759", "filesize": 7}
]
+7 -7
View File
@@ -85,7 +85,7 @@ async def test_compute_httpQuery(compute):
response.status = 200
await compute.post("/projects", {"a": "b"})
await compute.close()
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=120)
assert compute._auth is None
@@ -99,7 +99,7 @@ async def test_compute_httpQueryAuth(compute):
compute.password = "toor"
await compute.post("/projects", {"a": "b"})
await compute.close()
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=compute._auth, chunked=None, timeout=20)
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=b'{"a": "b"}', headers={'content-type': 'application/json'}, auth=compute._auth, chunked=None, timeout=120)
assert compute._auth.login == "root"
assert compute._auth.password == "toor"
@@ -156,7 +156,7 @@ async def test_compute_httpQueryNotConnectedInvalidVersion(compute):
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
with pytest.raises(aiohttp.web.HTTPConflict):
await compute.post("/projects", {"a": "b"})
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=120)
await compute.close()
@@ -169,7 +169,7 @@ async def test_compute_httpQueryNotConnectedNonGNS3Server(compute):
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
with pytest.raises(aiohttp.web.HTTPConflict):
await compute.post("/projects", {"a": "b"})
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=120)
await compute.close()
@@ -182,7 +182,7 @@ async def test_compute_httpQueryNotConnectedNonGNS3Server2(compute):
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
with pytest.raises(aiohttp.web.HTTPConflict):
await compute.post("/projects", {"a": "b"})
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=20)
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=None, timeout=120)
async def test_compute_httpQueryError(compute):
@@ -217,7 +217,7 @@ async def test_compute_httpQuery_project(compute):
project = Project(name="Test")
mock_notification.assert_called()
await compute.post("/projects", project)
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=json.dumps(project.__json__()), headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=json.dumps(project.__json__()), headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=120)
await compute.close()
# FIXME: https://github.com/aio-libs/aiohttp/issues/2525
@@ -424,7 +424,7 @@ async def test_interfaces(compute):
response.status = 200
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
assert await compute.interfaces() == res
mock.assert_any_call("GET", "https://example.com:84/v2/compute/network/interfaces", auth=None, chunked=None, data=None, headers={'content-type': 'application/json'}, timeout=20)
mock.assert_any_call("GET", "https://example.com:84/v2/compute/network/interfaces", auth=None, chunked=None, data=None, headers={'content-type': 'application/json'}, timeout=120)
await compute.close()
+7 -1
View File
@@ -21,6 +21,7 @@ import json
import pytest
import aiohttp
import zipfile
import stat
from pathlib import Path
from unittest.mock import patch
@@ -116,6 +117,8 @@ async def test_export(tmpdir, project):
with open(os.path.join(path, "project-files", "snapshots", "test"), 'w+') as f:
f.write("WORLD")
os.symlink("/tmp/anywhere", os.path.join(path, "vm-1", "dynamips", "symlink"))
with aiozipstream.ZipFile() as z:
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),):
await export_project(z, project, str(tmpdir), include_images=False)
@@ -131,9 +134,12 @@ async def test_export(tmpdir, project):
assert 'vm-1/dynamips/empty-dir/' in myzip.namelist()
assert 'project-files/snapshots/test' not in myzip.namelist()
assert 'vm-1/dynamips/test_log.txt' not in myzip.namelist()
assert 'images/IOS/test.image' not in myzip.namelist()
assert 'vm-1/dynamips/symlink' in myzip.namelist()
zip_info = myzip.getinfo('vm-1/dynamips/symlink')
assert stat.S_ISLNK(zip_info.external_attr >> 16)
with myzip.open("project.gns3") as myfile:
topo = json.loads(myfile.read().decode())["topology"]
assert topo["nodes"][0]["compute_id"] == "local" # All node should have compute_id local after export
+52
View File
@@ -21,7 +21,11 @@ import json
import zipfile
from tests.utils import asyncio_patch, AsyncioMagicMock
from unittest.mock import patch, MagicMock
from gns3server.utils.asyncio import aiozipstream
from gns3server.controller.project import Project
from gns3server.controller.export_project import export_project
from gns3server.controller.import_project import import_project, _move_files_to_compute
from gns3server.version import __version__
@@ -106,6 +110,54 @@ async def test_import_project_override(tmpdir, controller):
assert project.name == "test"
async def write_file(path, z):
with open(path, 'wb') as f:
async for chunk in z:
f.write(chunk)
async def test_import_project_containing_symlink(tmpdir, controller):
project = Project(controller=controller, name="test")
project.dump = MagicMock()
path = project.path
project_id = str(uuid.uuid4())
topology = {
"project_id": str(uuid.uuid4()),
"name": "test",
"auto_open": True,
"auto_start": True,
"topology": {
},
"version": "2.0.0"
}
with open(os.path.join(path, "project.gns3"), 'w+') as f:
json.dump(topology, f)
os.makedirs(os.path.join(path, "vm1", "dynamips"))
symlink_path = os.path.join(project.path, "vm1", "dynamips", "symlink")
symlink_target = "/tmp/anywhere"
os.symlink(symlink_target, symlink_path)
zip_path = str(tmpdir / "project.zip")
with aiozipstream.ZipFile() as z:
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),):
await export_project(z, project, str(tmpdir), include_images=False)
await write_file(zip_path, z)
with open(zip_path, "rb") as f:
project = await import_project(controller, project_id, f)
assert project.name == "test"
assert project.id == project_id
symlink_path = os.path.join(project.path, "vm1", "dynamips", "symlink")
assert os.path.islink(symlink_path)
assert os.readlink(symlink_path) == symlink_target
async def test_import_upgrade(tmpdir, controller):
"""
Topology made for previous GNS3 version are upgraded during the process
+2 -2
View File
@@ -144,7 +144,7 @@ def fake_image(tmpdir):
path = str(tmpdir / "7200.bin")
with open(path, "wb+") as f:
f.write(b'\x7fELF\x01\x01\x01')
f.write(b'\x7fELF\x01\x02\x01')
os.chmod(path, stat.S_IREAD)
return path
@@ -168,7 +168,7 @@ async def test_images(compute_api, tmpdir, fake_image, fake_file):
assert response.json == [{"filename": "7200.bin",
"path": "7200.bin",
"filesize": 7,
"md5sum": "e573e8f5c93c6c00783f20c7a170aa6c"
"md5sum": "b0d5aa897d937aced5a6b1046e8f7e2e"
}]
+3 -3
View File
@@ -45,7 +45,7 @@ def fake_qemu_vm(images_dir):
img_dir = os.path.join(images_dir, "QEMU")
bin_path = os.path.join(img_dir, "linux载.img")
with open(bin_path, "w+") as f:
f.write("1")
f.write("1234567")
os.chmod(bin_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
return bin_path
@@ -101,7 +101,7 @@ async def test_qemu_create_with_params(compute_api, compute_project, base_params
assert response.json["project_id"] == compute_project.id
assert response.json["ram"] == 1024
assert response.json["hda_disk_image"] == "linux载.img"
assert response.json["hda_disk_image_md5sum"] == "c4ca4238a0b923820dcc509a6f75849b"
assert response.json["hda_disk_image_md5sum"] == "fcea920f7412b5da7be0cf42b8c93759"
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
@@ -279,7 +279,7 @@ async def test_images(compute_api, fake_qemu_vm):
response = await compute_api.get("/qemu/images")
assert response.status == 200
assert {"filename": "linux载.img", "path": "linux载.img", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1} in response.json
assert {"filename": "linux载.img", "path": "linux载.img", "md5sum": "fcea920f7412b5da7be0cf42b8c93759", "filesize": 7} in response.json
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Does not work on Windows")
+59 -34
View File
@@ -114,66 +114,91 @@ def test_remove_checksum(tmpdir):
def test_list_images(tmpdir):
path1 = tmpdir / "images1" / "IOS" / "test1.image"
path1.write(b'\x7fELF\x01\x01\x01', ensure=True)
path1 = force_unix_path(str(path1))
# IOS image in the images directory
ios_image_1 = tmpdir / "images1" / "IOS" / "ios_image_1.image"
ios_image_1.write(b'\x7fELF\x01\x02\x01', ensure=True)
ios_image_1 = force_unix_path(str(ios_image_1))
path2 = tmpdir / "images2" / "test2.image"
path2.write(b'\x7fELF\x01\x01\x01', ensure=True)
path2 = force_unix_path(str(path2))
# IOS image in an additional images path
ios_image_2 = tmpdir / "images2" / "ios_image_2.image"
ios_image_2.write(b'\x7fELF\x01\x02\x01', ensure=True)
ios_image_2 = force_unix_path(str(ios_image_2))
# Invalid image because not a valid elf file
path = tmpdir / "images2" / "test_invalid.image"
path.write(b'NOTANELF', ensure=True)
# Not a valid elf file
not_elf_file = tmpdir / "images1" / "IOS" / "not_elf.image"
not_elf_file.write(b'NOTANELF', ensure=True)
not_elf_file = force_unix_path(str(not_elf_file))
# Invalid image because it is very small
small_file = tmpdir / "images1" / "too_small.image"
small_file.write(b'1', ensure=True)
if sys.platform.startswith("linux"):
path3 = tmpdir / "images1" / "IOU" / "test3.bin"
path3.write(b'\x7fELF\x02\x01\x01', ensure=True)
path3 = force_unix_path(str(path3))
# 64-bit IOU image
iou_image_1 = tmpdir / "images1" / "IOU" / "iou64.bin"
iou_image_1.write(b'\x7fELF\x02\x01\x01', ensure=True)
iou_image_1 = force_unix_path(str(iou_image_1))
# 32-bit IOU image
iou_image_2 = tmpdir / "images1" / "IOU" / "iou32.bin"
iou_image_2.write(b'\x7fELF\x01\x01\x01', ensure=True) # 32-bit IOU image
iou_image_2 = force_unix_path(str(iou_image_2))
path4 = tmpdir / "images1" / "QEMU" / "test4.qcow2"
path4.write("1", ensure=True)
path4 = force_unix_path(str(path4))
path5 = tmpdir / "images1" / "QEMU" / "test4.qcow2.md5sum"
path5.write("1", ensure=True)
path5 = force_unix_path(str(path5))
# Qemu image
qemu_image_1 = tmpdir / "images1" / "QEMU" / "qemu_image.qcow2"
qemu_image_1.write("1234567", ensure=True)
qemu_image_1 = force_unix_path(str(qemu_image_1))
# ELF file inside the Qemu
elf_file = tmpdir / "images1" / "QEMU" / "elf_file.bin"
elf_file.write(b'\x7fELF\x02\x01\x01', ensure=True) # ELF file
elf_file = force_unix_path(str(elf_file))
md5sum_file = tmpdir / "images1" / "QEMU" / "image.qcow2.md5sum"
md5sum_file.write("1", ensure=True)
md5sum_file = force_unix_path(str(md5sum_file))
with patch("gns3server.config.Config.get_section_config", return_value={
"images_path": str(tmpdir / "images1"),
"additional_images_path": "/tmp/null24564;{}".format(str(tmpdir / "images2")),
"local": False}):
assert list_images("dynamips") == [
assert sorted(list_images("dynamips"), key=lambda k: k['filename']) == [
{
'filename': 'test1.image',
'filename': 'ios_image_1.image',
'filesize': 7,
'md5sum': 'e573e8f5c93c6c00783f20c7a170aa6c',
'path': 'test1.image'
'md5sum': 'b0d5aa897d937aced5a6b1046e8f7e2e',
'path': 'ios_image_1.image'
},
{
'filename': 'test2.image',
'filename': 'ios_image_2.image',
'filesize': 7,
'md5sum': 'e573e8f5c93c6c00783f20c7a170aa6c',
'path': str(path2)
'md5sum': 'b0d5aa897d937aced5a6b1046e8f7e2e',
'path': str(ios_image_2)
}
]
if sys.platform.startswith("linux"):
assert list_images("iou") == [
assert sorted(list_images("iou"), key=lambda k: k['filename']) == [
{
'filename': 'test3.bin',
'filename': 'iou32.bin',
'filesize': 7,
'md5sum': 'e573e8f5c93c6c00783f20c7a170aa6c',
'path': 'iou32.bin'
},
{
'filename': 'iou64.bin',
'filesize': 7,
'md5sum': 'c73626d23469519894d58bc98bee9655',
'path': 'test3.bin'
}
'path': 'iou64.bin'
},
]
assert list_images("qemu") == [
assert sorted(list_images("qemu"), key=lambda k: k['filename']) == [
{
'filename': 'test4.qcow2',
'filesize': 1,
'md5sum': 'c4ca4238a0b923820dcc509a6f75849b',
'path': 'test4.qcow2'
'filename': 'qemu_image.qcow2',
'filesize': 7,
'md5sum': 'fcea920f7412b5da7be0cf42b8c93759',
'path': 'qemu_image.qcow2'
}
]