Merge remote-tracking branch 'origin/3.0' into gh-pages

This commit is contained in:
github-actions 2024-08-11 17:36:16 +00:00
commit bb8cf65a13
61 changed files with 1330 additions and 142 deletions

View File

@ -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 }}

View File

@ -13,58 +13,81 @@ name: "CodeQL"
on:
push:
branches: [ master ]
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
branches: [ "master" ]
schedule:
- cron: '44 1 * * 3'
- cron: '21 12 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
include:
- language: python
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@ -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

View File

@ -20,9 +20,9 @@ jobs:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
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: Display Python version

View File

@ -1,5 +1,32 @@
# Change Log
## 3.0.0rc1 11/08/2024
* Bundle web-ui v3.0.0rc1
* Convert topologies < 3.0 to have valid node hostnames
* Fix to access resources_path and install_builtin_appliances settings
## 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
* Add 'install_builtin_appliances' and 'resources_path' settings in the server config
* Option to keep the compute IDs unchanged when exporting a project
* Forbid unsafe Qemu additional options
* Fix error when snapshot exists with an underscore in the name
* Upgrade sentry-sdk, psutil and aiofiles packages
* Fix check for IPv6 enabled on host
## 3.0.0b3 19/05/2024
* Bundle web-ui v3.0.0b3

View File

@ -1,7 +1,7 @@
pytest==8.1.1
flake8==7.0.0
pytest==8.3.2
flake8==7.1.0
pytest-timeout==2.3.1
pytest-asyncio==0.21.1
requests==2.31.0
pytest-asyncio==0.21.2
requests==2.32.3
httpx==0.24.1 # version 0.24.1 is required by httpx_ws
httpx_ws==0.4.2

View File

@ -320,6 +320,7 @@ async def export_project(
include_snapshots: bool = False,
include_images: bool = False,
reset_mac_addresses: bool = False,
keep_compute_ids: bool = False,
compression: schemas.ProjectCompression = "zstd",
compression_level: int = None,
) -> StreamingResponse:
@ -366,6 +367,7 @@ async def export_project(
tmpdir,
include_snapshots=include_snapshots,
include_images=include_images,
keep_compute_ids=keep_compute_ids,
reset_mac_addresses=reset_mac_addresses,
)
async for chunk in zstream:

View File

