mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-07 15:43:43 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8014da10b | ||
|
|
f6080013e3 | ||
|
|
fc54c6e496 | ||
|
|
04cd107651 | ||
|
|
19cabdfde6 | ||
|
|
af7fbe6bb4 | ||
|
|
3d58b437b4 | ||
|
|
83921a45df | ||
|
|
11c9802268 | ||
|
|
a60e0d424d | ||
|
|
db1fb29c63 | ||
|
|
a5f0dba5cf | ||
|
|
754680d8e9 | ||
|
|
05773ce189 | ||
|
|
aeae9deb01 | ||
|
|
f3749e83ec | ||
|
|
c2db4e8542 | ||
|
|
52a7696618 | ||
|
|
7bf17392dd | ||
|
|
fb06eb3c0c | ||
|
|
753135a80d | ||
|
|
c05e1cb8e7 | ||
|
|
48b7e6ca50 | ||
|
|
dbe2b8a5fb | ||
|
|
80487eb62d | ||
|
|
6e66b26b88 | ||
|
|
9990666076 | ||
|
|
97e5a5edc3 | ||
|
|
2b5c6ce8fb | ||
|
|
0aac62d03a | ||
|
|
4058abf16e | ||
|
|
4357410b10 | ||
|
|
734365b216 | ||
|
|
abb7cc2075 | ||
|
|
c273a78560 | ||
|
|
718269e5b3 | ||
|
|
19fd7d2193 | ||
|
|
e62ffb1b87 | ||
|
|
42808161bf | ||
|
|
45ee662c56 | ||
|
|
24bfc205db | ||
|
|
cb46c0fbcc | ||
|
|
35256901b5 | ||
|
|
6933c3d938 | ||
|
|
8af71ee291 | ||
|
|
c0be6875c2 | ||
|
|
a1922ef067 | ||
|
|
cafdb2522b | ||
|
|
f7996d5e98 | ||
|
|
996dad2f5c | ||
|
|
1332e940fd | ||
|
|
19bd953d31 | ||
|
|
3a896b6964 | ||
|
|
441f0fb1b5 | ||
|
|
a02b57698a | ||
|
|
7582107ae5 | ||
|
|
2dbde5df22 | ||
|
|
7b5d123ad8 | ||
|
|
d1a7474ef6 | ||
|
|
af6f34b2ca | ||
|
|
f1294cf267 | ||
|
|
74782d413f | ||
|
|
c41c11eb34 | ||
|
|
1f09a3e6bc | ||
|
|
22f022cc22 | ||
|
|
8429494280 | ||
|
|
ddd6235acd | ||
|
|
bcc148bbd2 | ||
|
|
3792901dc7 | ||
|
|
5ffe5fd9b3 | ||
|
|
69a5b16bad | ||
|
|
21a5c5d3f2 | ||
|
|
225779bc11 | ||
|
|
b1209155f5 | ||
|
|
7cebb9472a | ||
|
|
00c3b1abc1 | ||
|
|
b1c1c0520c | ||
|
|
2bb26075f0 | ||
|
|
6746ef39be | ||
|
|
8889eaa439 | ||
|
|
95a4c284bc | ||
|
|
6951137a25 | ||
|
|
cccbca3d5e | ||
|
|
8659439829 | ||
|
|
677bc389a5 | ||
|
|
4a58ede550 | ||
|
|
3f5b0bb514 | ||
|
|
35f94b0c73 | ||
|
|
b82b9a64e6 | ||
|
|
901652aaeb | ||
|
|
6c9a3b634b | ||
|
|
19142d97bb | ||
|
|
faf7e09ebb | ||
|
|
4959a51ce7 | ||
|
|
5bab4131e1 |
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 }}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,49 @@
|
||||
# Change Log
|
||||
|
||||
## 2.2.52 02/12/2024
|
||||
|
||||
* Bundle web-ui v2.2.52
|
||||
* Sync appliances
|
||||
* 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
|
||||
|
||||
## 2.2.48 08/07/2024
|
||||
|
||||
* Bundle web-ui v2.2.48
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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": {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -13,11 +13,17 @@
|
||||
"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.iol",
|
||||
"version": "17.15.1",
|
||||
"md5sum": "6c587cdfd5056078e70b3f6c26800d66",
|
||||
"filesize": 243251976
|
||||
},
|
||||
{
|
||||
"filename": "x86_64_crb_linux_l2-adventerprisek9-ms.bin",
|
||||
"version": "17.12.1",
|
||||
@@ -44,6 +50,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "17.15.1",
|
||||
"images": {
|
||||
"image": "x86_64_crb_linux_l2-adventerprisek9-ms.iol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "17.12.1",
|
||||
"images": {
|
||||
|
||||
@@ -13,11 +13,17 @@
|
||||
"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.iol",
|
||||
"version": "17.15.1",
|
||||
"md5sum": "5d584f6cfbeaadc87d55f613da1049ed",
|
||||
"filesize": 292001512
|
||||
},
|
||||
{
|
||||
"filename": "x86_64_crb_linux-adventerprisek9-ms.bin",
|
||||
"version": "17.12.1",
|
||||
@@ -44,6 +50,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "17.15.1",
|
||||
"images": {
|
||||
"image": "x86_64_crb_linux-adventerprisek9-ms.iol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "17.12.1",
|
||||
"images": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"arch": "x86_64",
|
||||
"console_type": "vnc",
|
||||
"kvm": "require",
|
||||
"options": "-nographic"
|
||||
"options": "-nographic -machine q35,smbios-entry-point-type=32"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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": {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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,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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"symbol": "linux_guest.svg",
|
||||
"docker": {
|
||||
"adapters": 1,
|
||||
"image": "gns3/ubuntu:focal",
|
||||
"image": "gns3/ubuntu:noble",
|
||||
"console_type": "telnet"
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}")
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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:
|
||||
|
||||
@@ -57,7 +57,7 @@ class CrashReport:
|
||||
Report crash to a third party service
|
||||
"""
|
||||
|
||||
DSN = "https://3fb84d1ee07fa46b3638825e30cb8f05@o19455.ingest.us.sentry.io/38482"
|
||||
DSN = "https://b2ea85d65646be3f56aebf2458337918@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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,6 +1,4 @@
|
||||
<html lang="en"><head><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.b65e52314df938ebe652.js" defer></script>
|
||||
|
||||
|
||||
<!DOCTYPE html><html lang="en"><head>
|
||||
<meta charset="utf-8">
|
||||
<title>GNS3 Web UI</title>
|
||||
<!-- It's important to have base here because of the script below //-->
|
||||
@@ -38,4 +36,16 @@
|
||||
<body class="mat-app-background" oncontextmenu="return false;">
|
||||
<app-root></app-root>
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
</body></html>
|
||||
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-0BT7QQV1W1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag('js', new Date());
|
||||
|
||||
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.9297104511b6616fc55c.js" defer></script>
|
||||
|
||||
</body></html>
|
||||
+1
-1
@@ -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
|
||||
@@ -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()
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
|
||||
__version__ = "2.2.48"
|
||||
__version_info__ = (2, 2, 48, 0)
|
||||
__version__ = "2.2.52"
|
||||
__version_info__ = (2, 2, 52, 0)
|
||||
|
||||
if "dev" in __version__:
|
||||
try:
|
||||
|
||||
+6
-6
@@ -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
|
||||
sentry-sdk>=2.17,<2.18 # optional dependency
|
||||
psutil>=6.1.0
|
||||
async-timeout>=4.0.3,<4.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'
|
||||
@@ -197,8 +197,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
|
||||
# Block potential IOU phone home call (xml.cisco.com is not in use at this time)
|
||||
log "Block IOU phone home call"
|
||||
if [ "$UBUNTU_CODENAME" == "focal" ]
|
||||
then
|
||||
iptables -I OUTPUT -p udp --dport 53 -m string --hex-string "|03|xml|05|cisco|03|com" --algo bm -j DROP
|
||||
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | debconf-set-selections
|
||||
echo iptables-persistent iptables-persistent/autosave_v6 boolean true | debconf-set-selections
|
||||
apt-get install -y iptables-persistent
|
||||
else
|
||||
echo "127.0.0.254 xml.cisco.com" | tee --append /etc/hosts
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
log "Add gns3 to the kvm group"
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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}
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}]
|
||||
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
+55
-30
@@ -114,30 +114,49 @@ 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"),
|
||||
@@ -146,34 +165,40 @@ def test_list_images(tmpdir):
|
||||
|
||||
assert list_images("dynamips") == [
|
||||
{
|
||||
'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") == [
|
||||
{
|
||||
'filename': 'test3.bin',
|
||||
'filename': 'iou64.bin',
|
||||
'filesize': 7,
|
||||
'md5sum': 'c73626d23469519894d58bc98bee9655',
|
||||
'path': 'test3.bin'
|
||||
'path': 'iou64.bin'
|
||||
},
|
||||
{
|
||||
'filename': 'iou32.bin',
|
||||
'filesize': 7,
|
||||
'md5sum': 'e573e8f5c93c6c00783f20c7a170aa6c',
|
||||
'path': 'iou32.bin'
|
||||
}
|
||||
]
|
||||
|
||||
assert list_images("qemu") == [
|
||||
{
|
||||
'filename': 'test4.qcow2',
|
||||
'filesize': 1,
|
||||
'md5sum': 'c4ca4238a0b923820dcc509a6f75849b',
|
||||
'path': 'test4.qcow2'
|
||||
'filename': 'qemu_image.qcow2',
|
||||
'filesize': 7,
|
||||
'md5sum': 'fcea920f7412b5da7be0cf42b8c93759',
|
||||
'path': 'qemu_image.qcow2'
|
||||
}
|
||||
]
|
||||
Reference in new issue
Block a user