@ -32,6 +32,27 @@
"process_priority": "normal"
},
"images": [
{
"filename": "arubaoscx-disk-image-genericx86-p4-20240129204649.vmdk",
"version": "10.13.1000",
"md5sum": "a1a24b15e3b8a09b0c0f14bdfacc4a75",
"filesize": 395342848,
"download_url": "https://networkingsupport.hpe.com"
},
{
"filename": "arubaoscx-disk-image-genericx86-p4-20231110145644.vmdk",
"version": "10.13.0005",
"md5sum": "427fd4580e2ee3eac55a9e7d629d1375",
"filesize": 394995200,
"download_url": "https://networkingsupport.hpe.com"
},
{
"filename": "arubaoscx-disk-image-genericx86-p4-20230810165021.vmdk",
"version": "10.12.1000",
"md5sum": "ea89f94dda9d28bf583dc35e0299b106",
"filesize": 384622080,
"download_url": "https://networkingsupport.hpe.com"
},
{
"filename": "arubaoscx-disk-image-genericx86-p4-20230531220439.vmdk",
"version": "10.12.0006",
@ -118,6 +139,24 @@
}
],
"versions": [
{
"name": "10.13.1000",
"images": {
"hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20240129204649.vmdk"
}
},
{
"name": "10.13.0005",
"images": {
"hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20231110145644.vmdk"
}
},
{
"name": "10.12.1000",
"images": {
"hda_disk_image": "arubaoscx-disk-image-genericx86-p4-20230810165021.vmdk"
}
},
{
"name": "10.12.0006",
"images": {

View File

@ -19,7 +19,7 @@
},
"images": [
{
"filename": "x86_64_crb_linux_l2-adventerprisek9-ms",
"filename": "x86_64_crb_linux_l2-adventerprisek9-ms.bin",
"version": "17.12.1",
"md5sum": "2b5055e4cef8fd257416d74a94adb626",
"filesize": 240355720
@ -47,7 +47,7 @@
{
"name": "17.12.1",
"images": {
"image": "x86_64_crb_linux_l2-adventerprisek9-ms"
"image": "x86_64_crb_linux_l2-adventerprisek9-ms.bin"
}
},
{

View File

@ -19,7 +19,7 @@
},
"images": [
{
"filename": "x86_64_crb_linux-adventerprisek9-ms",
"filename": "x86_64_crb_linux-adventerprisek9-ms.bin",
"version": "17.12.1",
"md5sum": "4a2fce8de21d1831fbceffd155e41ae7",
"filesize": 288947184
@ -47,7 +47,7 @@
{
"name": "17.12.1",
"images": {
"image": "x86_64_crb_linux-adventerprisek9-ms"
"image": "x86_64_crb_linux-adventerprisek9-ms.bin"
}
},
{

View File

@ -23,6 +23,14 @@
"kvm": "allow"
},
"images": [
{
"filename": "debian-12.6.qcow2",
"version": "12.6",
"md5sum": "04753ba14295c6414d49bffe27b676ae",
"filesize": 280907776,
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
"direct_download_url": "https://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/debian-12.6.qcow2"
},
{
"filename": "debian-12.4.qcow2",
"version": "12.4",
@ -31,6 +39,14 @@
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
"direct_download_url": "https://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/debian-12.4.qcow2"
},
{
"filename": "debian-11.10.qcow2",
"version": "11.10",
"md5sum": "99a1dc8e110d641309674e69b630e732",
"filesize": 263520256,
"download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/",
"direct_download_url": "https://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/debian-11.10.qcow2"
},
{
"filename": "debian-11.8.qcow2",
"version": "11.8",
@ -41,12 +57,24 @@
}
],
"versions": [
{
"name": "12.6",
"images": {
"hda_disk_image": "debian-12.6.qcow2"
}
},
{
"name": "12.4",
"images": {
"hda_disk_image": "debian-12.4.qcow2"
}
},
{
"name": "11.10",
"images": {
"hda_disk_image": "debian-11.10.qcow2"
}
},
{
"name": "11.8",
"images": {

View File

@ -28,10 +28,17 @@
},
"images": [
{
"filename": "FAD_KVM-FORTINET.out.kvm-data.qcow2",
"version": "ALL",
"md5sum": "b7500835594e62d8acb1c6ec43d597c1",
"filesize": 30998528,
"filename": "FAD_KVM-V7.4.4-build0347-FORTINET.out.kvm_boot.qcow2",
"version": "7.4.4",
"md5sum": "52fa343fd423a1a560473b8cf02f4c9c",
"filesize": 180617216,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-V7.2.6-build0257-FORTINET.out.kvm_boot.qcow2",
"version": "7.2.6",
"md5sum": "ed8c3622b12212786c310aa94c928f06",
"filesize": 146341888,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
@ -41,6 +48,13 @@
"filesize": 145817600,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-v7.1.4-build0138-FORTINET.out.kvm_boot.qcow2",
"version": "7.1.4",
"md5sum": "d4b3ff27fc9d0461199d6066174744ca",
"filesize": 134152192,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-V7.1.1-build0117-FORTINET.out.kvm-boot.qcow2",
"version": "7.1.1",
@ -243,9 +257,30 @@
"md5sum": "7a71f52bde93c0000b047626731b7aef",
"filesize": 68026368,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-FORTINET.out.kvm-data.qcow2",
"version": "ALL",
"md5sum": "b7500835594e62d8acb1c6ec43d597c1",
"filesize": 30998528,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
}
],
"versions": [
{
"name": "7.4.4",
"images": {
"hda_disk_image": "FAD_KVM-V7.4.4-build0347-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2"
}
},
{
"name": "7.2.6",
"images": {
"hda_disk_image": "FAD_KVM-V7.2.6-build0257-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2"
}
},
{
"name": "7.2.0",
"images": {
@ -253,6 +288,13 @@
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2"
}
},
{
"name": "7.1.4",
"images": {
"hda_disk_image": "FAD_KVM-v7.1.4-build0138-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2"
}
},
{
"name": "7.1.1",
"images": {

View File

@ -29,6 +29,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FAZ_VM64_KVM-v7.4.3-build2487-FORTINET.out.kvm.qcow2",
"version": "7.4.3",
"md5sum": "c58709af18516763ed88f58621447bf6",
"filesize": 504463360,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.4.2-build2397-FORTINET.out.kvm.qcow2",
"version": "7.4.2",
@ -43,6 +50,13 @@
"filesize": 435310592,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.2.5-build1574-FORTINET.out.kvm.qcow2",
"version": "7.2.5",
"md5sum": "225d7405f35f78a482cffa34ef90080d",
"filesize": 379973632,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.2.4-build1460-FORTINET.out.kvm.qcow2",
"version": "7.2.4",
@ -64,6 +78,13 @@
"filesize": 340631552,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.0.12-build0623-FORTINET.out.kvm.qcow2",
"version": "7.0.12",
"md5sum": "a45f8987ea13da836c684b5d9850c1c2",
"filesize": 349560832,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v7.0.11-build0595-FORTINET.out.kvm.qcow2",
"version": "7.0.11",
@ -256,6 +277,13 @@
}
],
"versions": [
{
"name": "7.4.3",
"images": {
"hda_disk_image": "FAZ_VM64_KVM-v7.4.3-build2487-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.4.2",
"images": {
@ -270,6 +298,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.5",
"images": {
"hda_disk_image": "FAZ_VM64_KVM-v7.2.5-build1574-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.4",
"images": {
@ -291,6 +326,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.12",
"images": {
"hda_disk_image": "FAZ_VM64_KVM-v7.0.12-build0623-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.11",
"images": {

View File

@ -13,13 +13,13 @@
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "Default username is admin, no password is set. First book takes longer.",
"usage": "Default username is admin, no password is set. First boot takes longer.",
"symbol": "fortinet.svg",
"port_name_format": "Port{port1}",
"qemu": {
"adapter_type": "e1000",
"adapters": 4,
"ram": 1024,
"ram": 4096,
"hda_disk_interface": "virtio",
"hdb_disk_interface": "virtio",
"arch": "x86_64",
@ -28,6 +28,27 @@
"kvm": "allow"
},
"images": [
{
"filename": "FAC_VM_KVM-v6.6.1-build1660-FORTINET.out.kvm_fackvm.qcow2",
"version": "6.6.1",
"md5sum": "4b2b475ac8b6f88b5033dca367d53cbb",
"filesize": 138477584,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_fackvm.qcow2",
"version": "6.5.5",
"md5sum": "6850128ac51cee2577114ecd487786ff",
"filesize": 112918544,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6.4.9-build1067-FORTINET.out.kvm_fackvm.qcow2",
"version": "6.4.9",
"md5sum": "aee068a16fb2ca332d41e6add499b7d3",
"filesize": 112197648,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6-build0058-FORTINET.out.kvm.qcow2",
"version": "6.0.3",
@ -105,6 +126,20 @@
"filesize": 62771200,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6.6.1-build1660-FORTINET.out.kvm_datadrive.qcow2",
"version": "6.6.1",
"md5sum": "9bbaa1ce1508b4af1f43ba00879269f9",
"filesize": 197568,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_datadrive.qcow2",
"version": "6.4.x, 6.5.x",
"md5sum": "3f7173307047cf562f55ed2f99450c10",
"filesize": 197568,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-ALL-DATADRIVE.qcow2",
"version": "All",
@ -114,6 +149,27 @@
}
],
"versions": [
{
"name": "6.6.1",
"images": {
"hda_disk_image": "FAC_VM_KVM-v6.6.1-build1660-FORTINET.out.kvm_fackvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v6.6.1-build1660-FORTINET.out.kvm_datadrive.qcow2"
}
},
{
"name": "6.5.5",
"images": {
"hda_disk_image": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_fackvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_datadrive.qcow2"
}
},
{
"name": "6.4.9",
"images": {
"hda_disk_image": "FAC_VM_KVM-v6.4.9-build1067-FORTINET.out.kvm_fackvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v6.5.5-build1385-FORTINET.out.kvm_datadrive.qcow2"
}
},
{
"name": "6.0.3",
"images": {

View File

@ -28,6 +28,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FGT_VM64_KVM-v7.4.4.F-build2573-FORTINET.out.kvm.qcow2",
"version": "7.4.4",
"md5sum": "dfe0e78827ec728631539669001bb23f",
"filesize": 100728832,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.4.3.F-build2573-FORTINET.out.kvm.qcow2",
"version": "7.4.3",
@ -42,6 +49,13 @@
"filesize": 116064256,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.2.8.M-build1639-FORTINET.out.kvm_fortios.qcow2",
"version": "7.2.8",
"md5sum": "5c8fd4baf80aeb2999d4be5a9c49eb3d",
"filesize": 89980928,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.2.7.M-build1577-FORTINET.out.kvm.qcow2",
"version": "7.2.7",
@ -77,6 +91,13 @@
"filesize": 86704128,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.0.15.M-build0601-FORTINET.out.kvm.qcow2",
"version": "7.0.15",
"md5sum": "423f50378b7e93098ab765c3dd3a788f",
"filesize": 77398016,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v7.0.14.M-build0601-FORTINET.out.kvm.qcow2",
"version": "7.0.14",
@ -367,6 +388,13 @@
}
],
"versions": [
{
"name": "7.4.4",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v7.4.4.F-build2573-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.4.3",
"images": {
@ -381,6 +409,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.8",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v7.2.8.M-build1639-FORTINET.out.kvm_fortios.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.7",
"images": {
@ -416,6 +451,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.15",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v7.0.15.M-build0601-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.14",
"images": {

View File

@ -29,6 +29,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FMG_VM64_KVM-v7.4.3-build2487-FORTINET.out.kvm.qcow2",
"version": "7.4.23",
"md5sum": "b01d9f86aa27c538407d518df1326863",
"filesize": 346107904,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.4.2-build2397-FORTINET.out.kvm.qcow2",
"version": "7.4.2",
@ -43,6 +50,13 @@
"filesize": 309387264,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.2.5-build1574-FORTINET.out.kvm.qcow2",
"version": "7.2.5",
"md5sum": "754326845096afd909ec45d98f8d5a83",
"filesize": 278401024,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.2.4-build1460-FORTINET.out.kvm.qcow2",
"version": "7.2.4",
@ -64,6 +78,13 @@
"filesize": 242814976,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.0.12-build0623-FORTINET.out.kvm.qcow2",
"version": "7.0.12",
"md5sum": "5b6f6a2b8bc00e56337aa7023a9025cf",
"filesize": 249520128,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v7.0.11-build0595-FORTINET.out.kvm.qcow2",
"version": "7.0.11",
@ -256,6 +277,13 @@
}
],
"versions": [
{
"name": "7.4.3",
"images": {
"hda_disk_image": "FMG_VM64_KVM-v7.4.3-build2487-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.4.2",
"images": {
@ -270,6 +298,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.5",
"images": {
"hda_disk_image": "FMG_VM64_KVM-v7.2.5-build1574-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.4",
"images": {
@ -291,6 +326,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.12",
"images": {
"hda_disk_image": "FMG_VM64_KVM-v7.0.12-build0623-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.11",
"images": {

View File

@ -28,6 +28,27 @@
"kvm": "allow"
},
"images": [
{
"filename": "FWB_KVM-v7.6.0.F-build0962-FORTINET.out.kvm_boot.qcow2",
"version": "7.6.0",
"md5sum": "e94aa4af7ed0a12bd6084f0d74a2a96e",
"filesize": 329187840,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.4.3-build0638-FORTINET.out.kvm_boot.qcow2",
"version": "7.4.3",
"md5sum": "3c0ac11a6d80a319a4fe460aff5bc66c",
"filesize": 303497728,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.2.8-build0400-FORTINET.out.kvm_boot.qcow2",
"version": "7.2.8",
"md5sum": "367307242e6855dc190df089d196e712",
"filesize": 257950208,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.2.1-build0330-FORTINET.out.kvm.boot.qcow2",
"version": "7.2.1",
@ -35,6 +56,13 @@
"filesize": 260506112,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.0.10-build0166-FORTINET.out.kvm_boot.qcow2",
"version": "7.0.10",
"md5sum": "ff9d4b827c4e41c1b38e59359ba05487",
"filesize": 257556992,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v7.0.6-build0140-FORTINET.out.kvm.boot.qcow2",
"version": "7.0.6",
@ -150,6 +178,27 @@
}
],
"versions": [
{
"name": "7.6.0",
"images": {
"hda_disk_image": "FWB_KVM-v7.6.0.F-build0962-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.4.3",
"images": {
"hda_disk_image": "FWB_KVM-v7.4.3-build0638-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.8",
"images": {
"hda_disk_image": "FWB_KVM-v7.2.8-build0400-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.2.1",
"images": {
@ -157,6 +206,13 @@
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.10",
"images": {
"hda_disk_image": "FWB_KVM-v7.0.10-build0166-FORTINET.out.kvm_boot.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "7.0.6",
"images": {

View File

@ -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": [
{

View File

@ -34,7 +34,7 @@
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{

View File

@ -26,7 +26,7 @@
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -enable-kvm"
"options": "-nographic -enable-kvm -machine q35,smbios-entry-point-type=32"
},
"images": [
{

View File

@ -20,11 +20,12 @@
"adapter_type": "virtio-net-pci",
"adapters": 13,
"ram": 4096,
"cpus": 4,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -enable-kvm -smp cpus=3"
"options": "-nographic -enable-kvm -machine q35,smbios-entry-point-type=32"
},
"images": [
{

View File

@ -23,7 +23,7 @@
"arch": "x86_64",
"console_type": "vnc",
"kvm": "require",
"options": "-nographic"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{

View File

@ -19,11 +19,12 @@
"adapter_type": "virtio-net-pci",
"adapters": 12,
"ram": 1024,
"cpus": 2,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -smp 2"
"options": "-nographic -machine q35,smbios-entry-point-type=32"
},
"images": [
{

View File

@ -25,7 +25,7 @@
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-nographic -enable-kvm"
"options": "-nographic -enable-kvm -machine q35,smbios-entry-point-type=32"
},
"images": [
{

View File

@ -19,11 +19,12 @@
"adapter_type": "vmxnet3",
"adapters": 6,
"ram": 4096,
"cpus": 2,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require",
"options": "-smp 2"
"options": "-machine q35,smbios-entry-point-type=32"
},
"images": [
{

View File

@ -28,6 +28,20 @@
},
"images": [
{
"filename": "PA-VM-KVM-11.0.0.qcow2",
"version": "11.0.0",
"md5sum": "fc54b0e680ca2bcecb5522430e420f06",
"filesize": 4130865152,
"download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/"
},
{
"filename": "PA-VM-KVM-10.2.3.qcow2",
"version": "10.2.3",
"md5sum": "0e7b2a52d1447186d335ef9a1a197c6c",
"filesize": 5298585600,
"download_url": "https://support.paloaltonetworks.com/Updates/SoftwareUpdates/"
},
{
"filename": "PA-VM-KVM-10.1.0.qcow2",
"version": "10.1.0",
"md5sum": "8266fd412a22694749f2cd4afcd5fa33",
@ -128,6 +142,18 @@
],
"versions": [
{
"name": "11.0.0",
"images": {
"hda_disk_image": "PA-VM-KVM-11.0.0.qcow2"
}
},
{
"name": "10.2.3",
"images": {
"hda_disk_image": "PA-VM-KVM-10.2.3.qcow2"
}
},
{
"name": "10.1.0",
"images": {
"hda_disk_image": "PA-VM-KVM-10.1.0.qcow2"

View File

@ -13,18 +13,27 @@
"status": "stable",
"maintainer": "Brent Stewart",
"maintainer_email": "brent@stewart.tc",
"usage": "Your default account will have sudo priviledges. Squil and Squert username and password are configured in the Setup wizard. MySQL root is set to null. For more info see https://github.com/Security-Onion-Solutions/security-onion/wiki/Passwords.",
"usage": "Your default account will have sudo privileges. Squil and Squert username and password are configured in the Setup wizard. MySQL root is set to null. For more info see https://github.com/Security-Onion-Solutions/security-onion/wiki/Passwords.",
"symbol": "securityonion-logo.png",
"qemu": {
"adapter_type": "e1000",
"adapters": 2,
"ram": 3072,
"ram": 4096,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "vnc",
"kvm": "allow"
"kvm": "allow",
"options": "-cpu host"
},
"images": [
{
"filename": "securityonion-2.4.80-20240624.iso",
"version": "2.4.80-20240624",
"md5sum": "139f9762e926f9cb3c4a9528a3752c31",
"filesize": 12391022592,
"download_url": "https://github.com/Security-Onion-Solutions/securityonion/blob/2.4/main/DOWNLOAD_AND_VERIFY_ISO.md",
"direct_download_url": "https://download.securityonion.net/file/securityonion/securityonion-2.4.80-20240624.iso"
},
{
"filename": "securityonion-16.04.7.1.iso",
"version": "16.04.7.1",
@ -49,6 +58,14 @@
"download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/",
"direct_download_url": "https://github.com/Security-Onion-Solutions/security-onion/releases/download/v14.04.5.4_20171031/securityonion-14.04.5.4.iso"
},
{
"filename": "empty100G.qcow2",
"version": "1.0",
"md5sum": "5d9fec18a980f13002028491259f158d",
"filesize": 198656,
"download_url": "https://github.com/riverbed/Riverbed-Community-Toolkit/raw/master/SteelHead/GNS3",
"direct_download_url": "https://github.com/riverbed/Riverbed-Community-Toolkit/raw/master/SteelHead/GNS3/empty100G.qcow2"
},
{
"filename": "empty30G.qcow2",
"version": "1.0",
@ -59,6 +76,13 @@
}
],
"versions": [
{
"name": "2.4.80-20240624",
"images": {
"hda_disk_image": "empty100G.qcow2",
"cdrom_image": "securityonion-2.4.80-20240624.iso"
}
},
{
"name": "16.04.7.1",
"images": {

View File

@ -14,7 +14,7 @@
"symbol": "linux_guest.svg",
"docker": {
"adapters": 1,
"image": "gns3/ubuntu:focal",
"image": "gns3/ubuntu:noble",
"console_type": "telnet"
}
}

View File

@ -28,6 +28,7 @@ import shutil
import platformdirs
from gns3server.utils import parse_version
from gns3server.config import Config
from gns3server.utils.asyncio import locking
from gns3server.compute.base_manager import BaseManager
from gns3server.compute.docker.docker_vm import DockerVM
@ -95,8 +96,13 @@ class Docker(BaseManager):
Get the Docker resources storage directory
"""
appname = vendor = "GNS3"
docker_resources_dir = os.path.join(platformdirs.user_data_dir(appname, vendor, roaming=True), "docker", "resources")
resources_path = Config.instance().settings.Server.resources_path
if not resources_path:
appname = vendor = "GNS3"
resources_path = platformdirs.user_data_dir(appname, vendor, roaming=True)
else:
resources_path = os.path.expanduser(resources_path)
docker_resources_dir = os.path.join(resources_path, "docker")
os.makedirs(docker_resources_dir, exist_ok=True)
return docker_resources_dir

View File

@ -45,7 +45,7 @@ from ..nios.nio_tap import NIOTAP
from ..base_node import BaseNode
from ...utils.asyncio import monitor_process
from ...utils.images import md5sum
from ...utils import macaddress_to_int, int_to_macaddress
from ...utils import macaddress_to_int, int_to_macaddress, is_ipv6_enabled
from ...utils.hostname import is_rfc1123_hostname_valid
from gns3server.schemas.compute.qemu_nodes import Qemu, QemuPlatform
@ -54,6 +54,12 @@ import logging
log = logging.getLogger(__name__)
# forbidden additional options
FORBIDDEN_OPTIONS = {"-blockdev", "-drive", "-hda", "-hdb", "-hdc", "-hdd",
"-fsdev", "-virtfs", "-nic", "-netdev"}
FORBIDDEN_OPTIONS |= {"-" + opt for opt in FORBIDDEN_OPTIONS
if opt.startswith("-") and not opt.startswith("--")}
class QemuVM(BaseNode):
module_name = "qemu"
@ -1855,14 +1861,17 @@ class QemuVM(BaseNode):
if port:
console_host = self._manager.port_manager.console_host
if console_host == "0.0.0.0":
if socket.has_ipv6:
# to fix an issue with Qemu when IPv4 is not enabled
# see https://github.com/GNS3/gns3-gui/issues/2352
# FIXME: consider making this more global (not just for Qemu + SPICE)
console_host = "::"
else:
raise QemuError("IPv6 must be enabled in order to use the SPICE console")
return ["-spice", f"addr={console_host},port={port},disable-ticketing", "-vga", "qxl"]
try:
if is_ipv6_enabled():
# to fix an issue with Qemu when IPv4 is not enabled
# see https://github.com/GNS3/gns3-gui/issues/2352
# FIXME: consider making this more global (not just for Qemu + SPICE)
console_host = "::"
except OSError as e:
raise QemuError("Could not check if IPv6 is enabled: {}".format(e))
return ["-spice",
f"addr={console_host},port={port},disable-ticketing",
"-vga", "qxl"]
else:
return []
@ -2640,9 +2649,16 @@ class QemuVM(BaseNode):
command.extend(self._tpm_options())
if additional_options:
try:
command.extend(shlex.split(additional_options))
additional_opt_list = shlex.split(additional_options)
except ValueError as e:
raise QemuError(f"Invalid additional options: {additional_options} error {e}")
allow_unsafe_options = self.manager.config.settings.Qemu.allow_unsafe_options
if allow_unsafe_options is False:
for opt in additional_opt_list:
if opt in FORBIDDEN_OPTIONS:
raise QemuError("Forbidden additional option: {}".format(opt))
command.extend(additional_opt_list)
# avoiding mouse offset (see https://github.com/GNS3/gns3-server/issues/2335)
if self._console_type == "vnc":
command.extend(['-machine', 'usb=on', '-device', 'usb-tablet'])

View File

@ -34,7 +34,7 @@ enable_ssl = False
certfile = /home/gns3/.config/GNS3/ssl/server.cert
certkey = /home/gns3/.config/GNS3/ssl/server.key
; Path where devices images are stored
; Path where binary images are stored
images_path = /home/gns3/GNS3/images
; Additional paths to look for images
@ -43,15 +43,20 @@ additional_images_paths = /opt/images;/mnt/disk1/images
; Path where user projects are stored
projects_path = /home/gns3/GNS3/projects
; Path where user appliances are stored
; Path where custom user appliances are stored
appliances_path = /home/gns3/GNS3/appliances
; Path where custom device symbols are stored
; Path where custom user symbols are stored
symbols_path = /home/gns3/GNS3/symbols
; Path where custom configs are stored
configs_path = /home/gns3/GNS3/configs
; Path where files like built-in appliances and Docker resources are stored
; The default path is the local user data directory
; (Linux: "~/.local/share/GNS3", macOS: "~/Library/Application Support/GNS3", Windows: "%APPDATA%\GNS3")
; resources_path = /home/gns3/GNS3/resources
; Default symbol theme
; Currently available themes are "Classic", Affinity-square-blue", "Affinity-square-red"
; "Affinity-square-gray", "Affinity-circle-blue", "Affinity-circle-red" and "Affinity-circle-gray"
@ -102,6 +107,9 @@ default_nat_interface = vmnet10
; Enable the built-in templates
enable_builtin_templates = True
; Install built-in appliances
install_builtin_appliances = True
; check if hardware virtualization is used by other emulators (KVM, VMware or VirtualBox)
hardware_virtualization_check = True
@ -148,3 +156,5 @@ monitor_host = 127.0.0.1
enable_hardware_acceleration = True
; Require hardware acceleration in order to start VMs
require_hardware_acceleration = False
; Allow unsafe additional command line options
allow_unsafe_options = False

View File

@ -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
!
!
!

View File

@ -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

View File

@ -270,13 +270,18 @@ class Controller:
log.error(f"Cannot read IOU license file '{iourc_path}': {e}")
self._iou_license_settings["license_check"] = iou_config.license_check
previous_version = controller_vars.get("version")
log.info("Comparing controller version {} with config version {}".format(__version__, previous_version))
if not previous_version or \
parse_version(__version__.split("+")[0]) > parse_version(previous_version.split("+")[0]):
self._appliance_manager.install_builtin_appliances()
elif not os.listdir(self._appliance_manager.builtin_appliances_path()):
self._appliance_manager.install_builtin_appliances()
# install the built-in appliances if needed
if Config.instance().settings.Server.install_builtin_appliances:
previous_version = controller_vars.get("version")
log.info("Comparing controller version {} with config version {}".format(__version__, previous_version))
builtin_appliances_path = self._appliance_manager.builtin_appliances_path()
if not previous_version or \
parse_version(__version__.split("+")[0]) > parse_version(previous_version.split("+")[0]):
self._appliance_manager.install_builtin_appliances()
elif not os.listdir(builtin_appliances_path):
self._appliance_manager.install_builtin_appliances()
else:
log.info(f"Built-in appliances are installed in '{builtin_appliances_path}'")
self._appliance_manager.appliances_etag = controller_vars.get("appliances_etag")
self._appliance_manager.load_appliances()

View File

@ -100,8 +100,13 @@ class ApplianceManager:
Get the built-in appliance storage directory
"""
appname = vendor = "GNS3"
appliances_dir = os.path.join(platformdirs.user_data_dir(appname, vendor, roaming=True), "appliances")
resources_path = Config.instance().settings.Server.resources_path
if not resources_path:
appname = vendor = "GNS3"
resources_path = platformdirs.user_data_dir(appname, vendor, roaming=True)
else:
resources_path = os.path.expanduser(resources_path)
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)

View File

@ -39,7 +39,7 @@ async def export_project(
temporary_dir,
include_images=False,
include_snapshots=False,
keep_compute_id=False,
keep_compute_ids=False,
allow_all_nodes=False,
reset_mac_addresses=False,
):
@ -54,9 +54,9 @@ async def export_project(
:param temporary_dir: A temporary dir where to store intermediate data
:param include_images: save OS images to the zip file
:param include_snapshots: save snapshots to the zip file
:param keep_compute_id: If false replace all compute id by local (standard behavior for .gns3project to make it portable)
:param allow_all_nodes: Allow all nodes type to be include in the zip even if not portable
:param reset_mac_addresses: Reset MAC addresses for every nodes.
:param keep_compute_ids: If false replace all compute IDs by local (standard behavior for .gns3project to make it portable)
:param allow_all_nodes: Allow all nodes type to be included in the zip even if not portable
:param reset_mac_addresses: Reset MAC addresses for each node.
"""
# To avoid issue with data not saved we disallow the export of a running project
@ -77,7 +77,7 @@ async def export_project(
os.path.join(project._path, file),
zstream,
include_images,
keep_compute_id,
keep_compute_ids,
allow_all_nodes,
temporary_dir,
reset_mac_addresses,
@ -193,7 +193,7 @@ def _is_exportable(path, include_snapshots=False):
async def _patch_project_file(
project, path, zstream, include_images, keep_compute_id, allow_all_nodes, temporary_dir, reset_mac_addresses
project, path, zstream, include_images, keep_compute_ids, allow_all_nodes, temporary_dir, reset_mac_addresses
):
"""
Patch a project file (.gns3) to export a project.
@ -225,7 +225,7 @@ async def _patch_project_file(
if not allow_all_nodes and node["node_type"] in ["virtualbox", "vmware"]:
raise ControllerError("Projects with a {} node cannot be exported".format(node["node_type"]))
if not keep_compute_id:
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":
@ -243,13 +243,13 @@ async def _patch_project_file(
if value is None or value.strip() == "":
continue
if not keep_compute_id: # If we keep the original compute we can keep the image path
if not keep_compute_ids: # If we keep the original compute we can keep the image path
node["properties"][prop] = os.path.basename(value)
if include_images is True:
images.append({"compute_id": compute_id, "image": value, "image_type": node["node_type"]})
if not keep_compute_id:
if not keep_compute_ids:
topology["topology"][
"computes"
] = [] # Strip compute information because could contain secret info like password

View File

@ -40,7 +40,7 @@ Handle the import of project from a .gns3project
"""
async def import_project(controller, project_id, stream, location=None, name=None, keep_compute_id=False,
async def import_project(controller, project_id, stream, location=None, name=None, keep_compute_ids=False,
auto_start=False, auto_open=False, auto_close=True):
"""
Import a project contain in a zip file
@ -52,7 +52,7 @@ async def import_project(controller, project_id, stream, location=None, name=Non
:param stream: A io.BytesIO of the zipfile
:param location: Directory for the project if None put in the default directory
:param name: Wanted project name, generate one from the .gns3 if None
:param keep_compute_id: If true do not touch the compute id
:param keep_compute_ids: keep compute IDs unchanged
:returns: Project
"""
@ -126,7 +126,7 @@ async def import_project(controller, project_id, stream, location=None, name=Non
drawing["drawing_id"] = str(uuid.uuid4())
# Modify the compute id of the node depending of compute capacity
if not keep_compute_id:
if not keep_compute_ids:
# For some VM type we move them to the GNS3 VM if possible
# unless it's a linux host without GNS3 VM
if not sys.platform.startswith("linux") or controller.has_compute("vm"):

View File

@ -210,7 +210,11 @@ class Project:
if os.path.exists(snapshot_dir):
for snap in os.listdir(snapshot_dir):
if snap.endswith(".gns3project"):
snapshot = Snapshot(self, filename=snap)
try:
snapshot = Snapshot(self, filename=snap)
except ValueError:
log.error("Invalid snapshot file: {}".format(snap))
continue
self._snapshots[snapshot.id] = snapshot
# Create the project on demand on the compute node
@ -491,7 +495,7 @@ class Project:
if base_name is None:
return None
base_name = re.sub(r"[ ]", "", base_name)
base_name = re.sub(r"[ ]", "", base_name) # remove spaces in node name
if base_name in self._allocated_node_names:
base_name = re.sub(r"[0-9]+$", "{0}", base_name)
@ -1087,7 +1091,7 @@ class Project:
zstream,
self,
tmpdir,
keep_compute_id=True,
keep_compute_ids=True,
allow_all_nodes=True,
reset_mac_addresses=reset_mac_addresses,
)
@ -1106,7 +1110,7 @@ class Project:
str(uuid.uuid4()),
f,
name=name,
keep_compute_id=True
keep_compute_ids=True
)
log.info(f"Project '{project.name}' duplicated in {time.time() - begin:.4f} seconds")

View File

@ -59,14 +59,9 @@ class Snapshot:
+ ".gns3project"
)
else:
self._name = filename.split("_")[0]
self._name = filename.rsplit("_", 2)[0]
datestring = filename.replace(self._name + "_", "").split(".")[0]
try:
self._created_at = (
datetime.strptime(datestring, "%d%m%y_%H%M%S").replace(tzinfo=timezone.utc).timestamp()
)
except ValueError:
self._created_at = datetime.now(timezone.utc)
self._created_at = (datetime.strptime(datestring, "%d%m%y_%H%M%S").replace(tzinfo=timezone.utc).timestamp())
self._path = os.path.join(project.path, "snapshots", filename)
@property
@ -104,7 +99,7 @@ class Snapshot:
with tempfile.TemporaryDirectory(dir=snapshot_directory) as tmpdir:
# Do not compress the snapshots
with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream:
await export_project(zstream, self._project, tmpdir, keep_compute_id=True, allow_all_nodes=True)
await export_project(zstream, self._project, tmpdir, keep_compute_ids=True, allow_all_nodes=True)
async with aiofiles.open(self.path, "wb") as f:
async for chunk in zstream:
await f.write(chunk)

View File

@ -35,6 +35,7 @@ from .drawing import Drawing
from .node import Node
from .link import Link
from gns3server.utils.hostname import is_ios_hostname_valid, is_rfc1123_hostname_valid, to_rfc1123_hostname, to_ios_hostname
from gns3server.schemas.controller.topology import Topology
from gns3server.schemas.compute.dynamips_nodes import DynamipsCreate
@ -43,7 +44,7 @@ import logging
log = logging.getLogger(__name__)
GNS3_FILE_FORMAT_REVISION = 9
GNS3_FILE_FORMAT_REVISION = 10
class DynamipsNodeValidation(DynamipsCreate):
@ -186,6 +187,10 @@ def load_topology(path):
if variables:
topo["variables"] = [var for var in variables if var.get("name")]
# Version before GNS3 3.0
if topo["revision"] < 10:
topo = _convert_2_2_0(topo, path)
try:
_check_topology_schema(topo, path)
except ControllerError as e:
@ -201,6 +206,30 @@ def load_topology(path):
return topo
def _convert_2_2_0(topo, topo_path):
"""
Convert topologies from GNS3 2.2.x to 3.0
Changes:
* Convert Qemu and Docker node names to be a valid RFC1123 hostnames.
* Convert Dynamips and IOU node names to be a valid IOS hostnames.
"""
topo["revision"] = 10
for node in topo.get("topology", {}).get("nodes", []):
if "properties" in node:
if node["node_type"] in ("qemu", "docker") and not is_rfc1123_hostname_valid(node["name"]):
new_name = to_rfc1123_hostname(node["name"])
log.info(f"Convert node name {node['name']} to {new_name} (RFC1123)")
node["name"] = new_name
if node["node_type"] in ("dynamips", "iou") and not is_ios_hostname_valid(node["name"] ):
new_name = to_ios_hostname(node["name"])
log.info(f"Convert node name {node['name']} to {new_name} (IOS)")
node["name"] = new_name
return topo
def _convert_2_1_0(topo, topo_path):
"""
Convert topologies from GNS3 2.1.x to 2.2

View File

@ -58,7 +58,7 @@ class CrashReport:
Report crash to a third party service
"""
DSN = "https://99870c759d1c1d62ceb091d59dbcfa78@o19455.ingest.us.sentry.io/38482"
DSN = "https://1ae6f3c9d64e75bf8ad39295723da722@o19455.ingest.us.sentry.io/38482"
_instance = None
def __init__(self):

View File

@ -69,6 +69,7 @@ class QemuSettings(BaseModel):
monitor_host: str = "127.0.0.1"
enable_hardware_acceleration: bool = True
require_hardware_acceleration: bool = False
allow_unsafe_options: bool = False
model_config = ConfigDict(validate_assignment=True, str_strip_whitespace=True)
@ -126,6 +127,7 @@ class ServerSettings(BaseModel):
appliances_path: str = "~/GNS3/appliances"
symbols_path: str = "~/GNS3/symbols"
configs_path: str = "~/GNS3/configs"
resources_path: str = None
default_symbol_theme: BuiltinSymbolTheme = BuiltinSymbolTheme.affinity_square_blue
allow_raw_images: bool = True
auto_discover_images: bool = True
@ -144,6 +146,7 @@ class ServerSettings(BaseModel):
default_nat_interface: str = None
allow_remote_console: bool = False
enable_builtin_templates: bool = True
install_builtin_appliances: bool = True
model_config = ConfigDict(validate_assignment=True, str_strip_whitespace=True, use_enum_values=True)
@field_validator("additional_images_paths", mode="before")

View File

@ -36,7 +36,7 @@
<body class="mat-app-background" oncontextmenu="return false;">
<app-root></app-root>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-5D6FZL9923"></script>
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-0BT7QQV1W1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
@ -44,8 +44,8 @@
}
gtag('js', new Date());
gtag('config', 'G-5D6FZL9923');
gtag('config', 'G-0BT7QQV1W1');
</script>
<script src="runtime.24fa95b7061d7056.js" type="module"></script><script src="polyfills.319c79dd175e50d0.js" type="module"></script><script src="main.f3840f9b1c0240e6.js" type="module"></script>
<script src="runtime.24fa95b7061d7056.js" type="module"></script><script src="polyfills.319c79dd175e50d0.js" type="module"></script><script src="main.4185a8e61824af0d.js" type="module"></script>
</body></html>

View File

@ -21,6 +21,8 @@ import re
import shlex
import textwrap
import posixpath
import socket
import errno
def force_unix_path(path):
@ -89,3 +91,21 @@ def parse_version(version):
version.append("000000")
version.append("final")
return tuple(version)
def is_ipv6_enabled() -> bool:
if not socket.has_ipv6:
return False # the socket library has no support for IPv6
try:
with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as sock:
sock.bind(("::1", 0))
return True
except OSError as e:
if e.errno in (errno.EADDRNOTAVAIL, errno.EAFNOSUPPORT):
# EADDRNOTAVAIL is the errno if IPv6 modules/drivers are loaded but disabled.
# EAFNOSUPPORT is the errno if IPv6 modules/drivers are not loaded at all.
return False
if e.errno == errno.EADDRINUSE:
return True
raise

View File

@ -32,6 +32,28 @@ def is_ios_hostname_valid(hostname: str) -> bool:
return False
def to_ios_hostname(name):
"""
Convert name to an IOS hostname
"""
# Replace invalid characters with hyphens
name = re.sub(r'[^a-zA-Z0-9-]', '-', name)
# Ensure the hostname starts with a letter
if not re.search(r'^[a-zA-Z]', name):
name = 'a' + name
# Ensure the hostname ends with a letter or digit
if not re.search(r'[a-zA-Z0-9]$', name):
name = name.rstrip('-') + '0'
# Truncate the hostname to 63 characters
name = name[:63]
return name
def is_rfc1123_hostname_valid(hostname: str) -> bool:
"""
Check if a hostname is valid according to RFC 1123
@ -57,3 +79,34 @@ def is_rfc1123_hostname_valid(hostname: str) -> bool:
allowed = re.compile(r"(?!-)[a-zA-Z0-9-]{1,63}(?<!-)$")
return all(allowed.match(label) for label in labels)
def to_rfc1123_hostname(name: str) -> str:
"""
Convert name to RFC 1123 hostname
"""
# Replace invalid characters with hyphens
name = re.sub(r'[^a-zA-Z0-9-.]', '-', name)
# Remove trailing dot if it exists
name = name.rstrip('.')
# Ensure each label is not longer than 63 characters
labels = name.split('.')
labels = [label[:63] for label in labels]
# Remove leading and trailing hyphens from each label if they exist
labels = [label.strip('-') for label in labels]
# Check if the TLD is all-numeric and if so, replace it with "invalid"
if re.match(r"[0-9]+$", labels[-1]):
labels[-1] = 'invalid'
# Join the labels back together
name = '.'.join(labels)
# Ensure the total length is not longer than 253 characters
name = name[:253]
return name

View File

@ -22,7 +22,7 @@
# or negative for a release candidate or beta (after the base version
# number has been incremented)
__version__ = "3.0.0b3"
__version__ = "3.0.0rc1"
__version_info__ = (3, 0, 0, -99)
if "dev" in __version__:

View File

@ -1,23 +1,23 @@
uvicorn==0.29.0
fastapi==0.111.0
fastapi==0.112.0
python-multipart==0.0.9
websockets==12.0
aiohttp==3.9.3
aiohttp>=3.9.5,<3.10
async-timeout==4.0.3
aiofiles==23.2.1
aiofiles>=24.1.0,<25.0
Jinja2>=3.1.4,<3.2
sentry-sdk==2.1.1,<2.2
psutil==5.9.8
sentry-sdk==2.12,<2.13
psutil==6.0.0
distro>=1.9.0
py-cpuinfo==9.0.0
sqlalchemy==2.0.29
sqlalchemy==2.0.31
aiosqlite==0.20.0
alembic==1.12.1
bcrypt==4.1.2
bcrypt==4.2.0
python-jose[cryptography]==3.3.0
email-validator==2.1.1
watchfiles==0.21.0
zstandard==0.22.0
platformdirs==4.2.1
email-validator==2.2.0
watchfiles==0.22.0
zstandard==0.23.0
platformdirs==4.2.2
importlib-resources>=1.3; python_version <= '3.9'
truststore>=0.9.1; python_version >= '3.10'

View File

@ -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"

View File

@ -792,6 +792,14 @@ async def test_build_command_with_invalid_options(vm):
await vm._build_command()
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
async def test_build_command_with_forbidden_options(vm):
vm.options = "-blockdev"
with pytest.raises(QemuError):
await vm._build_command()
def test_hda_disk_image(vm, images_dir):
open(os.path.join(images_dir, "test1"), "w+").close()

View File

@ -334,7 +334,7 @@ async def test_export_with_images(tmpdir, project):
@pytest.mark.asyncio
async def test_export_keep_compute_id(tmpdir, project):
async def test_export_keep_compute_ids(tmpdir, project):
"""
If we want to restore the same computes we could ask to keep them
in the file
@ -363,7 +363,7 @@ async def test_export_keep_compute_id(tmpdir, project):
json.dump(data, f)
with aiozipstream.ZipFile() as z:
await export_project(z, project, str(tmpdir), keep_compute_id=True)
await export_project(z, project, str(tmpdir), keep_compute_ids=True)
await write_file(str(tmpdir / 'zipfile.zip'), z)
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
@ -469,7 +469,7 @@ async def test_export_with_ignoring_snapshots(tmpdir, project):
Path(os.path.join(snapshots_dir, 'snap.gns3project')).touch()
with aiozipstream.ZipFile() as z:
await export_project(z, project, str(tmpdir), keep_compute_id=True)
await export_project(z, project, str(tmpdir), keep_compute_ids=True)
await write_file(str(tmpdir / 'zipfile.zip'), z)
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:

View File

@ -462,7 +462,7 @@ async def test_import_node_id(linux_platform, tmpdir, controller):
@pytest.mark.asyncio
async def test_import_keep_compute_id(windows_platform, tmpdir, controller):
async def test_import_keep_compute_ids(windows_platform, tmpdir, controller):
"""
On linux host IOU should be moved to the GNS3 VM
"""
@ -500,7 +500,7 @@ async def test_import_keep_compute_id(windows_platform, tmpdir, controller):
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
with open(zip_path, "rb") as f:
project = await import_project(controller, project_id, f, keep_compute_id=True)
project = await import_project(controller, project_id, f, keep_compute_ids=True)
with open(os.path.join(project.path, "test.gns3")) as f:
topo = json.load(f)

View File

@ -786,7 +786,7 @@ def test_snapshots(project):
def test_get_snapshot(project):
os.makedirs(os.path.join(project.path, "snapshots"))
open(os.path.join(project.path, "snapshots", "test1.gns3project"), "w+").close()
open(os.path.join(project.path, "snapshots", "test1_260716_103713.gns3project"), "w+").close()
project.reset()
snapshot = list(project.snapshots.values())[0]

View File

@ -61,15 +61,21 @@ def test_snapshot_filename(project):
def test_json(project):
snapshot = Snapshot(project, filename="test1_260716_100439.gns3project")
snapshot = Snapshot(project, filename="snapshot_test_260716_100439.gns3project")
assert snapshot.asdict() == {
"snapshot_id": snapshot._id,
"name": "test1",
"name": "snapshot_test",
"project_id": project.id,
"created_at": 1469527479
}
def test_invalid_snapshot_filename(project):
with pytest.raises(ValueError):
Snapshot(project, filename="snapshot_test_invalid_file.gns3project")
@pytest.mark.asyncio
async def test_restore(project, controller, config):

View File

@ -23,11 +23,11 @@
"label": {
"rotation": 0,
"style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
"text": "remote_busybox-1",
"text": "remote-busybox-1",
"x": -20,
"y": -25
},
"name": "remote_busybox-1",
"name": "remote-busybox-1",
"node_id": "d397ef5a-84f1-4b6b-9d44-671937ec7781",
"node_type": "docker",
"port_name_format": "Ethernet{0}",

View File

@ -11,7 +11,7 @@
"label": {
"color": "#ff000000",
"font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
"text": "remote_busybox-1",
"text": "remote-busybox-1",
"x": -20.4453125,
"y": -25.0
},
@ -32,7 +32,7 @@
"console_resolution": "1024x768",
"console_type": "telnet",
"image": "busybox:latest",
"name": "remote_busybox-1"
"name": "remote-busybox-1"
},
"server_id": 2,
"type": "DockerVM",

View File

@ -0,0 +1,222 @@
{
"auto_close": true,
"auto_open": false,
"auto_start": false,
"drawing_grid_size": 25,
"grid_size": 75,
"name": "test-hostnames",
"project_id": "8b83e3ac-6b6a-4d6b-9938-bd630a6e458e",
"revision": 10,
"scene_height": 1000,
"scene_width": 2000,
"show_grid": false,
"show_interface_labels": false,
"show_layers": false,
"snap_to_grid": false,
"supplier": null,
"topology": {
"computes": [],
"drawings": [],
"links": [],
"nodes": [
{
"compute_id": "local",
"console": 5000,
"console_auto_start": false,
"console_type": "telnet",
"custom_adapters": [],
"first_port_name": null,
"height": 45,
"label": {
"rotation": 0,
"style": "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
"text": "42Router_A-1",
"x": -20,
"y": -25
},
"locked": false,
"name": "a42Router-A-1",
"node_id": "adb89fbb-92ba-419b-96ca-1ad0f03ce3f6",
"node_type": "dynamips",
"port_name_format": "Ethernet{0}",
"port_segment_size": 0,
"properties": {
"auto_delete_disks": false,
"aux": null,
"clock_divisor": 8,
"disk0": 0,
"disk1": 0,
"dynamips_id": 1,
"exec_area": 64,
"idlemax": 500,
"idlepc": "0x60aa1da0",
"idlesleep": 30,
"image": "c3745-adventerprisek9-mz.124-25d.image",
"image_md5sum": "ddbaf74274822b50fa9670e10c75b08f",
"iomem": 5,
"mac_addr": "c401.fff5.0000",
"mmap": true,
"nvram": 256,
"platform": "c3745",
"ram": 256,
"slot0": "GT96100-FE",
"slot1": "NM-1FE-TX",
"slot2": "NM-4T",
"slot3": null,
"slot4": null,
"sparsemem": true,
"system_id": "FTX0945W0MY",
"usage": "",
"wic0": "WIC-1T",
"wic1": "WIC-1T",
"wic2": "WIC-1T"
},
"symbol": ":/symbols/classic/router.svg",
"template_id": "24f09d1a-64e1-4dc4-ae49-e785c1dbc0c5",
"width": 66,
"x": -130,
"y": -64,
"z": 1
},
{
"compute_id": "local",
"console": 5001,
"console_auto_start": false,
"console_type": "telnet",
"custom_adapters": [
{
"adapter_number": 0,
"adapter_type": "e1000"
},
{
"adapter_number": 1,
"adapter_type": "e1000"
},
{
"adapter_number": 2,
"adapter_type": "e1000"
},
{
"adapter_number": 3,
"adapter_type": "e1000"
},
{
"adapter_number": 4,
"adapter_type": "e1000"
},
{
"adapter_number": 5,
"adapter_type": "e1000"
},
{
"adapter_number": 6,
"adapter_type": "e1000"
},
{
"adapter_number": 7,
"adapter_type": "e1000"
},
{
"adapter_number": 8,
"adapter_type": "e1000"
},
{
"adapter_number": 9,
"adapter_type": "e1000"
},
{
"adapter_number": 10,
"adapter_type": "e1000"
},
{
"adapter_number": 11,
"adapter_type": "e1000"
},
{
"adapter_number": 12,
"adapter_type": "e1000"
},
{
"adapter_number": 13,
"adapter_type": "e1000"
},
{
"adapter_number": 14,
"adapter_type": "e1000"
},
{
"adapter_number": 15,
"adapter_type": "e1000"
}
],
"first_port_name": "",
"height": 48,
"label": {
"rotation": 0,
"style": "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
"text": "Switch_10.0.0.1",
"x": -36,
"y": -25
},
"locked": false,
"name": "Switch-10.0.0.invalid",
"node_id": "ccda4e49-770f-4237-956b-cc7281630468",
"node_type": "qemu",
"port_name_format": "Gi0/{0}",
"port_segment_size": 4,
"properties": {
"adapter_type": "e1000",
"adapters": 16,
"bios_image": "",
"bios_image_md5sum": null,
"boot_priority": "c",
"cdrom_image": "",
"cdrom_image_md5sum": null,
"cpu_throttling": 0,
"cpus": 1,
"create_config_disk": false,
"hda_disk_image": "vios_l2-adventerprisek9-m.03.2017.qcow2",
"hda_disk_image_md5sum": "8f14b50083a14688dec2fc791706bb3e",
"hda_disk_interface": "virtio",
"hdb_disk_image": "",
"hdb_disk_image_md5sum": null,
"hdb_disk_interface": "none",
"hdc_disk_image": "",
"hdc_disk_image_md5sum": null,
"hdc_disk_interface": "none",
"hdd_disk_image": "",
"hdd_disk_image_md5sum": null,
"hdd_disk_interface": "none",
"initrd": "",
"initrd_md5sum": null,
"kernel_command_line": "",
"kernel_image": "",
"kernel_image_md5sum": null,
"legacy_networking": false,
"linked_clone": true,
"mac_address": "0c:da:4e:49:00:00",
"on_close": "power_off",
"options": "",
"platform": "x86_64",
"process_priority": "normal",
"qemu_path": "/bin/qemu-system-x86_64",
"ram": 768,
"replicate_network_connection_state": true,
"tpm": false,
"uefi": false,
"usage": "There is no default password and enable password. There is no default configuration present. SUPER UPDATED!"
},
"symbol": ":/symbols/classic/multilayer_switch.svg",
"template_id": "9db64790-65f4-4d38-a1ac-2f6ce45b70db",
"width": 51,
"x": -13,
"y": 54,
"z": 1
}
]
},
"type": "topology",
"variables": null,
"version": "2.2.49",
"zoom": 100
}

View File

@ -0,0 +1,222 @@
{
"auto_close": true,
"auto_open": false,
"auto_start": false,
"drawing_grid_size": 25,
"grid_size": 75,
"name": "test-hostnames",
"project_id": "8b83e3ac-6b6a-4d6b-9938-bd630a6e458e",
"revision": 9,
"scene_height": 1000,
"scene_width": 2000,
"show_grid": false,
"show_interface_labels": false,
"show_layers": false,
"snap_to_grid": false,
"supplier": null,
"topology": {
"computes": [],
"drawings": [],
"links": [],
"nodes": [
{
"compute_id": "local",
"console": 5000,
"console_auto_start": false,
"console_type": "telnet",
"custom_adapters": [],
"first_port_name": null,
"height": 45,
"label": {
"rotation": 0,
"style": "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
"text": "42Router_A-1",
"x": -20,
"y": -25
},
"locked": false,
"name": "42Router_A-1",
"node_id": "adb89fbb-92ba-419b-96ca-1ad0f03ce3f6",
"node_type": "dynamips",
"port_name_format": "Ethernet{0}",
"port_segment_size": 0,
"properties": {
"auto_delete_disks": false,
"aux": null,
"clock_divisor": 8,
"disk0": 0,
"disk1": 0,
"dynamips_id": 1,
"exec_area": 64,
"idlemax": 500,
"idlepc": "0x60aa1da0",
"idlesleep": 30,
"image": "c3745-adventerprisek9-mz.124-25d.image",
"image_md5sum": "ddbaf74274822b50fa9670e10c75b08f",
"iomem": 5,
"mac_addr": "c401.fff5.0000",
"mmap": true,
"nvram": 256,
"platform": "c3745",
"ram": 256,
"slot0": "GT96100-FE",
"slot1": "NM-1FE-TX",
"slot2": "NM-4T",
"slot3": null,
"slot4": null,
"sparsemem": true,
"system_id": "FTX0945W0MY",
"usage": "",
"wic0": "WIC-1T",
"wic1": "WIC-1T",
"wic2": "WIC-1T"
},
"symbol": ":/symbols/classic/router.svg",
"template_id": "24f09d1a-64e1-4dc4-ae49-e785c1dbc0c5",
"width": 66,
"x": -130,
"y": -64,
"z": 1
},
{
"compute_id": "local",
"console": 5001,
"console_auto_start": false,
"console_type": "telnet",
"custom_adapters": [
{
"adapter_number": 0,
"adapter_type": "e1000"
},
{
"adapter_number": 1,
"adapter_type": "e1000"
},
{
"adapter_number": 2,
"adapter_type": "e1000"
},
{
"adapter_number": 3,
"adapter_type": "e1000"
},
{
"adapter_number": 4,
"adapter_type": "e1000"
},
{
"adapter_number": 5,
"adapter_type": "e1000"
},
{
"adapter_number": 6,
"adapter_type": "e1000"
},
{
"adapter_number": 7,
"adapter_type": "e1000"
},
{
"adapter_number": 8,
"adapter_type": "e1000"
},
{
"adapter_number": 9,
"adapter_type": "e1000"
},
{
"adapter_number": 10,
"adapter_type": "e1000"
},
{
"adapter_number": 11,
"adapter_type": "e1000"
},
{
"adapter_number": 12,
"adapter_type": "e1000"
},
{
"adapter_number": 13,
"adapter_type": "e1000"
},
{
"adapter_number": 14,
"adapter_type": "e1000"
},
{
"adapter_number": 15,
"adapter_type": "e1000"
}
],
"first_port_name": "",
"height": 48,
"label": {
"rotation": 0,
"style": "font-family: TypeWriter;font-size: 10.0;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
"text": "Switch_10.0.0.1",
"x": -36,
"y": -25
},
"locked": false,
"name": "Switch_10.0.0.1",
"node_id": "ccda4e49-770f-4237-956b-cc7281630468",
"node_type": "qemu",
"port_name_format": "Gi0/{0}",
"port_segment_size": 4,
"properties": {
"adapter_type": "e1000",
"adapters": 16,
"bios_image": "",
"bios_image_md5sum": null,
"boot_priority": "c",
"cdrom_image": "",
"cdrom_image_md5sum": null,
"cpu_throttling": 0,
"cpus": 1,
"create_config_disk": false,
"hda_disk_image": "vios_l2-adventerprisek9-m.03.2017.qcow2",
"hda_disk_image_md5sum": "8f14b50083a14688dec2fc791706bb3e",
"hda_disk_interface": "virtio",
"hdb_disk_image": "",
"hdb_disk_image_md5sum": null,
"hdb_disk_interface": "none",
"hdc_disk_image": "",
"hdc_disk_image_md5sum": null,
"hdc_disk_interface": "none",
"hdd_disk_image": "",
"hdd_disk_image_md5sum": null,
"hdd_disk_interface": "none",
"initrd": "",
"initrd_md5sum": null,
"kernel_command_line": "",
"kernel_image": "",
"kernel_image_md5sum": null,
"legacy_networking": false,
"linked_clone": true,
"mac_address": "0c:da:4e:49:00:00",
"on_close": "power_off",
"options": "",
"platform": "x86_64",
"process_priority": "normal",
"qemu_path": "/bin/qemu-system-x86_64",
"ram": 768,
"replicate_network_connection_state": true,
"tpm": false,
"uefi": false,
"usage": "There is no default password and enable password. There is no default configuration present. SUPER UPDATED!"
},
"symbol": ":/symbols/classic/multilayer_switch.svg",
"template_id": "9db64790-65f4-4d38-a1ac-2f6ce45b70db",
"width": 51,
"x": -13,
"y": 54,
"z": 1
}
]
},
"type": "topology",
"variables": null,
"version": "2.2.49",
"zoom": 100
}

View File

@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from gns3server.utils import hostname
def test_ios_hostname_valid_with_valid_hostnames():
assert hostname.is_ios_hostname_valid("router1")
assert hostname.is_ios_hostname_valid("switch-2")
assert hostname.is_ios_hostname_valid("a1-b2-c3")
def test_ios_hostname_valid_with_invalid_hostnames():
assert not hostname.is_ios_hostname_valid("-router")
assert not hostname.is_ios_hostname_valid("router-")
assert not hostname.is_ios_hostname_valid("123router")
assert not hostname.is_ios_hostname_valid("router@123")
assert not hostname.is_ios_hostname_valid("router.router")
def test_ios_hostname_valid_with_long_hostnames():
assert hostname.is_ios_hostname_valid("a" * 63)
assert not hostname.is_ios_hostname_valid("a" * 64)
def test_ios_hostname_conversion_with_valid_characters():
assert hostname.to_ios_hostname("validHostname123") == "validHostname123"
def test_ios_hostname_conversion_starts_with_digit():
assert hostname.to_ios_hostname("1InvalidStart") == "a1InvalidStart"
def test_ios_hostname_conversion_starts_with_special_character():
assert hostname.to_ios_hostname("@InvalidStart") == "a-InvalidStart"
def test_ios_hostname_conversion_ends_with_special_character():
assert hostname.to_ios_hostname("InvalidEnd-") == "InvalidEnd0"
def test_ios_hostname_conversion_contains_special_characters():
assert hostname.to_ios_hostname("Invalid@Hostname!") == "Invalid-Hostname0"
def test_ios_hostname_conversion_exceeds_max_length():
long_name = "a" * 64
assert hostname.to_ios_hostname(long_name) == "a" * 63
def test_ios_hostname_conversion_just_right_length():
exact_length_name = "a" * 63
assert hostname.to_ios_hostname(exact_length_name) == "a" * 63
def test_rfc1123_hostname_validity_with_valid_hostnames():
assert hostname.is_rfc1123_hostname_valid("example.com")
assert hostname.is_rfc1123_hostname_valid("subdomain.example.com")
assert hostname.is_rfc1123_hostname_valid("example-hyphen.com")
assert hostname.is_rfc1123_hostname_valid("example.com.")
assert hostname.is_rfc1123_hostname_valid("123.com")
def test_rfc1123_hostname_validity_with_invalid_hostnames():
assert not hostname.is_rfc1123_hostname_valid("-example.com")
assert not hostname.is_rfc1123_hostname_valid("example-.com")
assert not hostname.is_rfc1123_hostname_valid("example..com")
assert not hostname.is_rfc1123_hostname_valid("example_com")
assert not hostname.is_rfc1123_hostname_valid("example.123")
def test_rfc1123_hostname_validity_with_long_hostnames():
long_hostname = "a" * 63 + "." + "b" * 63 + "." + "c" * 63 + "." + "d" * 61 # 253 characters
too_long_hostname = long_hostname + "e"
assert hostname.is_rfc1123_hostname_valid(long_hostname)
assert not hostname.is_rfc1123_hostname_valid(too_long_hostname)
def test_rfc1123_conversion_hostname_with_valid_characters():
assert hostname.to_rfc1123_hostname("valid-hostname.example.com") == "valid-hostname.example.com"
def test_rfc1123_conversion_hostname_with_invalid_characters_replaced():
assert hostname.to_rfc1123_hostname("invalid_hostname!@#$.example") == "invalid-hostname.example"
def test_rfc1123_conversion_hostname_with_trailing_dot_removed():
assert hostname.to_rfc1123_hostname("hostname.example.com.") == "hostname.example.com"
def test_rfc1123_conversion_hostname_with_labels_exceeding_63_characters():
long_label = "a" * 64 + ".example.com"
expected_label = "a" * 63 + ".example.com"
assert hostname.to_rfc1123_hostname(long_label) == expected_label
def test_rfc1123_conversion_hostname_with_total_length_exceeding_253_characters():
long_hostname = "a" * 50 + "." + "b" * 50 + "." + "c" * 50 + "." + "d" * 50 + "." + "e" * 50
assert len(hostname.to_rfc1123_hostname(long_hostname)) <= 253
def test_rfc1123_conversion_hostname_with_all_numeric_tld_replaced():
assert hostname.to_rfc1123_hostname("hostname.123") == "hostname.invalid"
def rfc1123_hostname_with_multiple_consecutive_invalid_characters():
assert hostname.to_rfc1123_hostname("hostname!!!.example..com") == "hostname---.example.com"