diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml
index 6ecb10d0..10fb15d8 100644
--- a/.github/workflows/testing.yml
+++ b/.github/workflows/testing.yml
@@ -13,12 +13,11 @@ on:
jobs:
build:
- runs-on: ${{ matrix.os }}
+ runs-on: ubuntu-latest
strategy:
matrix:
- os: [ubuntu-latest]
- python-version: [3.6, 3.7, 3.8, 3.9]
+ python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v2
diff --git a/CHANGELOG b/CHANGELOG
index c6e1d886..32c64f3f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,33 @@
# Change Log
+## 2.2.26 08/10/2021
+
+* Release web UI 2.2.26
+* Sort symbols by theme. Fixes https://github.com/GNS3/gns3-gui/issues/3230
+* Fix memory percentage left warning. Fixes #1966
+* Update affinity symbols. Fixes https://github.com/GNS3/gns3-gui/issues/3232
+
+## 2.2.25 14/09/2021
+
+* Release web UI 2.2.25
+* Fix issue preventing to use custom nested symbols. Fixes #1969
+* Updated affinity symbols
+* Fix qemu-img rebase code to support Qemu 6.1. Ref https://github.com/GNS3/gns3-server/pull/1962
+* Reinstate qemu-img rebase
+* Return disk usage for partition that contains the default project directory. Fixes #1947
+* Explicitly require setuptools, utils/get_resource.py imports pkg_resources
+
+## 2.2.24 25/08/2021
+
+* Release web UI 2.2.24
+* Fix issue when searching for image with relative path. Fixes #1925
+* Fix wrong error when NAT interface is not allowed. Fixes #1943
+* Fix incorrect Qemu binary selected when importing template. Fixes https://github.com/GNS3/gns3-gui/issues/3216
+* Fix error when updating a link style. Fixes https://github.com/GNS3/gns3-gui/issues/2461
+* Some fixes for early support for Python3.10 The loop parameter has been removed from most of asyncio‘s high-level API following deprecation in Python 3.8.
+* Early support for Python3.10 Fixes #1940
+* Bump pywin32 from 300 to 301
+
## 2.2.23 05/08/2021
* Release web UI 2.2.23
diff --git a/Dockerfile b/Dockerfile
index 3ff8b9d3..d6df9536 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -14,9 +14,8 @@ RUN set -eux \
&& apk add --no-cache --virtual .build-deps build-base \
gcc libc-dev musl-dev linux-headers python3-dev \
vpcs qemu libvirt ubridge \
- && pip install --upgrade pip setuptools wheel \
- && pip install -r /gns3server/requirements.txt \
- && rm -rf /root/.cache/pip
+ && pip install --no-cache-dir --upgrade pip setuptools wheel \
+ && pip install --no-cache-dir -r /gns3server/requirements.txt
COPY . /gns3server
RUN python3 setup.py install
diff --git a/README.rst b/README.rst
index 3c70ede9..37d5523e 100644
--- a/README.rst
+++ b/README.rst
@@ -32,6 +32,11 @@ In addition of Python dependencies listed in a section below, other software may
* mtools is recommended to support data transfer to/from QEMU VMs using virtual disks.
* i386-libraries of libc and libcrypto are optional (Linux only), they are only needed to run IOU based nodes.
+Docker support
+**************
+
+Docker support needs the script program (`bsdutils` or `util-linux` package), when running a docker VM and a static busybox during installation (python3 setup.py install / pip3 install / package creation).
+
Branches
--------
diff --git a/conf/gns3_server.conf b/conf/gns3_server.conf
index 8560d59d..a5864c5a 100644
--- a/conf/gns3_server.conf
+++ b/conf/gns3_server.conf
@@ -68,7 +68,7 @@ password = gns3
; It cannot be changed once the server has started once
default_admin_username = "admin"
-; Initial default super admin username
+; Initial default super admin password
; It cannot be changed once the server has started once
default_admin_password = "admin"
diff --git a/gns3server/api/routes/compute/qemu_nodes.py b/gns3server/api/routes/compute/qemu_nodes.py
index 66ce046a..d60625d5 100644
--- a/gns3server/api/routes/compute/qemu_nodes.py
+++ b/gns3server/api/routes/compute/qemu_nodes.py
@@ -139,13 +139,6 @@ async def start_qemu_node(node: QemuVM = Depends(dep_node)) -> Response:
Start a Qemu node.
"""
- qemu_manager = Qemu.instance()
- hardware_accel = qemu_manager.config.settings.Qemu.enable_hardware_acceleration
- if hardware_accel and "-machine accel=tcg" not in node.options:
- pm = ProjectManager.instance()
- if pm.check_hardware_virtualization(node) is False:
- pass # FIXME: check this
- # raise ComputeError("Cannot start VM with hardware acceleration (KVM/HAX) enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox")
await node.start()
return Response(status_code=status.HTTP_204_NO_CONTENT)
diff --git a/gns3server/api/routes/controller/__init__.py b/gns3server/api/routes/controller/__init__.py
index 71e0cc02..7f6cdcdd 100644
--- a/gns3server/api/routes/controller/__init__.py
+++ b/gns3server/api/routes/controller/__init__.py
@@ -28,6 +28,7 @@ from . import projects
from . import snapshots
from . import symbols
from . import templates
+from . import images
from . import users
from . import groups
from . import roles
@@ -61,9 +62,17 @@ router.include_router(
tags=["Permissions"]
)
+router.include_router(
+ images.router,
+ dependencies=[Depends(get_current_active_user)],
+ prefix="/images",
+ tags=["Images"]
+)
+
router.include_router(
templates.router,
dependencies=[Depends(get_current_active_user)],
+ prefix="/templates",
tags=["Templates"]
)
diff --git a/gns3server/api/routes/controller/appliances.py b/gns3server/api/routes/controller/appliances.py
index 89dbe281..550473e1 100644
--- a/gns3server/api/routes/controller/appliances.py
+++ b/gns3server/api/routes/controller/appliances.py
@@ -18,22 +18,106 @@
API routes for appliances.
"""
-from fastapi import APIRouter
+import logging
+
+from fastapi import APIRouter, Depends, Response, status
from typing import Optional, List
+from uuid import UUID
+
+from gns3server import schemas
+from gns3server.controller import Controller
+from gns3server.controller.controller_error import (
+ ControllerError,
+ ControllerBadRequestError,
+ ControllerNotFoundError
+)
+
+from gns3server.db.repositories.images import ImagesRepository
+from gns3server.db.repositories.templates import TemplatesRepository
+from gns3server.db.repositories.rbac import RbacRepository
+
+from .dependencies.authentication import get_current_active_user
+from .dependencies.database import get_repository
+
+log = logging.getLogger(__name__)
router = APIRouter()
@router.get("")
-async def get_appliances(update: Optional[bool] = False, symbol_theme: Optional[str] = "Classic") -> List[dict]:
+async def get_appliances(
+ update: Optional[bool] = False,
+ symbol_theme: Optional[str] = "Classic"
+) -> List[schemas.Appliance]:
"""
Return all appliances known by the controller.
"""
- from gns3server.controller import Controller
-
controller = Controller.instance()
if update:
await controller.appliance_manager.download_appliances()
controller.appliance_manager.load_appliances(symbol_theme=symbol_theme)
return [c.asdict() for c in controller.appliance_manager.appliances.values()]
+
+
+@router.get("/{appliance_id}")
+def get_appliance(appliance_id: UUID) -> schemas.Appliance:
+ """
+ Get an appliance file.
+ """
+
+ controller = Controller.instance()
+ appliance = controller.appliance_manager.appliances.get(str(appliance_id))
+ if not appliance:
+ raise ControllerNotFoundError(message=f"Could not find appliance '{appliance_id}'")
+ return appliance.asdict()
+
+
+@router.post("/{appliance_id}/version", status_code=status.HTTP_201_CREATED)
+def add_appliance_version(appliance_id: UUID, appliance_version: schemas.ApplianceVersion) -> schemas.Appliance:
+ """
+ Add a version to an appliance
+ """
+
+ controller = Controller.instance()
+ appliance = controller.appliance_manager.appliances.get(str(appliance_id))
+ if not appliance:
+ raise ControllerNotFoundError(message=f"Could not find appliance '{appliance_id}'")
+
+ if not appliance.versions:
+ raise ControllerBadRequestError(message=f"Appliance '{appliance_id}' do not have versions")
+
+ if not appliance_version.images:
+ raise ControllerBadRequestError(message=f"Version '{appliance_version.name}' must contain images")
+
+ for version in appliance.versions:
+ if version.get("name") == appliance_version.name:
+ raise ControllerError(message=f"Appliance '{appliance_id}' already has version '{appliance_version.name}'")
+
+ appliance.versions.append(appliance_version.dict(exclude_unset=True))
+ return appliance.asdict()
+
+
+@router.post("/{appliance_id}/install", status_code=status.HTTP_204_NO_CONTENT)
+async def install_appliance(
+ appliance_id: UUID,
+ version: Optional[str] = None,
+ images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
+ templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
+ current_user: schemas.User = Depends(get_current_active_user),
+ rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
+) -> Response:
+ """
+ Install an appliance.
+ """
+
+ controller = Controller.instance()
+ await controller.appliance_manager.install_appliance(
+ appliance_id,
+ version,
+ images_repo,
+ templates_repo,
+ rbac_repo,
+ current_user
+ )
+ return Response(status_code=status.HTTP_204_NO_CONTENT)
diff --git a/gns3server/api/routes/controller/groups.py b/gns3server/api/routes/controller/groups.py
index b9ac05c4..c29a6fc1 100644
--- a/gns3server/api/routes/controller/groups.py
+++ b/gns3server/api/routes/controller/groups.py
@@ -25,6 +25,7 @@ from typing import List
from gns3server import schemas
from gns3server.controller.controller_error import (
+ ControllerError,
ControllerBadRequestError,
ControllerNotFoundError,
ControllerForbiddenError,
@@ -126,7 +127,7 @@ async def delete_user_group(
success = await users_repo.delete_user_group(user_group_id)
if not success:
- raise ControllerNotFoundError(f"User group '{user_group_id}' could not be deleted")
+ raise ControllerError(f"User group '{user_group_id}' could not be deleted")
return Response(status_code=status.HTTP_204_NO_CONTENT)
diff --git a/gns3server/api/routes/controller/images.py b/gns3server/api/routes/controller/images.py
new file mode 100644
index 00000000..d8d8e193
--- /dev/null
+++ b/gns3server/api/routes/controller/images.py
@@ -0,0 +1,169 @@
+#
+# Copyright (C) 2021 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 .
+
+"""
+API routes for images.
+"""
+
+import os
+import logging
+import urllib.parse
+
+from fastapi import APIRouter, Request, Response, Depends, status
+from sqlalchemy.orm.exc import MultipleResultsFound
+from typing import List, Optional
+from gns3server import schemas
+
+from gns3server.utils.images import InvalidImageError, default_images_directory, write_image
+from gns3server.db.repositories.images import ImagesRepository
+from gns3server.db.repositories.templates import TemplatesRepository
+from gns3server.db.repositories.rbac import RbacRepository
+from gns3server.controller import Controller
+from gns3server.controller.controller_error import (
+ ControllerError,
+ ControllerNotFoundError,
+ ControllerForbiddenError,
+ ControllerBadRequestError
+)
+
+from .dependencies.authentication import get_current_active_user
+from .dependencies.database import get_repository
+
+log = logging.getLogger(__name__)
+
+router = APIRouter()
+
+
+@router.get("", response_model=List[schemas.Image])
+async def get_images(
+ images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
+) -> List[schemas.Image]:
+ """
+ Return all images.
+ """
+
+ return await images_repo.get_images()
+
+
+@router.post("/upload/{image_path:path}", response_model=schemas.Image, status_code=status.HTTP_201_CREATED)
+async def upload_image(
+ image_path: str,
+ request: Request,
+ image_type: schemas.ImageType = schemas.ImageType.qemu,
+ images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
+ templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
+ current_user: schemas.User = Depends(get_current_active_user),
+ rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)),
+ install_appliances: Optional[bool] = True
+) -> schemas.Image:
+ """
+ Upload an image.
+
+ Example: curl -X POST http://host:port/v3/images/upload/my_image_name.qcow2?image_type=qemu \
+ -H 'Authorization: Bearer ' --data-binary @"/path/to/image.qcow2"
+ """
+
+ image_path = urllib.parse.unquote(image_path)
+ image_dir, image_name = os.path.split(image_path)
+ directory = default_images_directory(image_type)
+ full_path = os.path.abspath(os.path.join(directory, image_dir, image_name))
+ if os.path.commonprefix([directory, full_path]) != directory:
+ raise ControllerForbiddenError(f"Cannot write image, '{image_path}' is forbidden")
+
+ if await images_repo.get_image(image_path):
+ raise ControllerBadRequestError(f"Image '{image_path}' already exists")
+
+ try:
+ image = await write_image(image_name, image_type, full_path, request.stream(), images_repo)
+ except (OSError, InvalidImageError) as e:
+ raise ControllerError(f"Could not save {image_type} image '{image_path}': {e}")
+
+ if install_appliances:
+ # attempt to automatically create templates based on image checksum
+ await Controller.instance().appliance_manager.install_appliances_from_image(
+ image_path,
+ image.checksum,
+ images_repo,
+ templates_repo,
+ rbac_repo,
+ current_user,
+ directory
+ )
+
+ return image
+
+
+@router.get("/{image_path:path}", response_model=schemas.Image)
+async def get_image(
+ image_path: str,
+ images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
+) -> schemas.Image:
+ """
+ Return an image.
+ """
+
+ image_path = urllib.parse.unquote(image_path)
+ image = await images_repo.get_image(image_path)
+ if not image:
+ raise ControllerNotFoundError(f"Image '{image_path}' not found")
+ return image
+
+
+@router.delete("/{image_path:path}", status_code=status.HTTP_204_NO_CONTENT)
+async def delete_image(
+ image_path: str,
+ images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
+) -> None:
+ """
+ Delete an image.
+ """
+
+ image_path = urllib.parse.unquote(image_path)
+
+ try:
+ image = await images_repo.get_image(image_path)
+ except MultipleResultsFound:
+ raise ControllerBadRequestError(f"Image '{image_path}' matches multiple images. "
+ f"Please include the relative path of the image")
+
+ if not image:
+ raise ControllerNotFoundError(f"Image '{image_path}' not found")
+
+ templates = await images_repo.get_image_templates(image.image_id)
+ if templates:
+ template_names = ", ".join([template.name for template in templates])
+ raise ControllerError(f"Image '{image_path}' is used by one or more templates: {template_names}")
+
+ try:
+ os.remove(image.path)
+ except OSError:
+ log.warning(f"Could not delete image file {image.path}")
+
+ success = await images_repo.delete_image(image_path)
+ if not success:
+ raise ControllerError(f"Image '{image_path}' could not be deleted")
+
+
+@router.post("/prune", status_code=status.HTTP_204_NO_CONTENT)
+async def prune_images(
+ images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
+) -> Response:
+ """
+ Prune images not attached to any template.
+ """
+
+ await images_repo.prune_images()
+ return Response(status_code=status.HTTP_204_NO_CONTENT)
diff --git a/gns3server/api/routes/controller/nodes.py b/gns3server/api/routes/controller/nodes.py
index c175d583..0f28eb73 100644
--- a/gns3server/api/routes/controller/nodes.py
+++ b/gns3server/api/routes/controller/nodes.py
@@ -260,6 +260,28 @@ async def reload_node(node: Node = Depends(dep_node)) -> Response:
return Response(status_code=status.HTTP_204_NO_CONTENT)
+@router.post("/{node_id}/isolate", status_code=status.HTTP_204_NO_CONTENT)
+async def isolate_node(node: Node = Depends(dep_node)) -> Response:
+ """
+ Isolate a node (suspend all attached links).
+ """
+
+ for link in node.links:
+ await link.update_suspend(True)
+ return Response(status_code=status.HTTP_204_NO_CONTENT)
+
+
+@router.post("/{node_id}/unisolate", status_code=status.HTTP_204_NO_CONTENT)
+async def unisolate_node(node: Node = Depends(dep_node)) -> Response:
+ """
+ Un-isolate a node (resume all attached suspended links).
+ """
+
+ for link in node.links:
+ await link.update_suspend(False)
+ return Response(status_code=status.HTTP_204_NO_CONTENT)
+
+
@router.get("/{node_id}/links", response_model=List[schemas.Link], response_model_exclude_unset=True)
async def get_node_links(node: Node = Depends(dep_node)) -> List[schemas.Link]:
"""
diff --git a/gns3server/api/routes/controller/permissions.py b/gns3server/api/routes/controller/permissions.py
index 8667903c..504f2c59 100644
--- a/gns3server/api/routes/controller/permissions.py
+++ b/gns3server/api/routes/controller/permissions.py
@@ -36,6 +36,7 @@ from gns3server.controller.controller_error import (
from gns3server.db.repositories.rbac import RbacRepository
from .dependencies.database import get_repository
+from .dependencies.authentication import get_current_active_user
import logging
@@ -59,6 +60,7 @@ async def get_permissions(
async def create_permission(
request: Request,
permission_create: schemas.PermissionCreate,
+ current_user: schemas.User = Depends(get_current_active_user),
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> schemas.Permission:
"""
@@ -82,11 +84,16 @@ async def create_permission(
# the permission can match multiple routes
if permission_create.path.endswith("/*"):
- route_path += r"/\*"
+ route_path += r"/.*"
if re.fullmatch(route_path, permission_create.path):
for method in permission_create.methods:
if method in list(route.methods):
+ # check user has the right to add the permission (i.e has already to right on the path)
+ if not await rbac_repo.check_user_is_authorized(current_user.user_id, method, permission_create.path):
+ raise ControllerForbiddenError(f"User '{current_user.username}' doesn't have the rights to "
+ f"add a permission on {method} {permission_create.path} or "
+ f"the endpoint doesn't exist")
return await rbac_repo.create_permission(permission_create)
raise ControllerBadRequestError(f"Permission '{permission_create.methods} {permission_create.path}' "
diff --git a/gns3server/api/routes/controller/roles.py b/gns3server/api/routes/controller/roles.py
index 8da951d6..f0ed7f1f 100644
--- a/gns3server/api/routes/controller/roles.py
+++ b/gns3server/api/routes/controller/roles.py
@@ -25,6 +25,7 @@ from typing import List
from gns3server import schemas
from gns3server.controller.controller_error import (
+ ControllerError,
ControllerBadRequestError,
ControllerNotFoundError,
ControllerForbiddenError,
@@ -119,7 +120,7 @@ async def delete_role(
success = await rbac_repo.delete_role(role_id)
if not success:
- raise ControllerNotFoundError(f"Role '{role_id}' could not be deleted")
+ raise ControllerError(f"Role '{role_id}' could not be deleted")
return Response(status_code=status.HTTP_204_NO_CONTENT)
diff --git a/gns3server/api/routes/controller/templates.py b/gns3server/api/routes/controller/templates.py
index 4f1914b5..c5982212 100644
--- a/gns3server/api/routes/controller/templates.py
+++ b/gns3server/api/routes/controller/templates.py
@@ -25,14 +25,15 @@ import logging
log = logging.getLogger(__name__)
-from fastapi import APIRouter, Request, Response, HTTPException, Depends, Response, status
-from typing import List
+from fastapi import APIRouter, Request, HTTPException, Depends, Response, status
+from typing import List, Optional
from uuid import UUID
from gns3server import schemas
from gns3server.db.repositories.templates import TemplatesRepository
from gns3server.services.templates import TemplatesService
from gns3server.db.repositories.rbac import RbacRepository
+from gns3server.db.repositories.images import ImagesRepository
from .dependencies.authentication import get_current_active_user
from .dependencies.database import get_repository
@@ -42,7 +43,7 @@ responses = {404: {"model": schemas.ErrorMessage, "description": "Could not find
router = APIRouter(responses=responses)
-@router.post("/templates", response_model=schemas.Template, status_code=status.HTTP_201_CREATED)
+@router.post("", response_model=schemas.Template, status_code=status.HTTP_201_CREATED)
async def create_template(
template_create: schemas.TemplateCreate,
templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
@@ -59,7 +60,7 @@ async def create_template(
return template
-@router.get("/templates/{template_id}", response_model=schemas.Template, response_model_exclude_unset=True)
+@router.get("/{template_id}", response_model=schemas.Template, response_model_exclude_unset=True)
async def get_template(
template_id: UUID,
request: Request,
@@ -81,7 +82,7 @@ async def get_template(
return template
-@router.put("/templates/{template_id}", response_model=schemas.Template, response_model_exclude_unset=True)
+@router.put("/{template_id}", response_model=schemas.Template, response_model_exclude_unset=True)
async def update_template(
template_id: UUID,
template_update: schemas.TemplateUpdate,
@@ -94,13 +95,12 @@ async def update_template(
return await TemplatesService(templates_repo).update_template(template_id, template_update)
-@router.delete(
- "/templates/{template_id}",
- status_code=status.HTTP_204_NO_CONTENT,
-)
+@router.delete("/{template_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_template(
template_id: UUID,
+ prune_images: Optional[bool] = False,
templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
+ images_repo: RbacRepository = Depends(get_repository(ImagesRepository)),
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository))
) -> Response:
"""
@@ -109,10 +109,12 @@ async def delete_template(
await TemplatesService(templates_repo).delete_template(template_id)
await rbac_repo.delete_all_permissions_with_path(f"/templates/{template_id}")
+ if prune_images:
+ await images_repo.prune_images()
return Response(status_code=status.HTTP_204_NO_CONTENT)
-@router.get("/templates", response_model=List[schemas.Template], response_model_exclude_unset=True)
+@router.get("", response_model=List[schemas.Template], response_model_exclude_unset=True)
async def get_templates(
templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
current_user: schemas.User = Depends(get_current_active_user),
@@ -139,7 +141,7 @@ async def get_templates(
return user_templates
-@router.post("/templates/{template_id}/duplicate", response_model=schemas.Template, status_code=status.HTTP_201_CREATED)
+@router.post("/{template_id}/duplicate", response_model=schemas.Template, status_code=status.HTTP_201_CREATED)
async def duplicate_template(
template_id: UUID, templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository)),
current_user: schemas.User = Depends(get_current_active_user),
diff --git a/gns3server/api/routes/controller/users.py b/gns3server/api/routes/controller/users.py
index 1bff6bfe..76b704f7 100644
--- a/gns3server/api/routes/controller/users.py
+++ b/gns3server/api/routes/controller/users.py
@@ -26,6 +26,7 @@ from typing import List
from gns3server import schemas
from gns3server.controller.controller_error import (
+ ControllerError,
ControllerBadRequestError,
ControllerNotFoundError,
ControllerForbiddenError,
@@ -74,7 +75,7 @@ async def authenticate(
) -> schemas.Token:
"""
Alternative authentication method using json.
- Example: curl http://host:port/v3/users/authenticate -d '{"username": "admin", "password": "admin"}'
+ Example: curl http://host:port/v3/users/authenticate -d '{"username": "admin", "password": "admin"} -H "Content-Type: application/json" '
"""
user = await users_repo.authenticate_user(username=user_credentials.username, password=user_credentials.password)
@@ -207,7 +208,7 @@ async def delete_user(
success = await users_repo.delete_user(user_id)
if not success:
- raise ControllerNotFoundError(f"User '{user_id}' could not be deleted")
+ raise ControllerError(f"User '{user_id}' could not be deleted")
return Response(status_code=status.HTTP_204_NO_CONTENT)
diff --git a/gns3server/appliances/6wind-turbo-router.gns3a b/gns3server/appliances/6wind-turbo-router.gns3a
index 56c4062b..0b089d4b 100644
--- a/gns3server/appliances/6wind-turbo-router.gns3a
+++ b/gns3server/appliances/6wind-turbo-router.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "bf0a4dd0-9e1f-491e-918a-1d1ac0e23161",
"name": "6WIND Turbo Router",
"category": "router",
"description": "6WIND Turbo Router is a high performance, ready-to-use software virtual router. It can be deployed bare metal or in virtual machines on commercial-off-the-shelf (COTS) servers. It is a carrier-grade solution for Service Prodivers aiming at using white boxes to deploy network functions. Typical use-cases are transit/peering router, IPsec VPN gateway and CGNAT.",
diff --git a/gns3server/appliances/IPCop.gns3a b/gns3server/appliances/IPCop.gns3a
index 2fdb1ef3..98476d38 100644
--- a/gns3server/appliances/IPCop.gns3a
+++ b/gns3server/appliances/IPCop.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "c30ea423-b6f8-443e-b599-955ea5647ef0",
"name": "IP Cop",
"category": "firewall",
"description": "The IPCop Firewall is a Linux firewall distribution. It is geared towards home and SOHO users. The IPCop web-interface is very user-friendly and makes usage easy.",
diff --git a/gns3server/appliances/Simulator.gns3a b/gns3server/appliances/Simulator.gns3a
index f2347c80..f59e33b7 100644
--- a/gns3server/appliances/Simulator.gns3a
+++ b/gns3server/appliances/Simulator.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "2def5797-cb7d-429e-b85e-497ff4b81547",
"name": "ParrotOS",
"category": "guest",
"description": " Parrot is a GNU/Linux distribution based on Debian Testing and designed with Security, Development and Privacy in mind. It includes a full portable laboratory for security and digital forensics experts, but it also includes all you need to develop your own software or protect your privacy while surfing the net.",
diff --git a/gns3server/appliances/a10-vthunder.gns3a b/gns3server/appliances/a10-vthunder.gns3a
index e36c2749..ec9ec434 100644
--- a/gns3server/appliances/a10-vthunder.gns3a
+++ b/gns3server/appliances/a10-vthunder.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "7aa41b5b-3ae9-40a7-be38-5c109c59e086",
"name": "A10 vThunder",
"category": "router",
"description": "vThunder, part of A10 Networks' award-winning A10 Thunder and AX Series Application Delivery Controller (ADC) family, is designed to meet the growing needs of organizations that require a flexible and easy-to-deploy application delivery and server load balancer solution running within a virtualized infrastructure.",
diff --git a/gns3server/appliances/aaa.gns3a b/gns3server/appliances/aaa.gns3a
index 4334d9af..7bb024ad 100644
--- a/gns3server/appliances/aaa.gns3a
+++ b/gns3server/appliances/aaa.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "99920801-829d-4689-8231-7183c21ff878",
"name": "AAA",
"category": "guest",
"description": "This appliance provides RADIUS and TACACS+ services with preconfigured users and groups.",
diff --git a/gns3server/appliances/alcatel-7750.gns3a b/gns3server/appliances/alcatel-7750.gns3a
index 1e2dc85b..872006d8 100644
--- a/gns3server/appliances/alcatel-7750.gns3a
+++ b/gns3server/appliances/alcatel-7750.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "4d06be08-ce6d-4ee7-b5a7-79729fa75489",
"name": "Alcatel 7750",
"category": "router",
"description": "The Alcatel-Lucent 7750 Service Router (SR) portfolio is a suite of multiservice edge routing platforms that deliver high performance, service richness, and creates exceptional value for networking in the cloud era. It is designed for the concurrent delivery of advanced residential, business and wireless broadband IP services, and provides cloud, data center and branch office connectivity for enterprise networking on a common IP edge routing platform.",
diff --git a/gns3server/appliances/alpine-linux.gns3a b/gns3server/appliances/alpine-linux.gns3a
index 0f870177..590e740b 100644
--- a/gns3server/appliances/alpine-linux.gns3a
+++ b/gns3server/appliances/alpine-linux.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "fc520ae2-a4e5-48c3-9a13-516bb2e94668",
"name": "Alpine Linux",
"category": "guest",
"description": "Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox.",
diff --git a/gns3server/appliances/arista-ceos.gns3a b/gns3server/appliances/arista-ceos.gns3a
index 84790a41..2fbd791a 100644
--- a/gns3server/appliances/arista-ceos.gns3a
+++ b/gns3server/appliances/arista-ceos.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a7eec173-9680-4c1f-bf79-1bf29d485375",
"name": "cEOS",
"category": "multilayer_switch",
"description": "Arista cEOS\u2122 introduces the containerized packaging of EOS software and its agents for deployment in cloud infrastructure with the same proven EOS software image that runs on all Arista products. These flexible deployment options empower cloud network operators that are customizing their operating environments to provide a uniform workflow for development, testing and deployment of differentiated services.",
diff --git a/gns3server/appliances/arista-veos.gns3a b/gns3server/appliances/arista-veos.gns3a
index 7d49517e..5d75152c 100644
--- a/gns3server/appliances/arista-veos.gns3a
+++ b/gns3server/appliances/arista-veos.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "c90f3ff3-4ed2-4437-9afb-21232fa92015",
"name": "Arista vEOS",
"category": "multilayer_switch",
"description": "Arista EOS\u00ae is the core of Arista cloud networking solutions for next-generation data centers and cloud networks. Cloud architectures built with Arista EOS scale to tens of thousands of compute and storage nodes with management and provisioning capabilities that work at scale. Through its programmability, EOS enables a set of software applications that deliver workflow automation, high availability, unprecedented network visibility and analytics and rapid integration with a wide range of third-party applications for virtualization, management, automation and orchestration services.\n\nArista Extensible Operating System (EOS) is a fully programmable and highly modular, Linux-based network operation system, using familiar industry standard CLI and runs a single binary software image across the Arista switching family. Architected for resiliency and programmability, EOS has a unique multi-process state sharing architecture that separates state information and packet forwarding from protocol processing and application logic.",
@@ -26,6 +27,13 @@
"kvm": "require"
},
"images": [
+ {
+ "filename": "vEOS-lab-4.26.2F.vmdk",
+ "version": "4.26.2F",
+ "md5sum": "de8ce9750fddb63bd3f71bccfcd7651e",
+ "filesize": 475332608,
+ "download_url": "https://www.arista.com/en/support/software-download"
+ },
{
"filename": "vEOS-lab-4.25.3M.vmdk",
"version": "4.25.3M",
@@ -210,6 +218,13 @@
}
],
"versions": [
+ {
+ "name": "4.26.2F",
+ "images": {
+ "hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
+ "hdb_disk_image": "vEOS-lab-4.26.2F.vmdk"
+ }
+ },
{
"name": "4.25.3M",
"images": {
diff --git a/gns3server/appliances/aruba-arubaoscx.gns3a b/gns3server/appliances/aruba-arubaoscx.gns3a
index 16094598..bd84c1c8 100644
--- a/gns3server/appliances/aruba-arubaoscx.gns3a
+++ b/gns3server/appliances/aruba-arubaoscx.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "8f074218-9d61-4e99-ab89-35ca19ad44ee",
"name": "ArubaOS-CX Simulation Software",
"category": "multilayer_switch",
"description": "The ArubaOS-CX Simulation Software is a virtual platform to enable simulation of the ArubaOS-CX Network Operating System. Simulated networks can be created using many of the protocols in the ArubaOS-CX Operating system like OSPF, BGP (inc. EVPN). Key features like the Aruba Network Analytics Engine and the REST API can be simulated, providing a lightweight development platform to building the modern network.",
diff --git a/gns3server/appliances/aruba-vgw.gns3a b/gns3server/appliances/aruba-vgw.gns3a
index 17a709ed..6592a204 100644
--- a/gns3server/appliances/aruba-vgw.gns3a
+++ b/gns3server/appliances/aruba-vgw.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "38c9e478-4a1d-4611-ac61-945d2f2ca376",
"name": "Aruba VGW",
"category": "firewall",
"description": "Aruba Virtual Gateways allow customers to bring their public cloud infrastructure to the SD-WAN fabric and facilitate connectivity between branches and the public cloud.",
diff --git a/gns3server/appliances/aruba-vmc.gns3a b/gns3server/appliances/aruba-vmc.gns3a
index 35052627..52ba75d4 100644
--- a/gns3server/appliances/aruba-vmc.gns3a
+++ b/gns3server/appliances/aruba-vmc.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a51fbf46-6350-4db2-8dbc-e90704ed60ef",
"name": "Aruba VMC",
"category": "guest",
"description": "Aruba Virtual Mobility Controller",
diff --git a/gns3server/appliances/asterisk.gns3a b/gns3server/appliances/asterisk.gns3a
index 8e080360..e89cec7b 100644
--- a/gns3server/appliances/asterisk.gns3a
+++ b/gns3server/appliances/asterisk.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "b6319fe9-19d5-4a4d-a857-6eee3c92ca2d",
"name": "AsteriskNOW / FreePBX",
"category": "guest",
"description": "AsteriskNOW makes it easy to create custom telephony solutions by automatically installing the 'plumbing'. It's a complete Linux distribution with Asterisk, the DAHDI driver framework, and, the FreePBX administrative GUI. Much of the complexity of Asterisk and Linux is handled by the installer, the yum package management utility and the administrative GUI. With AsteriskNOW, application developers and integrators can concentrate on building solutions, not maintaining the plumbing.",
diff --git a/gns3server/appliances/bigswitch-bigcloud-fabric.gns3a b/gns3server/appliances/bigswitch-bigcloud-fabric.gns3a
index 8da0e867..96d907b4 100644
--- a/gns3server/appliances/bigswitch-bigcloud-fabric.gns3a
+++ b/gns3server/appliances/bigswitch-bigcloud-fabric.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "8885febc-9067-4c2b-94e9-67090df0c21e",
"name": "Big Cloud Fabric",
"category": "router",
"description": "Big Cloud Fabric\u2122 is the industry's first data center fabric built using whitebox or britebox switches and SDN controller technology. Embracing hyperscale data center design principles, Big Cloud Fabric solution enables rapid innovation, ease of provisioning and management, while reducing overall costs, making it ideal for current and next generation data centers. Big Cloud Fabric is designed from the ground up to satisfy the requirements of physical, virtual, containerized, or a combination of such workloads. Some of the typical OpenStack or VMware data center workloads include NFV, High Performance Computing, Big Data and Software Defined Storage deployments.",
diff --git a/gns3server/appliances/bird.gns3a b/gns3server/appliances/bird.gns3a
index c2a92202..688f072e 100644
--- a/gns3server/appliances/bird.gns3a
+++ b/gns3server/appliances/bird.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "088df570-f637-46f5-8a68-85acde538e5e",
"name": "BIRD",
"category": "router",
"description": "The BIRD project aims to develop a fully functional dynamic IP routing daemon primarily targeted on (but not limited to) Linux, FreeBSD and other UNIX-like systems and distributed under the GNU General Public License.",
diff --git a/gns3server/appliances/brocade-vadx.gns3a b/gns3server/appliances/brocade-vadx.gns3a
index 865c3959..dc8c85ae 100644
--- a/gns3server/appliances/brocade-vadx.gns3a
+++ b/gns3server/appliances/brocade-vadx.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "5952eca3-fc06-4a57-a3b0-986237cb7de7",
"name": "Brocade Virtual ADX",
"category": "firewall",
"description": "The Brocade Virtual ADX (vADX\u2122) is a full-fledged Application Delivery Controller (ADC) platform with a virtual footprint that leverages Intel advanced technology to deliver remarkable performance. The software is designed to run on standardsbased hypervisors, hosted on Intel x86 COTS hardware. It offers a complete suite of Layer 4 and Layer 7 server load balancing capabilities and application security services with extensible management via rich SOAP/XML APIs.",
diff --git a/gns3server/appliances/brocade-vrouter.gns3a b/gns3server/appliances/brocade-vrouter.gns3a
index f7fe1ce3..98c33d53 100644
--- a/gns3server/appliances/brocade-vrouter.gns3a
+++ b/gns3server/appliances/brocade-vrouter.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "52a04aee-1046-4214-a364-18ecd776f7b3",
"name": "vRouter",
"category": "router",
"description": "With proven ultra-high performance and scalability, the Brocade vRouter is the networking industry leader in software innovation. The Brocade vRouter has set a the benchmark for all software-based routers, while offering easy scalability, a broad set of capabilities, and the peace of mind that comes with rock solid reliability.",
diff --git a/gns3server/appliances/brocade-vtm.gns3a b/gns3server/appliances/brocade-vtm.gns3a
index f502b44d..08510a06 100644
--- a/gns3server/appliances/brocade-vtm.gns3a
+++ b/gns3server/appliances/brocade-vtm.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "cabd6cb2-1c70-4f90-b225-6601fea89cfc",
"name": "vTM DE",
"category": "router",
"description": "Take control of your online applications with Brocade virtual Traffic Manager (Developer Edition). Enhance customer experience, inspect traffic in real-time, control service levels to differentiate users and services, and reduce your costs with an extensible delivery platform that can grow with your business using ADC-as-a-Service. A fully functional Developer Edition which needs no license key, is limited to 1 Mbps/100 SSL tps throughput, and has access to the Brocade Community support web pages.",
diff --git a/gns3server/appliances/bsdrp.gns3a b/gns3server/appliances/bsdrp.gns3a
index f5735424..eadbaf67 100644
--- a/gns3server/appliances/bsdrp.gns3a
+++ b/gns3server/appliances/bsdrp.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "f28432b3-c5fe-48fa-b9e8-4024aa7cbe9e",
"name": "BSDRP",
"category": "router",
"description": "BSD Router Project (BSDRP) is an embedded free and open source router distribution based on FreeBSD with Quagga and Bird.",
diff --git a/gns3server/appliances/centos-cloud.gns3a b/gns3server/appliances/centos-cloud.gns3a
index daaf0d37..de73f614 100644
--- a/gns3server/appliances/centos-cloud.gns3a
+++ b/gns3server/appliances/centos-cloud.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "f8186e9a-5145-4da0-ac18-b5b13cf57d3b",
"name": "CentOS Cloud Guest",
"category": "guest",
"description": "CentOS official image for self-hosted cloud",
diff --git a/gns3server/appliances/centos7.gns3a b/gns3server/appliances/centos7.gns3a
index 1fbec7c8..44b6fdbf 100644
--- a/gns3server/appliances/centos7.gns3a
+++ b/gns3server/appliances/centos7.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "b1e84913-1c9b-49f5-bf2e-45f2b42ba404",
"name": "Centos",
"category": "guest",
"description": "The CentOS Linux distribution is a stable, predictable, manageable and reproducible platform derived from the sources of Red Hat Enterprise Linux (RHEL). We are now looking to expand on that by creating the resources needed by other communities to come together and be able to build on the CentOS Linux platform. And today we start the process by delivering a clear governance model, increased transparency and access. In the coming weeks we aim to publish our own roadmap that includes variants of the core CentOS Linux.",
diff --git a/gns3server/appliances/checkpoint-gaia.gns3a b/gns3server/appliances/checkpoint-gaia.gns3a
index fb90ea3a..bd4a4033 100644
--- a/gns3server/appliances/checkpoint-gaia.gns3a
+++ b/gns3server/appliances/checkpoint-gaia.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "7bfa7a66-b1fa-4e5e-9b85-95d74440ee31",
"name": "Checkpoint GAiA",
"category": "firewall",
"description": "Check Point Gaia is the next generation Secure Operating System for all Check Point Appliances, Open Servers and Virtualized Gateways.\n\nGaia combines the best features from IPSO and SecurePlatform (SPLAT) into a single unified OS providing greater efficiency and robust performance. By upgrading to Gaia, customers will benefit from improved appliance connection capacity and reduced operating costs. With Gaia, IP Appliance customers will gain the ability to leverage the full breadth and power of all Check Point Software Blades.\n\nGaia secures IPv6 networks utilizing the Check Point Acceleration & Clustering technology and it protects the most dynamic network and virtualized environments by supporting 5 different dynamic routing protocols. As a 64-Bit OS, Gaia increases the connection capacity of existing appliances supporting up-to 10M concurrent connections for select 2012 Models.\n\nGaia simplifies management with segregation of duties by enabling role-based administrative access. Furthermore, Gaia greatly increases operation efficiency by offering Automatic Software Update.\n\nThe feature-rich Web interface allows for search of any command or property in a second.\n\nGaia provides backward compatibility with IPSO and SPLAT CLI-style commands making it an easy transition for existing Check Point customers.",
diff --git a/gns3server/appliances/chromium.gns3a b/gns3server/appliances/chromium.gns3a
index 655b69db..e109c79a 100644
--- a/gns3server/appliances/chromium.gns3a
+++ b/gns3server/appliances/chromium.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "c95b160b-4515-4cc9-81cc-92ac063dd250",
"name": "Chromium",
"category": "guest",
"description": "The chromium browser",
diff --git a/gns3server/appliances/cisco-1700.gns3a b/gns3server/appliances/cisco-1700.gns3a
index 2d6a52fe..c136b7c4 100644
--- a/gns3server/appliances/cisco-1700.gns3a
+++ b/gns3server/appliances/cisco-1700.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "cc2b1802-3520-4963-8ff7-c19b1f6418c5",
"name": "Cisco 1700",
"category": "router",
"description": "Cisco 1700 Router",
diff --git a/gns3server/appliances/cisco-2600.gns3a b/gns3server/appliances/cisco-2600.gns3a
index 51bc2287..817e8584 100644
--- a/gns3server/appliances/cisco-2600.gns3a
+++ b/gns3server/appliances/cisco-2600.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "ed474fea-cd3b-4e2e-be84-a855a133060a",
"name": "Cisco 2600",
"category": "router",
"description": "Cisco 2600 Router",
diff --git a/gns3server/appliances/cisco-2691.gns3a b/gns3server/appliances/cisco-2691.gns3a
index e678c81e..cc6123bf 100644
--- a/gns3server/appliances/cisco-2691.gns3a
+++ b/gns3server/appliances/cisco-2691.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "ed0f079e-a506-4cb4-b46c-714a80bbe2d3",
"name": "Cisco 2691",
"category": "router",
"description": "Cisco 2691 Router",
diff --git a/gns3server/appliances/cisco-3620.gns3a b/gns3server/appliances/cisco-3620.gns3a
index 4294c98a..97477e61 100644
--- a/gns3server/appliances/cisco-3620.gns3a
+++ b/gns3server/appliances/cisco-3620.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "7ada6336-7280-4306-9f32-6b1e242ae989",
"name": "Cisco 3620",
"category": "router",
"description": "Cisco 3620 Router",
diff --git a/gns3server/appliances/cisco-3640.gns3a b/gns3server/appliances/cisco-3640.gns3a
index b767d909..71b3f90b 100644
--- a/gns3server/appliances/cisco-3640.gns3a
+++ b/gns3server/appliances/cisco-3640.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "ef119e49-19fe-4239-9c6b-16ea12f6ec01",
"name": "Cisco 3640",
"category": "router",
"description": "Cisco 3640 Router",
diff --git a/gns3server/appliances/cisco-3660.gns3a b/gns3server/appliances/cisco-3660.gns3a
index 5a636df4..57f2c551 100644
--- a/gns3server/appliances/cisco-3660.gns3a
+++ b/gns3server/appliances/cisco-3660.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "ac460a9c-9274-4ccf-a056-af50b699925f",
"name": "Cisco 3660",
"category": "router",
"description": "Cisco 3660 Router",
diff --git a/gns3server/appliances/cisco-3725.gns3a b/gns3server/appliances/cisco-3725.gns3a
index 93c85330..2e258082 100644
--- a/gns3server/appliances/cisco-3725.gns3a
+++ b/gns3server/appliances/cisco-3725.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "5b9c5293-a5a7-47a3-9df4-6cf658f2f378",
"name": "Cisco 3725",
"category": "router",
"description": "Cisco 3725 Router",
diff --git a/gns3server/appliances/cisco-3745.gns3a b/gns3server/appliances/cisco-3745.gns3a
index 9a683493..f48765a0 100644
--- a/gns3server/appliances/cisco-3745.gns3a
+++ b/gns3server/appliances/cisco-3745.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "18737edb-e43f-4fb0-8a0f-88982cff58b1",
"name": "Cisco 3745",
"category": "router",
"description": "Cisco 3745 Multiservice Access Router",
diff --git a/gns3server/appliances/cisco-7200.gns3a b/gns3server/appliances/cisco-7200.gns3a
index d3db50e1..59371e21 100644
--- a/gns3server/appliances/cisco-7200.gns3a
+++ b/gns3server/appliances/cisco-7200.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "38aa3135-f169-4131-9b64-73605787b5ef",
"name": "Cisco 7200",
"category": "router",
"description": "Cisco 7200 Router",
diff --git a/gns3server/appliances/cisco-asa.gns3a b/gns3server/appliances/cisco-asa.gns3a
index 69afb053..1227a674 100644
--- a/gns3server/appliances/cisco-asa.gns3a
+++ b/gns3server/appliances/cisco-asa.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "fdbfc23e-413f-4b9f-b930-6cd27527d72b",
"name": "Cisco ASA",
"category": "firewall",
"description": "Cisco ASA firewall",
diff --git a/gns3server/appliances/cisco-asav.gns3a b/gns3server/appliances/cisco-asav.gns3a
index ca8e47b9..ccc0e57e 100644
--- a/gns3server/appliances/cisco-asav.gns3a
+++ b/gns3server/appliances/cisco-asav.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "886c4059-4a10-4c62-ab59-7f02beeac292",
"name": "Cisco ASAv",
"category": "firewall",
"description": "The Adaptive Security Virtual Appliance is a virtualized network security solution based on the market-leading Cisco ASA 5500-X Series firewalls. It supports both traditional and next-generation software-defined network (SDN) and Cisco Application Centric Infrastructure (ACI) environments to provide policy enforcement and threat inspection across heterogeneous multisite environments.",
diff --git a/gns3server/appliances/cisco-c8000v.gns3a b/gns3server/appliances/cisco-c8000v.gns3a
index d10c4a58..6c1828da 100644
--- a/gns3server/appliances/cisco-c8000v.gns3a
+++ b/gns3server/appliances/cisco-c8000v.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "d223e573-8de5-4f93-b26d-d5d1f2f18226",
"name": "Cisco Catalyst 8000V",
"category": "router",
"description": "The Cisco Catalyst 8000V Edge Software is a virtual, form-factor router deployed on a virtual machine (VM) running on an x86 server hardware.",
diff --git a/gns3server/appliances/cisco-csr1000v.gns3a b/gns3server/appliances/cisco-csr1000v.gns3a
index 07df2292..0d062d3c 100644
--- a/gns3server/appliances/cisco-csr1000v.gns3a
+++ b/gns3server/appliances/cisco-csr1000v.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "95d17663-f40a-437f-b5f1-dab4779965de",
"name": "Cisco CSR1000v",
"category": "router",
"description": "The Cisco Cloud Services Router 1000V (CSR 1000V) is a router and network services platform in virtual form factor that is intended for deployment in cloud and virtual data centers. It is optimized to serve as a single-tenant or multitenant WAN gateway. Using proven, industry-leading Cisco IOS\u00ae XE Software networking and security features, the CSR 1000V enables enterprises to transparently extend their WANs into external provider-hosted clouds and cloud providers to offer their tenants enterprise-class networking services.",
diff --git a/gns3server/appliances/cisco-dcnm.gns3a b/gns3server/appliances/cisco-dcnm.gns3a
index 3fba6a32..4942faa7 100644
--- a/gns3server/appliances/cisco-dcnm.gns3a
+++ b/gns3server/appliances/cisco-dcnm.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "ae09653b-c8eb-4ecd-9341-2d0319e16b9b",
"name": "Cisco DCNM",
"category": "guest",
"description": "Cisco Data Center Network Manager (DCNM) 10 unifies and automates Cisco Nexus and Cisco MDS 9000 Family multitenant infrastructure for data center management across Cisco Nexus 5000, 6000, 7000, and 9000 Series Switches in NX-OS mode using Cisco NX-OS Software as well as across Cisco MDS 9100 and 9300 Series Multilayer Fabric Switches, 9200 Series Multiservice Switches, and 9500 and 9700 Series Multilayer Directors. Data Center Network Manager 10 lets you manage very large numbers of devices while providing ready-to-use management and automation capabilities plus Virtual Extensible LAN (VXLAN) overlay visibility into Cisco Nexus LAN fabrics.",
diff --git a/gns3server/appliances/cisco-fcnf.gns3a b/gns3server/appliances/cisco-fcnf.gns3a
index 83e5ae0b..269f0d28 100644
--- a/gns3server/appliances/cisco-fcnf.gns3a
+++ b/gns3server/appliances/cisco-fcnf.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "e36183b5-5960-4bcf-bdb9-ca258c28b3e5",
"name": "Cisco Flow Collector for NetFlow",
"category": "firewall",
"description": "Cisco Stealthwatch is the most comprehensive visibility and network traffic security analytics solution that uses enterprise telemetry from the existing network infrastructure. It provides advanced threat detection, accelerated threat response, and simplified network segmentation using multilayer machine learning and entity modeling. With advanced behavioral analytics, you'll always know who is on your network and what they are doing.\n\nAt the heart of the Stealthwatch System is the highly scalable Stealthwatch Flow Collector. The Flow Collector is available as either a physical or a virtual appliance. The Flow Collector VE performs the same functions as its physical counterpart, but in a virtual environment. The Stealthwatch Flow Collector for NetFlow gathers NetFlow, cFlow, J-Flow, Packeteer 2, NetStream, and IPFIX data. To achieve full network visibility with a traditional probe-based approach, you would need to install a probe for each router or switch on your network. This results in many costly hardware installations. Conversely, Stealthwatch's flow-based approach provides you with full network visibility at a fraction of the cost. Each Flow Collector can process data for as many as 1,000,000 hosts from up to 2,000 flow exporters, depending on the Flow Collector model and license restrictions. ",
diff --git a/gns3server/appliances/cisco-fmcv.gns3a b/gns3server/appliances/cisco-fmcv.gns3a
index 87a86c96..1fe7269d 100644
--- a/gns3server/appliances/cisco-fmcv.gns3a
+++ b/gns3server/appliances/cisco-fmcv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "1e409568-f8d6-4f94-8804-53039eb7784a",
"name": "Cisco FMCv",
"category": "firewall",
"description": "This is your administrative nerve center for managing critical Cisco network security solutions. It provides complete and unified management over firewalls, application control, intrusion prevention, URL filtering, and advanced malware protection. Easily go from managing a firewall to controlling applications to investigating and remediating malware outbreaks.",
diff --git a/gns3server/appliances/cisco-fsve.gns3a b/gns3server/appliances/cisco-fsve.gns3a
index d5ce9c91..9f9871d5 100644
--- a/gns3server/appliances/cisco-fsve.gns3a
+++ b/gns3server/appliances/cisco-fsve.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "709c2a9b-5dc3-4362-b147-fb848a0df963",
"name": "Cisco Flow Sensor",
"category": "firewall",
"description": "Cisco Stealthwatch is the most comprehensive visibility and network traffic security analytics solution that uses enterprise telemetry from the existing network infrastructure. It provides advanced threat detection, accelerated threat response, and simplified network segmentation using multilayer machine learning and entity modeling. With advanced behavioral analytics, you'll always know who is on your network and what they are doing.\n\nUsing the same technology as the Stealthwatch Flow Sensor appliance, the Flow Sensor VE is a virtual appliance that provides visibility into virtual environments, generating flow data for areas that are not flow-enabled. ",
diff --git a/gns3server/appliances/cisco-ftdv.gns3a b/gns3server/appliances/cisco-ftdv.gns3a
index 41e65f34..4c7f7390 100644
--- a/gns3server/appliances/cisco-ftdv.gns3a
+++ b/gns3server/appliances/cisco-ftdv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "adce6f0c-10ae-4f4d-9e00-da833f419eae",
"name": "Cisco FTDv",
"category": "firewall",
"description": "Cisco Firepower Threat Defense Virtual NGFW appliances combine Cisco's proven network firewall with the industry's most effective next-gen IPS and advanced malware protection. All so you can get more visibility, be more flexible, save more, and protect better.",
diff --git a/gns3server/appliances/cisco-iosv.gns3a b/gns3server/appliances/cisco-iosv.gns3a
index 89832630..c6d6bce6 100644
--- a/gns3server/appliances/cisco-iosv.gns3a
+++ b/gns3server/appliances/cisco-iosv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "3bf492b6-5717-4257-9bfd-b34617c6f133",
"name": "Cisco IOSv",
"category": "router",
"description": "Cisco Virtual IOS allows user to run IOS on a standard computer.",
diff --git a/gns3server/appliances/cisco-iosvl2.gns3a b/gns3server/appliances/cisco-iosvl2.gns3a
index 02a7af5b..821ca78d 100644
--- a/gns3server/appliances/cisco-iosvl2.gns3a
+++ b/gns3server/appliances/cisco-iosvl2.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "4368f802-ddec-4863-adbd-a36a6d83cd4c",
"name": "Cisco IOSvL2",
"category": "multilayer_switch",
"description": "Cisco Virtual IOS L2 allows user to run a IOS switching image on a standard computer.",
diff --git a/gns3server/appliances/cisco-iosxrv.gns3a b/gns3server/appliances/cisco-iosxrv.gns3a
index 72276e58..53fd8ad9 100644
--- a/gns3server/appliances/cisco-iosxrv.gns3a
+++ b/gns3server/appliances/cisco-iosxrv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "78fc5177-c399-4369-a6f8-e9c9b217c2e2",
"name": "Cisco IOS XRv",
"category": "router",
"description": "IOS XRv supports the control plane features introduced in Cisco IOS XR.",
diff --git a/gns3server/appliances/cisco-iosxrv9k.gns3a b/gns3server/appliances/cisco-iosxrv9k.gns3a
index e1084abe..c1a8930a 100644
--- a/gns3server/appliances/cisco-iosxrv9k.gns3a
+++ b/gns3server/appliances/cisco-iosxrv9k.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "ea678b10-fc52-4079-83de-36769fbd9bc3",
"name": "Cisco IOS XRv 9000",
"category": "router",
"description": "IOS XRv 9000 (aka Sunstone) is the 1st VM released running the 64-bit IOS XR operating system as used on the NCS-6xxx platform. This appliance requires 4 vCPUs and 16GB of memory to run!",
diff --git a/gns3server/appliances/cisco-iou-l2.gns3a b/gns3server/appliances/cisco-iou-l2.gns3a
index 85410e4e..2f6ace04 100644
--- a/gns3server/appliances/cisco-iou-l2.gns3a
+++ b/gns3server/appliances/cisco-iou-l2.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "9593db48-558a-4914-bb78-a20605f39c65",
"name": "Cisco IOU L2",
"category": "multilayer_switch",
"description": "Cisco IOS on UNIX Layer 2 image.",
diff --git a/gns3server/appliances/cisco-iou-l3.gns3a b/gns3server/appliances/cisco-iou-l3.gns3a
index c31ac267..19a5380b 100644
--- a/gns3server/appliances/cisco-iou-l3.gns3a
+++ b/gns3server/appliances/cisco-iou-l3.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "87bf6f58-1e5a-4ee2-afe7-715dabffcf18",
"name": "Cisco IOU L3",
"category": "router",
"description": "Cisco IOS on UNIX Layer 3 image.",
diff --git a/gns3server/appliances/cisco-ise.gns3a b/gns3server/appliances/cisco-ise.gns3a
index 54e370b0..167ff8fa 100644
--- a/gns3server/appliances/cisco-ise.gns3a
+++ b/gns3server/appliances/cisco-ise.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "cf5d1f22-953a-434d-a07e-6e17de85acf1",
"name": "Cisco ISE",
"category": "firewall",
"description": "The Cisco ISE platform is a comprehensive, next-generation, contextually-based access control solution. Cisco ISE offers authenticated network access, profiling, posture, guest management, and security group access services along with monitoring, reporting, and troubleshooting capabilities on a single physical or virtual appliance.",
diff --git a/gns3server/appliances/cisco-ngipsv.gns3a b/gns3server/appliances/cisco-ngipsv.gns3a
index 1c9b7c8a..a57a7a5d 100644
--- a/gns3server/appliances/cisco-ngipsv.gns3a
+++ b/gns3server/appliances/cisco-ngipsv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "587dd8e4-0c73-465d-bfdc-5cd7ab67029b",
"name": "Cisco NGIPSv",
"category": "firewall",
"description": "Cisco Firepower Next-Generation IPS (NGIPS) threat appliances combine superior visibility, embedded security intelligence, automated analysis, and industry-leading threat effectiveness.",
diff --git a/gns3server/appliances/cisco-nxosv.gns3a b/gns3server/appliances/cisco-nxosv.gns3a
index 16070008..b49a026d 100644
--- a/gns3server/appliances/cisco-nxosv.gns3a
+++ b/gns3server/appliances/cisco-nxosv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "6260ec1e-8ab0-40c6-9e35-fbcc88ce935e",
"name": "Cisco NX-OSv",
"category": "multilayer_switch",
"description": "NXOSv is a reference platform for an implementation of the Cisco Nexus operating system, based on the Nexus 7000-series platforms, running as a full virtual machine on a hypervisor. This includes NXAPI and MPLS LDP support.",
diff --git a/gns3server/appliances/cisco-nxosv9k.gns3a b/gns3server/appliances/cisco-nxosv9k.gns3a
index ae3c6e84..2c1862b8 100644
--- a/gns3server/appliances/cisco-nxosv9k.gns3a
+++ b/gns3server/appliances/cisco-nxosv9k.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "f739d949-136b-4a56-8b0f-d39832e5aa30",
"name": "Cisco NX-OSv 9000",
"category": "multilayer_switch",
"description": "The NX-OSv 9000 is a virtual platform that is designed to simulate the control plane aspects of a network element running Cisco Nexus 9000 software. The NX-OSv 9000 shares the same software image running on Cisco Nexus 9000 hardware platform although no specific hardware emulation is implemented. When the software runs as a virtual machine, line card (LC) ASIC provisioning or any interaction from the control plane to hardware ASIC is handled by the NX-OSv 9000 software data plane.\nThe NX-OSv 9000 for the Cisco Nexus 9000 Series provides a useful tool to enable the devops model and rapidly test changes to the infrastructure or to infrastructure automation tools. This enables network simulations in large scale for customers to validate configuration changes on a simulated network prior to applying them on a production network. Some users have also expressed interest in using the simulation system for feature test ,verification, and automation tooling development and test simualtion prior to deployment. NX-OSv 9000 can be used as a programmability vehicle to validate software defined networks (SDNs) and Network Function Virtualization (NFV) based solutions.",
@@ -81,6 +82,13 @@
"filesize": 1330315264,
"download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.2%25281%2529"
},
+ {
+ "filename": "nxosv-final.7.0.3.I7.9.qcow2",
+ "version": "7.0.3.I7.9",
+ "md5sum": "50678c719f6b822c43dd096dbdf359e8",
+ "filesize": 1003618304,
+ "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/7.0(3)I7(9)?i=!pp"
+ },
{
"filename": "nxosv-final.7.0.3.I7.7.qcow2",
"version": "7.0.3.I7.7",
@@ -218,6 +226,13 @@
"hda_disk_image": "nxosv-final.9.2.1.qcow2"
}
},
+ {
+ "name": "7.0.3.I7.9",
+ "images": {
+ "bios_image": "OVMF-20160813.fd",
+ "hda_disk_image": "nxosv-final.7.0.3.I7.9.qcow2"
+ }
+ },
{
"name": "7.0.3.I7.7",
"images": {
diff --git a/gns3server/appliances/cisco-smc.gns3a b/gns3server/appliances/cisco-smc.gns3a
index 6ae32228..2480bb5b 100644
--- a/gns3server/appliances/cisco-smc.gns3a
+++ b/gns3server/appliances/cisco-smc.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "903bbc99-6c4a-4bc7-b9b1-eb5f2e3c5470",
"name": "Cisco Stealthwatch Management Console",
"category": "firewall",
"description": "Cisco Stealthwatch is the most comprehensive visibility and network traffic security analytics solution that uses enterprise telemetry from the existing network infrastructure. It provides advanced threat detection, accelerated threat response, and simplified network segmentation using multilayer machine learning and entity modeling. With advanced behavioral analytics, you'll always know who is on your network and what they are doing.\n\nAs the control center for the Stealthwatch System, the SMC manages, coordinates, configures, and organizes all of the different components of the system. The SMC client software allows you to access the SMC's user-friendly graphical user interface from any local computer with access to a Web browser. Through the client interface, you can easily access real-time security and network information about critical segments throughout your enterprise. ",
diff --git a/gns3server/appliances/cisco-vWLC.gns3a b/gns3server/appliances/cisco-vWLC.gns3a
index 607d1a54..d99504b1 100644
--- a/gns3server/appliances/cisco-vWLC.gns3a
+++ b/gns3server/appliances/cisco-vWLC.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "e632ff43-fc14-41f8-a293-b6a62f0e1788",
"name": "Cisco vWLC",
"category": "guest",
"description": "The Virtual Wireless Controller can cost-effectively manage, secure, and optimize the performance of local and branch wireless networks. Ideal for small and medium-sized businesses, the Virtual Wireless Controller facilitates server consolidation and improves business continuity in the face of outages.",
diff --git a/gns3server/appliances/cisco-wsav.gns3a b/gns3server/appliances/cisco-wsav.gns3a
index 241b3227..85b08b31 100644
--- a/gns3server/appliances/cisco-wsav.gns3a
+++ b/gns3server/appliances/cisco-wsav.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a9dc537f-3093-42c2-95d9-fca800e59f82",
"name": "Web Security Virtual Appliance",
"category": "firewall",
"description": "The Cisco WSA was one of the first secure web gateways to combine leading protections to help organizations address the growing challenges of securing and controlling web traffic. It enables simpler, faster deployment with fewer maintenance requirements, reduced latency, and lower operating costs. \"Set and forget\" technology frees staff after initial automated policy settings go live, and automatic security updates are pushed to network devices every 3 to 5 minutes. Flexible deployment options and integration with your existing security infrastructure help you meet quickly evolving security requirements.",
diff --git a/gns3server/appliances/citrix-netscaler-vpx.gns3a b/gns3server/appliances/citrix-netscaler-vpx.gns3a
index c34ea352..bd1402c3 100644
--- a/gns3server/appliances/citrix-netscaler-vpx.gns3a
+++ b/gns3server/appliances/citrix-netscaler-vpx.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a013860f-c65d-477d-abfc-d3d98b49e7d6",
"name": "NetScaler VPX",
"category": "router",
"description": "Today's enterprises face more demands than ever, from cloud computing to 24/7 availability to increasing security threats. NetScaler ADC, an advanced software-defined application delivery controller, is your networking power player. It provides outstanding delivery of business applications-to any device and any location-with unmatched security, superior L4-7 load balancing, reliable GSLB, and 100 percent uptime. In fact, NetScaler ADC offers up to five times the performance of our closest competitor. Plus our TriScale technology saves you money by allowing your network to scale up or down without additional hardware costs.",
diff --git a/gns3server/appliances/clearos.gns3a b/gns3server/appliances/clearos.gns3a
index 4c5bd27c..8ec83838 100644
--- a/gns3server/appliances/clearos.gns3a
+++ b/gns3server/appliances/clearos.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "c731e7d0-5893-4072-a681-998df576a67c",
"name": "ClearOS CE",
"category": "firewall",
"description": "ClearOS is an operating system for your Server, Network, and Gateway systems. It is designed for homes, small to medium businesses, and distributed environments. ClearOS is commonly known as the Next Generation Small Business Server, while including indispensable Gateway and Networking functionality. It delivers a powerful IT solution with an elegant user interface that is completely web-based. Simply put.. ClearOS is the new way of delivering IT.",
diff --git a/gns3server/appliances/cloudrouter.gns3a b/gns3server/appliances/cloudrouter.gns3a
index ce72e671..b6d6b9f5 100644
--- a/gns3server/appliances/cloudrouter.gns3a
+++ b/gns3server/appliances/cloudrouter.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "e5563056-f6dc-4b51-bcff-8b566ae8b0a7",
"name": "CloudRouter",
"category": "router",
"description": "The CloudRouter Project is a collaborative open source project focused on developing a powerful, easy to use router designed for the cloud.\nCompute resources are rapidly migrating from physical infrastructure to a combination of physical, virtual and cloud environments. A similar transition is emerging in the networking space, with network control logic shifting from proprietary hardware-based platforms to open source software-based platforms. CloudRouter is a software-based router distribution designed to run on physical, virtual and cloud environments, supporting software-defined networking infrastructure. It includes the features of traditional hardware routers, as well as support for emerging technologies such as containers and software-defined interconnection. CloudRouter aims to facilitate migration to the cloud without giving up control over network routing and governance.",
diff --git a/gns3server/appliances/coreos.gns3a b/gns3server/appliances/coreos.gns3a
index 32ac0c73..babf9f1b 100644
--- a/gns3server/appliances/coreos.gns3a
+++ b/gns3server/appliances/coreos.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "5a03e6b9-afe3-44f5-ae35-5664c0250b94",
"name": "CoreOS",
"category": "guest",
"description": "CoreOS is designed for security, consistency, and reliability. Instead of installing packages via yum or apt, CoreOS uses Linux containers to manage your services at a higher level of abstraction. A single service's code and all dependencies are packaged within a container that can be run on one or many CoreOS machines.",
diff --git a/gns3server/appliances/cumulus-vx.gns3a b/gns3server/appliances/cumulus-vx.gns3a
index 884ac4e5..03685393 100644
--- a/gns3server/appliances/cumulus-vx.gns3a
+++ b/gns3server/appliances/cumulus-vx.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "f1b83421-6c20-4fa7-8292-568fe08874c4",
"name": "Cumulus VX",
"category": "multilayer_switch",
"description": "Cumulus VX is a community-supported virtual appliance that enables cloud admins and network engineers to preview and test Cumulus Networks technology at zero cost. You can build sandbox environments to learn Open Networking concepts, prototype network operations and script & develop applications risk-free. With Cumulus VX, you can get started with Open Networking at your pace, on your time, and in your environment!",
diff --git a/gns3server/appliances/danos.gns3a b/gns3server/appliances/danos.gns3a
index bb9ed3d3..f0cd7f36 100644
--- a/gns3server/appliances/danos.gns3a
+++ b/gns3server/appliances/danos.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "ccbd2d81-c588-4bbb-80ac-ba20686b613a",
"name": "DANOS",
"category": "router",
"description": "The Disaggregated Network Operating System (DANOS) project enables community collaboration across network hardware, forwarding, and operating system layers. DANOS is initially based on AT&T's \"dNOS\" software framework of a more open, cost-effective and flexible alternative to traditional networking equipment. As part of The Linux Foundation, it now incorporates contributions from complementary open source communities in building a standardized distributed Network Operating System (NOS) to speed the adoption and use of white boxes in a service provider's infrastructure.",
diff --git a/gns3server/appliances/debian10-min.gns3a b/gns3server/appliances/debian10-min.gns3a
index fbe787b0..bf38dfb7 100644
--- a/gns3server/appliances/debian10-min.gns3a
+++ b/gns3server/appliances/debian10-min.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "8f8df56b-605d-447c-94a4-4848e3ae8392",
"name": "Debian 10 Minimal",
"category": "guest",
"description": "Debian 10 Custom, with automatic disk resize and ssh/nmap",
diff --git a/gns3server/appliances/deft-linux.gns3a b/gns3server/appliances/deft-linux.gns3a
index 5c9d25b4..0c39a22c 100644
--- a/gns3server/appliances/deft-linux.gns3a
+++ b/gns3server/appliances/deft-linux.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "518a5802-266a-4299-b84b-e6cccb5a39ac",
"name": "DEFT Linux",
"category": "guest",
"description": "DEFT (acronym for Digital Evidence & Forensics Toolkit) is a distribution made for Computer Forensics, with the purpose of running live on systems without tampering or corrupting devices (hard disks, pendrives, etc...) connected to the PC where the boot process takes place.\nThe DEFT system is based on GNU Linux, it can run live (via DVDROM or USB pendrive), installed or run as a Virtual Appliance on VMware or Virtualbox. DEFT employs LXDE as desktop environment and WINE for executing Windows tools under Linux. It features a comfortable mount manager for device management.\nDEFT is paired with DART (acronym for Digital Advanced Response Toolkit), a Forensics System which can be run on Windows and contains the best tools for Forensics and Incident Response. DART features a GUI with logging and integrity check for the instruments here contained.\nBesides all this, the DEFT staff is devoted to implementing and developing applications which are released to Law Enforcement Officers, such as Autopsy 3 for Linux.",
diff --git a/gns3server/appliances/dell-ftos.gns3a b/gns3server/appliances/dell-ftos.gns3a
index aa36baad..79314dcf 100644
--- a/gns3server/appliances/dell-ftos.gns3a
+++ b/gns3server/appliances/dell-ftos.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "85441847-4091-4894-9079-802084a1845b",
"name": "Dell OS9",
"category": "router",
"description": "Dell Networking OS9 (formerly FTOS).\nOS9 powers the Dell Networking product portfolio and has been hardened in some of the largest and most demanding environments in the world to meet stringent reliability, scalability and serviceability requirements. \n\nDownload and uncompress zip files from the Dell support site - corresponding to the FTOS/OS9 image name. Please 'Select FTOS for S-Series OS-EMULATOR'. Import the resulting ISO image.",
diff --git a/gns3server/appliances/dns.gns3a b/gns3server/appliances/dns.gns3a
index c0f10568..e41026f3 100644
--- a/gns3server/appliances/dns.gns3a
+++ b/gns3server/appliances/dns.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "f049539d-db46-422f-8d10-ff9b96a2a4ae",
"name": "DNS",
"category": "guest",
"description": "This appliance provides DNS using dnsmasq with the local domain set to \"lab\".",
diff --git a/gns3server/appliances/empty-vm.gns3a b/gns3server/appliances/empty-vm.gns3a
new file mode 100644
index 00000000..83724603
--- /dev/null
+++ b/gns3server/appliances/empty-vm.gns3a
@@ -0,0 +1,73 @@
+{
+ "appliance_id": "1cfdf900-7c30-4cb7-8f03-3f61d2581633",
+ "name": "Empty VM",
+ "category": "guest",
+ "description": "An empty VM with empty hard disks 8G, 30G & 100G.",
+ "vendor_name": "GNS3",
+ "vendor_url": "https://gns3.com",
+ "documentation_url": "",
+ "product_name": "QEMU",
+ "product_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/",
+ "registry_version": 4,
+ "status": "experimental",
+ "maintainer": "GNS3 Team",
+ "maintainer_email": "developers@gns3.net",
+ "usage": "Default at first boot the VM will start from the cdrom.",
+ "port_name_format": "eth{0}",
+ "qemu": {
+ "adapter_type": "e1000",
+ "adapters": 1,
+ "ram": 1024,
+ "arch": "x86_64",
+ "console_type": "vnc",
+ "hda_disk_interface": "sata",
+ "boot_priority": "d",
+ "kvm": "allow"
+ },
+ "images": [
+ {
+ "filename": "empty8G.qcow2",
+ "version": "8G",
+ "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": "empty30G.qcow2",
+ "version": "30G",
+ "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": "empty100G.qcow2",
+ "version": "100G",
+ "md5sum": "1e6409a4523ada212dea2ebc50e50a65",
+ "filesize": 198656,
+ "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/",
+ "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download"
+ }
+ ],
+ "versions": [
+ {
+ "name": "8G",
+ "images": {
+ "hda_disk_image": "empty8G.qcow2"
+ }
+ },
+ {
+ "name": "30G",
+ "images": {
+ "hda_disk_image": "empty30G.qcow2"
+ }
+ },
+ {
+ "name": "100G",
+ "images": {
+ "hda_disk_image": "empty100G.qcow2"
+ }
+ }
+ ]
+}
diff --git a/gns3server/appliances/exos.gns3a b/gns3server/appliances/exos.gns3a
index 5e51b1a3..14416153 100644
--- a/gns3server/appliances/exos.gns3a
+++ b/gns3server/appliances/exos.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "0293ded2-0ca3-4052-913f-8c2d872e46ba",
"name": "EXOS VM",
"category": "multilayer_switch",
"description": "The ExtremeXOS VM is created and maintained by Extreme Networks for users to emulate a network using EXOS switches.",
diff --git a/gns3server/appliances/extreme-networks-voss.gns3a b/gns3server/appliances/extreme-networks-voss.gns3a
index 54d99ca9..1435bcd6 100644
--- a/gns3server/appliances/extreme-networks-voss.gns3a
+++ b/gns3server/appliances/extreme-networks-voss.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "3e81eb47-43c4-4676-bbc5-8dda1d7abe08",
"name": "VOSS VM",
"category": "multilayer_switch",
"description": "The VOSS VM is a software emulation of a VSP8K switch.",
diff --git a/gns3server/appliances/f5-bigip.gns3a b/gns3server/appliances/f5-bigip.gns3a
index 9d0d902a..6d2061f4 100644
--- a/gns3server/appliances/f5-bigip.gns3a
+++ b/gns3server/appliances/f5-bigip.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "4aa73054-4d54-4829-9c00-b16ad50e7a7e",
"name": "F5 BIG-IP LTM VE",
"category": "router",
"description": "The BIG-IP family of products offers the application intelligence that network managers need to ensure applications are fast, secure, and available. All BIG-IP products share a common underlying architecture, F5's Traffic Management Operating System (TMOS), which provides unified intelligence, flexibility, and programmability. Together, BIG-IP's powerful platforms, advanced modules, and centralized management system make up the most comprehensive set of application delivery tools in the industry. BIG-IP Virtual Edition (VE) is a version of the BIG-IP system that runs as a virtual machine in specifically-supported hypervisors. BIG-IP VE emulates a hardware-based BIG-IP system running a VE-compatible version of BIG-IP software.",
diff --git a/gns3server/appliances/f5-bigiq.gns3a b/gns3server/appliances/f5-bigiq.gns3a
index 7aa07ffd..26517845 100644
--- a/gns3server/appliances/f5-bigiq.gns3a
+++ b/gns3server/appliances/f5-bigiq.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "799f2414-7341-4f55-8b6d-2b3f6d11b1d8",
"name": "F5 BIG-IQ CM",
"category": "guest",
"description": "When you go from managing a few boxes to managing a few dozen, your processes, logistics, and needs all change. BIG-IQ Centralized Management brings all of your devices together, so you can discover, track, upgrade, and deploy more efficiently. You can also monitor key metrics from one location, saving yourself both time and effort.\n\nCentrally manage up to 200 physical, virtual, or virtual clustered multiprocessing (vCMP) based BIG-IP devices. BIG-IQ Centralized Management also handles licensing for up to 5,000 unmanaged devices, so you can spin BIG-IP virtual editions (VEs) up or down as needed.",
diff --git a/gns3server/appliances/firefox.gns3a b/gns3server/appliances/firefox.gns3a
index 633bd74e..14fe1ba4 100644
--- a/gns3server/appliances/firefox.gns3a
+++ b/gns3server/appliances/firefox.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "b2027465-2959-4ef3-ba56-7b2880e4e711",
"name": "Firefox",
"category": "guest",
"description": "A light Linux based on TinyCore Linux with Firefox preinstalled",
diff --git a/gns3server/appliances/fortiadc-manager.gns3a b/gns3server/appliances/fortiadc-manager.gns3a
index e14f551c..d1df156f 100644
--- a/gns3server/appliances/fortiadc-manager.gns3a
+++ b/gns3server/appliances/fortiadc-manager.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a1903402-919b-4620-9b07-37902f46a4e3",
"name": "FortiADC Manager",
"category": "guest",
"description": "FortiADC Manager allows you to use a web- based user interface to configure remote FortiADC devices. It allows you to simplify and speed up the FortiADC deployment and update process by maintaining configuration templates and policy packages that you can modify and apply as needed.",
diff --git a/gns3server/appliances/fortiadc.gns3a b/gns3server/appliances/fortiadc.gns3a
index f8e86456..dce76870 100644
--- a/gns3server/appliances/fortiadc.gns3a
+++ b/gns3server/appliances/fortiadc.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "74e0ff73-7ceb-4871-81f0-b4dd4b35911a",
"name": "FortiADC",
"category": "router",
"description": "Fortinet ADC appliances optimize the availability, user experience, and scalability of enterprise application delivery. They deliver fast, secure, and intelligent acceleration and distribution of even the most demanding enterprise applications.",
diff --git a/gns3server/appliances/fortianalyzer.gns3a b/gns3server/appliances/fortianalyzer.gns3a
index b16940a2..3e73ea7a 100644
--- a/gns3server/appliances/fortianalyzer.gns3a
+++ b/gns3server/appliances/fortianalyzer.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "4fc11cfb-d600-4dd4-af94-e4b16191be2a",
"name": "FortiAnalyzer",
"category": "guest",
"description": "FortiAnalyzer Network Security Logging, Analysis, and Reporting Appliances securely aggregate log data from Fortinet Security Appliances. A comprehensive suite of easily customable reports allows you to quickly analyze and visualize network threats, inefficiencies and usage.",
diff --git a/gns3server/appliances/fortiauthenticator.gns3a b/gns3server/appliances/fortiauthenticator.gns3a
index 6d6799c8..f766ad96 100644
--- a/gns3server/appliances/fortiauthenticator.gns3a
+++ b/gns3server/appliances/fortiauthenticator.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "57e289b6-68a4-4911-a916-0d3def89ef74",
"name": "FortiAuthenticator",
"category": "guest",
"description": "FortiAuthenticator user identity management appliances strengthen enterprise security by simplifying and centralizing the management and storage of user identity information.",
diff --git a/gns3server/appliances/forticache.gns3a b/gns3server/appliances/forticache.gns3a
index e27362b0..b2a6d037 100644
--- a/gns3server/appliances/forticache.gns3a
+++ b/gns3server/appliances/forticache.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "75df92b4-69d3-4d5d-91b1-c36efa68d9fd",
"name": "FortiCache",
"category": "guest",
"description": "FortiCache VM high performance Web Caching virtual appliances address bandwidth saturation, high latency, and poor performance caused by caching popular internet content locally for carriers, service providers, enterprises and educational networks. FortiCache VM appliances reduce the cost and impact of cached content on the network, while increasing performance and end- user satisfaction by improving the speed of delivery of popular repeated content.",
diff --git a/gns3server/appliances/fortigate.gns3a b/gns3server/appliances/fortigate.gns3a
index 4e933a54..fb830442 100644
--- a/gns3server/appliances/fortigate.gns3a
+++ b/gns3server/appliances/fortigate.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "2b3da0fb-abe3-4131-92b6-4e7fcb50dba5",
"name": "FortiGate",
"category": "firewall",
"description": "FortiGate Virtual Appliance offers the same level of advanced threat prevention features like the physical appliances in private, hybrid and public cloud deployment.",
diff --git a/gns3server/appliances/fortimail.gns3a b/gns3server/appliances/fortimail.gns3a
index abb9eed4..77bc0c35 100644
--- a/gns3server/appliances/fortimail.gns3a
+++ b/gns3server/appliances/fortimail.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "4089ee66-e13b-4490-aa51-53cdb969e024",
"name": "FortiMail",
"category": "guest",
"description": "FortiMail is a complete Secure Email Gateway offering suitable for any size organization. It provides a single solution to protect against inbound attacks - including advanced malware -, as well as outbound threats and data loss with a wide range of top-rated security capabilities.",
diff --git a/gns3server/appliances/fortimanager.gns3a b/gns3server/appliances/fortimanager.gns3a
index 8f75a84e..ce77ab7f 100644
--- a/gns3server/appliances/fortimanager.gns3a
+++ b/gns3server/appliances/fortimanager.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "b9ce377f-6a6c-497a-a12d-444936a575c3",
"name": "FortiManager",
"category": "guest",
"description": "FortiManager Security Management appliances allow you to centrally manage any number of Fortinet Network Security devices, from several to thousands, including FortiGate, FortiWiFi, and FortiCarrier.",
diff --git a/gns3server/appliances/fortiproxy.gns3a b/gns3server/appliances/fortiproxy.gns3a
index 140f5bcd..93de1f51 100644
--- a/gns3server/appliances/fortiproxy.gns3a
+++ b/gns3server/appliances/fortiproxy.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "0f57eb3a-7b1c-47d4-96c4-fe8ed60c9f50",
"name": "FortiProxy",
"category": "firewall",
"description": "FortiProxy is a secure web proxy that protects employees against internet-borne attacks by incorporating multiple detection techniques such as web filtering, DNS filtering, data loss prevention, antivirus, intrusion prevention and advanced threat protection. It helps enterprises enforce internet compliance using granular application control.",
diff --git a/gns3server/appliances/fortirecorder.gns3a b/gns3server/appliances/fortirecorder.gns3a
index b4412c82..9a1331d8 100644
--- a/gns3server/appliances/fortirecorder.gns3a
+++ b/gns3server/appliances/fortirecorder.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "754f4df8-934f-4a55-8d32-5bfd922785d9",
"name": "FortiRecorder",
"category": "guest",
"description": "Surveillance systems can be complicated, expensive, and unreliable. But FortiCamera and FortiRecorder simplify IP video surveillance and there are no license fees. With FortiCams, you can see everything: doors, POS terminals, public areas--whatever you need to keep an eye on. FortiRecorder captures the images for easy monitoring, storage, and retrieval. Just plug in your cameras, connect the FortiRecorder, open a web browser or client application, and you're ready to go. It's easy to navigate and configure with event timelines and profile-driven configuration.",
diff --git a/gns3server/appliances/fortisandbox.gns3a b/gns3server/appliances/fortisandbox.gns3a
index d74d1bab..6d352117 100644
--- a/gns3server/appliances/fortisandbox.gns3a
+++ b/gns3server/appliances/fortisandbox.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "88252124-93a4-4851-9b0f-b0f264705c1a",
"name": "FortiSandbox",
"category": "firewall",
"description": "Today's threats are increasingly sophisticated and often bypass traditional malware security by masking their malicious activity. A sandbox augments your security architecture by validating threats in a separate, secure environment. FortiSandbox offers a powerful combination of advanced detection, automated mitigation, actionable insight, and flexible deployment to stop targeted attacks and subsequent data loss. It's also a key component of our Advanced Threat Protection solution.",
diff --git a/gns3server/appliances/fortisiem-super_worker.gns3a b/gns3server/appliances/fortisiem-super_worker.gns3a
index 9c9f39a7..92c345d3 100644
--- a/gns3server/appliances/fortisiem-super_worker.gns3a
+++ b/gns3server/appliances/fortisiem-super_worker.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "b963c9d0-f73b-4a6c-b876-644ae5dd2779",
"name": "FortiSIEM",
"category": "guest",
"description": "Breaches to network security continue to occur across all industry verticals, even to the most respected brands. The time it takes to discover, isolate, and remediate the incident continues to be measured in hundreds of days-having material impacts on security and compliance standards. It is no wonder that many organizations are struggling. As recent surveys have shown, enterprises have an average of 32 different vendors' devices in their network, with no automated ability to cross-correlate the data that each is collecting. It is also easy to see why organizations are strapped for the cyber security personnel they need to manage all the data in these complex environments.\n\nFrom its inception, FortiSIEM was built to reduce complexity in managing network and security operations. FortiSIEM provides organizations of all sizes with a comprehensive, holistic, and scalable solution for managing security, performance, and compliance from IoT to the cloud.",
diff --git a/gns3server/appliances/fortiweb.gns3a b/gns3server/appliances/fortiweb.gns3a
index 2365d76f..a0924bec 100644
--- a/gns3server/appliances/fortiweb.gns3a
+++ b/gns3server/appliances/fortiweb.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "62cc83dc-be46-49b3-80e0-9f0d4d644fc9",
"name": "FortiWeb",
"category": "firewall",
"description": "FortiWeb Web Application Firewalls provide specialized, layered web application threat protection for medium/large enterprises, application service providers, and SaaS providers.",
diff --git a/gns3server/appliances/freeRouter.gns3a b/gns3server/appliances/freeRouter.gns3a
index d1e0ed21..cc9b887b 100644
--- a/gns3server/appliances/freeRouter.gns3a
+++ b/gns3server/appliances/freeRouter.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "691f6552-725f-4dff-a2ba-220f5e3ab6a6",
"name": "freeRouter",
"category": "router",
"description": "networking swiss army knife - it speaks routing protocols, and (re)encapsulates packets on interfaces",
diff --git a/gns3server/appliances/freebsd.gns3a b/gns3server/appliances/freebsd.gns3a
index 5d6d2bd5..61f62171 100644
--- a/gns3server/appliances/freebsd.gns3a
+++ b/gns3server/appliances/freebsd.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "0706912e-be44-45b7-9723-d9c3749dd5ef",
"name": "FreeBSD",
"category": "guest",
"description": "FreeBSD is an advanced computer operating system used to power modern servers, desktops, and embedded platforms. A large community has continually developed it for more than thirty years. Its advanced networking, security, and storage features have made FreeBSD the platform of choice for many of the busiest web sites and most pervasive embedded networking and storage devices.",
diff --git a/gns3server/appliances/freenas.gns3a b/gns3server/appliances/freenas.gns3a
index 23583e2e..5d2a684a 100644
--- a/gns3server/appliances/freenas.gns3a
+++ b/gns3server/appliances/freenas.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "dabaa0d5-8b44-40a6-9a25-6c81129dd315",
"name": "FreeNAS",
"category": "guest",
"description": "FreeNAS is a Free and Open Source Network Attached Storage (NAS) software appliance. This means that you can use FreeNAS to share data over file-based sharing protocols, including CIFS for Windows users, NFS for Unix-like operating systems, and AFP for Mac OS X users. FreeNAS uses the ZFS file system to store, manage, and protect data. ZFS provides advanced features like snapshots to keep old versions of files, incremental remote backups to keep your data safe on another device without huge file transfers, and intelligent compression, which reduces the size of files so quickly and efficiently that it actually helps transfers happen faster.",
diff --git a/gns3server/appliances/frr.gns3a b/gns3server/appliances/frr.gns3a
index 2765dd81..c05e42cb 100644
--- a/gns3server/appliances/frr.gns3a
+++ b/gns3server/appliances/frr.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "64f3dd9e-77bf-492c-a245-26d2a0e9bde8",
"name": "FRR",
"category": "router",
"description": "FRRouting (FRR) is an IP routing protocol suite for Linux and Unix platforms which includes protocol daemons for BGP, IS-IS, LDP, OSPF, PIM, and RIP.\n\nFRR's seamless integration with the native Linux/Unix IP networking stacks makes it applicable to a wide variety of use cases including connecting hosts/VMs/containers to the network, advertising network services, LAN switching and routing, Internet access routers, and Internet peering.\n\nThis is an unofficial VM of FRR.",
diff --git a/gns3server/appliances/hp-vsr1001.gns3a b/gns3server/appliances/hp-vsr1001.gns3a
index e70d2ea1..015eb771 100644
--- a/gns3server/appliances/hp-vsr1001.gns3a
+++ b/gns3server/appliances/hp-vsr1001.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "16e06d10-bf02-4cd8-9807-69b8ef42efed",
"name": "HPE VSR1001",
"category": "router",
"description": "The HPE VSR1000 Virtual Services Router Series is a software application, running on a server, which provides functionality similar to that of a physical router: robust routing between networked devices using a number of popular routing protocols. It also delivers the critical network services associated with today's enterprise routers such as VPN gateway, firewall and other security and traffic management functions.\n\nThe virtual services router (VSR) application runs on a hypervqcor on the server, and supports VMware vSphere and Linux KVM hypervqcors. From one to eight virtual CPUs are supported, depending on license.\n\nBecause the VSR1000 Series application runs the same HPE Comware version 7 operating system as HPE switches and routers, it enables significant operational savings. And being virtual, additional agility and ease of deployment is realized, as resources on the VSR can be dynamically allocated and upgraded upon demand as performance requirements grow.\n\nA variety of deployment models are supported including enterprise branch CPE routing, and cloud offload for small to medium workloads.",
diff --git a/gns3server/appliances/huawei-ar1kv.gns3a b/gns3server/appliances/huawei-ar1kv.gns3a
index 46fba486..ef2ccfbd 100644
--- a/gns3server/appliances/huawei-ar1kv.gns3a
+++ b/gns3server/appliances/huawei-ar1kv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "84b4ff53-5d0a-492c-bf80-5e8d7e0745ae",
"name": "HuaWei AR1000v",
"category": "router",
"description": "Huawei AR1000V Virtual Router (Virtual CPE, vCPE) is an NFV product based on the industry-leading Huawei VRP platform. The product has rich business capabilities, integrating routing, switching, security, VPN, QoS and other functions, with software and hardware decoupling, Features such as easy business deployment and intelligent operation and maintenance can be applied to scenarios such as enterprise interconnection (SD-WAN) corporate headquarters (Hub point), POP point access, and cloud access.",
diff --git a/gns3server/appliances/huawei-ce12800.gns3a b/gns3server/appliances/huawei-ce12800.gns3a
index 135c4522..cf5cf6fb 100644
--- a/gns3server/appliances/huawei-ce12800.gns3a
+++ b/gns3server/appliances/huawei-ce12800.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "bd86792e-9870-4b42-8f16-cb2776f1d5d5",
"name": "HuaWei CE12800",
"category": "multilayer_switch",
"description": "CE12800 series switches are high-performance core switches designed for data center networks and high-end campus networks. The switches provide stable, reliable, secure, and high-performance Layer 2/Layer 3 switching services, to help build an elastic, virtualized, agile, and high-quality network.",
diff --git a/gns3server/appliances/huawei-ne40e.gns3a b/gns3server/appliances/huawei-ne40e.gns3a
index 4c07b542..8a039a7c 100644
--- a/gns3server/appliances/huawei-ne40e.gns3a
+++ b/gns3server/appliances/huawei-ne40e.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "03aa586b-5666-49e9-a70c-e5935fdbc23d",
"name": "HuaWei NE40E",
"category": "router",
"description": "Based on a 2T platform, the NetEngine 40E-X series provides the industry\u2019s highest capacity 2T routing line cards. Combining performance with low power consumption, innovative Internet Protocol (IP) hard pipe technology, and quick evolution capabilities, NetEngine 40E-X routers meet the low latency and high reliability requirements of business-critical services as well as mature Wide Area Network (WAN) Software-Defined Networking (SDN) solutions. They can serve as core nodes on enterprise WANs, access nodes on large-scale enterprise networks, interconnection and aggregation nodes on campus networks, and edge nodes on large-scale Internet Data Center (IDC) networks.",
diff --git a/gns3server/appliances/huawei-usg6kv.gns3a b/gns3server/appliances/huawei-usg6kv.gns3a
index 21256ac6..f2d0506c 100644
--- a/gns3server/appliances/huawei-usg6kv.gns3a
+++ b/gns3server/appliances/huawei-usg6kv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "62a59b15-84c7-4ab3-a785-50e139d94c6c",
"name": "HuaWei USG6000v",
"category": "firewall",
"description": "Huawei USG6000V is a virtual service gateway based on Network Functions Virtualization (NFV). It features high virtual resource usage and provides virtualized gateway services, such as vFW, vIPsec, vLB, vIPS, vAV, and vURL Remote Query.\nHuawei USG6000V is compatible with most mainstream virtual platforms. It provides standard APIs, together with the OpenStack cloud platform, SDN Controller, and MANO to achieve intelligent solutions for cloud security. This gateway meets flexible service customization requirements for frequent security service changes, elastic and on-demand resource allocation, visualized network management, and rapid rollout.",
diff --git a/gns3server/appliances/internet.gns3a b/gns3server/appliances/internet.gns3a
index 7d7ff9ec..489d35ce 100644
--- a/gns3server/appliances/internet.gns3a
+++ b/gns3server/appliances/internet.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "f8302832-ad07-47e2-a750-004f700bd47c",
"name": "Internet",
"category": "router",
"description": "This appliance simulate a domestic modem. It provide an IP via DHCP and will nat all connection to the internet without the need of using a cloud interface in your topologies. IP will be in the subnet 172.16.0.0/16. Multiple internet will have different IP range from 172.16.1.0/24 to 172.16.253.0/24 .\n\nWARNING USE IT ONLY WITH THE GNS3 VM.",
diff --git a/gns3server/appliances/ipfire.gns3a b/gns3server/appliances/ipfire.gns3a
index 5c361a6b..07610b57 100644
--- a/gns3server/appliances/ipfire.gns3a
+++ b/gns3server/appliances/ipfire.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "286b3ba3-6646-41d2-b67c-dd6de9da8a5a",
"name": "IPFire",
"category": "firewall",
"description": "IPFire was designed with both modularity and a high-level of flexibility in mind. You can easily deploy many variations of it, such as a firewall, a proxy server or a VPN gateway. The modular design ensures that it runs exactly what you've configured it for and nothing more. Everything is simple to manage and update through the package manager, making maintenance a breeze.",
diff --git a/gns3server/appliances/ipterm.gns3a b/gns3server/appliances/ipterm.gns3a
index 0fdbdf68..be1875ab 100644
--- a/gns3server/appliances/ipterm.gns3a
+++ b/gns3server/appliances/ipterm.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "7f58b246-c4f4-4db2-b4e6-f6180bf235ff",
"name": "ipterm",
"category": "guest",
"description": "ipterm is a debian based networking toolbox.\nIt contains the following utilities: net-tools, iproute2, ping, traceroute, curl, host, iperf3, mtr, socat, ssh client, tcpdump and the multicast testing tools msend/mreceive.",
diff --git a/gns3server/appliances/ipxe.gns3a b/gns3server/appliances/ipxe.gns3a
index fff2f330..ad4af414 100644
--- a/gns3server/appliances/ipxe.gns3a
+++ b/gns3server/appliances/ipxe.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "d6d659ae-b450-4dd8-abf6-face55c3de41",
"name": "ipxe",
"category": "guest",
"description": "boot guest from network via iPXE",
diff --git a/gns3server/appliances/juniper-junos-space.gns3a b/gns3server/appliances/juniper-junos-space.gns3a
index d4446dfe..ea462c32 100644
--- a/gns3server/appliances/juniper-junos-space.gns3a
+++ b/gns3server/appliances/juniper-junos-space.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "3b65c68f-cdde-4dde-a0e7-5ef8c9b7ec2c",
"name": "Junos Space",
"category": "guest",
"description": "Junos Space Network Management Platform works with Juniper's management applications to simplify and automate management of Juniper's switching, routing, and security devices. As part of a complete solution, the platform provides broad fault, configuration, accounting, performance, and security management (FCAPS) capability, same day support for new devices and Junos OS releases, a task-specific user interface, and northbound APIs for integration with existing network management systems (NMS) or operations/business support systems (OSS/BSS).\n\nThe platform helps network operators at enterprises and service providers scale operations, reduce complexity, and enable new applications and services to be brought to market quickly, through multilayered network abstractions, operator-centric automation schemes, and a simple point-and-click UI.",
diff --git a/gns3server/appliances/juniper-vmx-legacy.gns3a b/gns3server/appliances/juniper-vmx-legacy.gns3a
index d1eb1712..1409c4c7 100644
--- a/gns3server/appliances/juniper-vmx-legacy.gns3a
+++ b/gns3server/appliances/juniper-vmx-legacy.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "82b0804c-1ded-44d4-a79e-608f3fb505bd",
"name": "Juniper vMX",
"category": "router",
"description": "The vMX is a full-featured, carrier-grade virtual MX Series 3D Universal Edge Router that extends 15+ years of Juniper Networks edge routing expertise to the virtual realm. This appliance is a single VM pre-release version that does not require to be paired with another VM like in the vCP/vFP architecture.",
diff --git a/gns3server/appliances/juniper-vmx-vcp.gns3a b/gns3server/appliances/juniper-vmx-vcp.gns3a
index cc31d8c0..6a94a9fb 100644
--- a/gns3server/appliances/juniper-vmx-vcp.gns3a
+++ b/gns3server/appliances/juniper-vmx-vcp.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "92ea0431-2325-451f-8c0a-9830ddbe48ad",
"name": "Juniper vMX vCP",
"category": "router",
"description": "The vMX is a full-featured, carrier-grade virtual MX Series 3D Universal Edge Router that extends 15+ years of Juniper Networks edge routing expertise to the virtual realm. This appliance is for the Virtual Control Plane (vCP) VM and is meant to be paired with the Virtual Forwarding Plane (vFP) VM.",
@@ -6,7 +7,7 @@
"vendor_url": "https://www.juniper.net/us/en/",
"documentation_url": "http://www.juniper.net/techpubs/",
"product_name": "Juniper vMX vCP",
- "product_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/",
+ "product_url": "https://www.juniper.net/us/en/products/routers/mx-series/vmx-virtual-router-software.html",
"registry_version": 3,
"status": "experimental",
"maintainer": "none",
@@ -28,24 +29,48 @@
"options": "-nographic -enable-kvm"
},
"images": [
+ {
+ "filename": "vmxhdd.img",
+ "version": "1",
+ "md5sum": "ae26e0f32605a53a5c85342bad677c9f",
+ "filesize": 197120
+ },
{
"filename": "junos-vmx-x86-64-20.2R1.10.qcow2",
"version": "20.2R1.10-KVM",
"md5sum": "182484474accf07bd403ef17fa2959a9",
"filesize": 1413349376
},
- {
- "filename": "vmxhdd-20.2R1.10.img",
- "version": "20.2R1.10-KVM",
- "md5sum": "ae26e0f32605a53a5c85342bad677c9f",
- "filesize": 197120
- },
{
"filename": "metadata-usb-re-20.2R1.10.img",
"version": "20.2R1.10-KVM",
"md5sum": "25322c2caf542059de72e9adbec1fb68",
"filesize": 10485760
},
+ {
+ "filename": "junos-vmx-x86-64-19.4R3-S4.1.qcow2",
+ "version": "19.4R3-S4.1-OpenStack",
+ "md5sum": "ffd3901ca4566aa0b0f9566f8183da3b",
+ "filesize": 1378680832
+ },
+ {
+ "filename": "metadata-usb-re.img",
+ "version": "19.4R3-S4.1-OpenStack",
+ "md5sum": "d08d8d6c288d0d4588e7cc2b65ea1632",
+ "filesize": 10485760
+ },
+ {
+ "filename": "junos-vmx-x86-64-19.3R1.8.qcow2",
+ "version": "19.3R1.8-KVM",
+ "md5sum": "cd14a6884edeb6b337d3c2be02241c63",
+ "filesize": 1435238400
+ },
+ {
+ "filename": "metadata-usb-re-19.3R1.8.img",
+ "version": "19.3R1.8-KVM",
+ "md5sum": "3c66c4657773a0cd2b38ffd84115446a",
+ "filesize": 10485760
+ },
{
"filename": "junos-vmx-x86-64-17.4R1.16.qcow2",
"version": "17.4R1.16-KVM",
@@ -343,10 +368,26 @@
"name": "20.2R1.10-KVM",
"images": {
"hda_disk_image": "junos-vmx-x86-64-20.2R1.10.qcow2",
- "hdb_disk_image": "vmxhdd-20.2R1.10.img",
+ "hdb_disk_image": "vmxhdd.img",
"hdc_disk_image": "metadata-usb-re-20.2R1.10.img"
}
},
+ {
+ "name": "19.4R3-S4.1-OpenStack",
+ "images": {
+ "hda_disk_image": "junos-vmx-x86-64-19.4R3-S4.1.qcow2",
+ "hdb_disk_image": "vmxhdd.img",
+ "hdc_disk_image": "metadata-usb-re.img"
+ }
+ },
+ {
+ "name": "19.3R1.8-KVM",
+ "images": {
+ "hda_disk_image": "junos-vmx-x86-64-19.3R1.8.qcow2",
+ "hdb_disk_image": "vmxhdd.img",
+ "hdc_disk_image": "metadata-usb-re-19.3R1.8.img"
+ }
+ },
{
"name": "17.4R1.16-KVM",
"images": {
diff --git a/gns3server/appliances/juniper-vmx-vfp.gns3a b/gns3server/appliances/juniper-vmx-vfp.gns3a
index 9e6a9e35..626a3c3c 100644
--- a/gns3server/appliances/juniper-vmx-vfp.gns3a
+++ b/gns3server/appliances/juniper-vmx-vfp.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "31094219-7691-4eb1-8337-bb0a756a24a8",
"name": "Juniper vMX vFP",
"category": "router",
"description": "The vMX is a full-featured, carrier-grade virtual MX Series 3D Universal Edge Router that extends 15+ years of Juniper Networks edge routing expertise to the virtual realm. This appliance is for the Virtual Forwarding Plane (vFP) VM and is meant to be paired with the Virtual Control Plane (vCP) VM.",
@@ -33,6 +34,13 @@
"filesize": 2447376384,
"download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/"
},
+ {
+ "filename": "vFPC-20210115.img",
+ "version": "19.4R3-S4.1-OpenStack",
+ "md5sum": "a218029c288d32278d7c483a69de35c0",
+ "filesize": 2447376384,
+ "download_url": "http://www.juniper.net/us/en/products-services/routing/mx-series/vmx/"
+ },
{
"filename": "vFPC-20190819.img",
"version": "19.3R1.8-KVM",
@@ -160,6 +168,12 @@
"hda_disk_image": "vFPC-20200526.img"
}
},
+ {
+ "name": "19.4R3-S4.1-OpenStack",
+ "images": {
+ "hda_disk_image": "vFPC-20210115.img"
+ }
+ },
{
"name": "19.3R1.8-KVM",
"images": {
diff --git a/gns3server/appliances/juniper-vqfx-pfe.gns3a b/gns3server/appliances/juniper-vqfx-pfe.gns3a
index 889e982b..b605c22e 100644
--- a/gns3server/appliances/juniper-vqfx-pfe.gns3a
+++ b/gns3server/appliances/juniper-vqfx-pfe.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "5c32105f-0492-463e-bada-1d8dec88dcc7",
"name": "Juniper vQFX PFE",
"category": "multilayer_switch",
"description": "The vQFX10000 makes it easy for you to try out our physical QFX10000 high-performance data center switch without the wait for physical delivery. Although the virtual version has limited performance relative to the physical switch, it lets you quickly emulate the same features for the control plane of the physical switch, or both its control and data planes.",
diff --git a/gns3server/appliances/juniper-vqfx-re.gns3a b/gns3server/appliances/juniper-vqfx-re.gns3a
index 31c2710d..4235c280 100644
--- a/gns3server/appliances/juniper-vqfx-re.gns3a
+++ b/gns3server/appliances/juniper-vqfx-re.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "967f0f22-8235-4f9b-b0f8-6f50cb146d8f",
"name": "Juniper vQFX RE",
"category": "multilayer_switch",
"description": "The vQFX10000 makes it easy for you to try out our physical QFX10000 high-performance data center switch without the wait for physical delivery. Although the virtual version has limited performance relative to the physical switch, it lets you quickly emulate the same features for the control plane of the physical switch, or both its control and data planes.",
diff --git a/gns3server/appliances/juniper-vrr.gns3a b/gns3server/appliances/juniper-vrr.gns3a
index 593194ae..f1892c30 100644
--- a/gns3server/appliances/juniper-vrr.gns3a
+++ b/gns3server/appliances/juniper-vrr.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "2e2b0348-bf5c-43da-823e-aa0a61c0f8fe",
"name": "Juniper vRR",
"category": "router",
"description": "The vRR is a full-featured, carrier-grade virtual route reflector software that extends 15+ years of Juniper Networks edge routing expertise to the virtual realm.",
diff --git a/gns3server/appliances/juniper-vsrx.gns3a b/gns3server/appliances/juniper-vsrx.gns3a
index 356fa421..d78ed8a2 100644
--- a/gns3server/appliances/juniper-vsrx.gns3a
+++ b/gns3server/appliances/juniper-vsrx.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "23b231f5-efb9-4e19-9e4d-f1672d442d78",
"name": "vSRX",
"category": "firewall",
"description": "The vSRX delivers core firewall, networking, advanced security, and automated lifecycle management capabilities for enterprises and service providers. The industry's fastest virtual security platform, the vSRX offers firewall speeds up to 17 Gbps using only two virtual CPUs, providing scalable, secure protection across private, public, and hybrid clouds.\n\nJuniper version 12 can support only 1GB of ram.",
diff --git a/gns3server/appliances/jupyter.gns3a b/gns3server/appliances/jupyter.gns3a
index 3bc584ba..3ba8b88a 100644
--- a/gns3server/appliances/jupyter.gns3a
+++ b/gns3server/appliances/jupyter.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "9436eef5-de64-40f8-9ae4-28d9d2f582ba",
"name": "Jupyter",
"category": "guest",
"description": "The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, machine learning and much more.",
diff --git a/gns3server/appliances/jupyter27.gns3a b/gns3server/appliances/jupyter27.gns3a
index 07ae498b..30ac7a14 100644
--- a/gns3server/appliances/jupyter27.gns3a
+++ b/gns3server/appliances/jupyter27.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "8814bb98-3ae7-4bc3-a3e3-1a4dc1369dbd",
"name": "Jupyter 2.7",
"category": "guest",
"description": "The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, machine learning and much more. This appliance provide python 2.7.",
diff --git a/gns3server/appliances/kali-linux-cli.gns3a b/gns3server/appliances/kali-linux-cli.gns3a
index c94fcdcd..89585cac 100644
--- a/gns3server/appliances/kali-linux-cli.gns3a
+++ b/gns3server/appliances/kali-linux-cli.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "810c0dbf-21ae-478e-9d42-cc3d803064b7",
"name": "Kali Linux CLI",
"category": "guest",
"description": "From the creators of BackTrack comes Kali Linux, the most advanced and versatile penetration testing platform ever created. We have a set of amazing features lined up in our security distribution geared at streamlining the penetration testing experience. This version has no GUI.Include packages:\n* nmap\n* metasploit\n* sqlmap\n* hydra\n* telnet client\n* dnsutils (dig)",
diff --git a/gns3server/appliances/kali-linux.gns3a b/gns3server/appliances/kali-linux.gns3a
index ea215748..c5ad4112 100644
--- a/gns3server/appliances/kali-linux.gns3a
+++ b/gns3server/appliances/kali-linux.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "cb854aa6-379c-4458-8c4c-2164fa9ec98d",
"name": "Kali Linux",
"category": "guest",
"description": "From the creators of BackTrack comes Kali Linux, the most advanced and versatile penetration testing platform ever created. We have a set of amazing features lined up in our security distribution geared at streamlining the penetration testing experience.",
diff --git a/gns3server/appliances/kemp-vlm.gns3a b/gns3server/appliances/kemp-vlm.gns3a
index 15ca8df2..0f02a734 100644
--- a/gns3server/appliances/kemp-vlm.gns3a
+++ b/gns3server/appliances/kemp-vlm.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "da509b39-f0ec-4a63-a88c-ad8e9c712ee3",
"name": "KEMP Free VLM",
"category": "router",
"description": "KEMP Technologies free LoadMaster Application Load Balancer is a fully featured member of our award winning and industry leading Load Balancer family. It can be used without charge in production environments with throughput requirements that don't exceed 20 Mbps, and for services that do not directly generate revenue. It is an ideal choice for low traffic web sites and applications, DevOps testing environments, technical training environments, and for any other deployments that suit your non-commercial needs.",
diff --git a/gns3server/appliances/kerio-connect.gns3a b/gns3server/appliances/kerio-connect.gns3a
index e8002108..d7e9bb0e 100644
--- a/gns3server/appliances/kerio-connect.gns3a
+++ b/gns3server/appliances/kerio-connect.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "3efc41ea-bdb1-4c05-b12b-ef96a75fd63f",
"name": "Kerio Connect",
"category": "guest",
"description": "Kerio Connect makes email, calendars, contacts and task management easy and affordable. With Kerio Connect, you have immediate, secure access to your communications anytime, anywhere, on any device - without complexity or expensive overhead.",
diff --git a/gns3server/appliances/kerio-control.gns3a b/gns3server/appliances/kerio-control.gns3a
index 2f29fb4e..baaf2b39 100644
--- a/gns3server/appliances/kerio-control.gns3a
+++ b/gns3server/appliances/kerio-control.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "dd935ae3-5adb-4316-a963-6e4d8bbeed5f",
"name": "Kerio Control",
"category": "firewall",
"description": "Protect your network from viruses, malware and malicious activity with Kerio Control, the easy-to-administer yet powerful all-in-one security solution.\nKerio Control brings together next-generation firewall capabilities - including a network firewall and router, intrusion detection and prevention (IPS), gateway anti-virus, VPN, and web content and application filtering. These comprehensive capabilities and unmatched deployment flexibility make Kerio Control the ideal choice for small and mid-sized businesses.",
diff --git a/gns3server/appliances/kerio-operator.gns3a b/gns3server/appliances/kerio-operator.gns3a
index 7d4bf307..83d68701 100644
--- a/gns3server/appliances/kerio-operator.gns3a
+++ b/gns3server/appliances/kerio-operator.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "114d380e-302f-456d-b44d-ec47e1d22774",
"name": "Kerio Operator",
"category": "guest",
"description": "Stay connected to your customers and colleagues without being chained to your desk.\nKerio Operator is a VoIP based phone system that provides powerful yet affordable enterprise-class voice and video communication capabilities for small and mid-sized businesses globally.",
diff --git a/gns3server/appliances/loadbalancer_org-va.gns3a b/gns3server/appliances/loadbalancer_org-va.gns3a
index 868aa4db..c8479f65 100644
--- a/gns3server/appliances/loadbalancer_org-va.gns3a
+++ b/gns3server/appliances/loadbalancer_org-va.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "1f197327-9beb-48da-a3fc-f5fb721dc335",
"name": "Loadbalancer.org Enterprise VA",
"category": "router",
"description": "Don't you hate it when companies artificially cripple performance? We just give you two simple choices - Now isn't that a refreshing change?",
diff --git a/gns3server/appliances/macos-install.gns3a b/gns3server/appliances/macos-install.gns3a
index 5f920187..5556b285 100644
--- a/gns3server/appliances/macos-install.gns3a
+++ b/gns3server/appliances/macos-install.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "e250158f-bfb1-4a9c-ab00-bcad9c79eacc",
"name": "macOS",
"category": "guest",
"description": "macOS",
diff --git a/gns3server/appliances/mcjoin.gns3a b/gns3server/appliances/mcjoin.gns3a
index 74515a34..d99ff3ff 100644
--- a/gns3server/appliances/mcjoin.gns3a
+++ b/gns3server/appliances/mcjoin.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "c80f3423-20bf-4a12-b8fd-3eb2c747eabb",
"name": "mcjoin",
"category": "guest",
"description": "mcjoin is a very simple and easy-to-use tool to test IPv4 and IPv6 multicast.",
diff --git a/gns3server/appliances/microcore-linux.gns3a b/gns3server/appliances/microcore-linux.gns3a
index 0b42f6e1..0085a680 100644
--- a/gns3server/appliances/microcore-linux.gns3a
+++ b/gns3server/appliances/microcore-linux.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "361f1e33-f6a5-4e6e-9268-9605053bd059",
"name": "Micro Core Linux",
"category": "guest",
"description": "Micro Core Linux is a smaller variant of Tiny Core without a graphical desktop.\n\nThis is complete Linux system needing few resources to run.",
diff --git a/gns3server/appliances/mikrotik-chr.gns3a b/gns3server/appliances/mikrotik-chr.gns3a
index 707cdfc2..dc534a31 100644
--- a/gns3server/appliances/mikrotik-chr.gns3a
+++ b/gns3server/appliances/mikrotik-chr.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "05512118-2b99-4789-90d3-5135665c3ec5",
"name": "MikroTik CHR",
"category": "router",
"description": "Cloud Hosted Router (CHR) is a RouterOS version meant for running as a virtual machine. It supports x86 64-bit architecture and can be used on most of popular hypervisors such as VMWare, Hyper-V, VirtualBox, KVM and others. CHR has full RouterOS features enabled by default but has a different licensing model than other RouterOS versions.",
diff --git a/gns3server/appliances/mininet.gns3a b/gns3server/appliances/mininet.gns3a
index 50540c20..0a2c209c 100644
--- a/gns3server/appliances/mininet.gns3a
+++ b/gns3server/appliances/mininet.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "1248f9d1-fdaf-4cea-b036-195520b44d28",
"name": "Mininet",
"category": "guest",
"description": "Mininet creates a realistic virtual network, running real kernel, switch and application code, on a single machine (VM, cloud or native), in seconds, with a single command.",
diff --git a/gns3server/appliances/net_toolbox.gns3a b/gns3server/appliances/net_toolbox.gns3a
index af6bdf13..3bcc2a6b 100644
--- a/gns3server/appliances/net_toolbox.gns3a
+++ b/gns3server/appliances/net_toolbox.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "9fa5056a-15a6-4bb0-8b71-c0a6b5cfeea6",
"name": "Toolbox",
"category": "guest",
"description": "This appliance contains server side software for secondary management of network devices:\n- www (nginx) \n- ftp (vsftpd)\n- tftp (tftpd)\n- syslog (rsyslog)\n- dhcp (isc-dhcpd)\n- snmp server (snmpd + snmptrapd)",
diff --git a/gns3server/appliances/netem.gns3a b/gns3server/appliances/netem.gns3a
index 3b17c9c3..85302f39 100644
--- a/gns3server/appliances/netem.gns3a
+++ b/gns3server/appliances/netem.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "4b027aee-8214-4c97-ad8b-89abc67641bd",
"name": "NETem",
"category": "guest",
"description": "NETem emulates a network link, typically a WAN link. It supports bandwidth limitation, delay, jitter and packet loss. All this functionality is already build in the linux kernel, NETem is just a menu system to make the configuration user-friendly.",
diff --git a/gns3server/appliances/network_automation.gns3a b/gns3server/appliances/network_automation.gns3a
index b0607cf6..8d10a494 100644
--- a/gns3server/appliances/network_automation.gns3a
+++ b/gns3server/appliances/network_automation.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a61b580a-99c5-4d77-bc25-61f4c60d214f",
"name": "Network Automation",
"category": "guest",
"description": "This container provides the popular tools used for network automation: Netmiko, NAPALM, Pyntc, and Ansible.",
diff --git a/gns3server/appliances/nokia-vsim.gns3a b/gns3server/appliances/nokia-vsim.gns3a
new file mode 100644
index 00000000..c44de2af
--- /dev/null
+++ b/gns3server/appliances/nokia-vsim.gns3a
@@ -0,0 +1,47 @@
+{
+ "appliance_id": "98525a92-5146-46e9-996c-b6d9dc0a449f",
+ "name": "Nokia vSIM",
+ "category": "router",
+ "description": "The Nokia Virtualized 7750 SR and 7950 XRS Simulator (vSIM) is a Virtualized Network Function (VNF) that simulates the control, management, and forwarding functions of a 7750 SR or 7950 XRS router. The vSIM runs the same Service Router Operating System (SR OS) as 7750 SR and 7950 XRS hardware-based routers and, therefore, has the same feature set and operational behavior as those platforms.",
+ "vendor_name": "Nokia",
+ "vendor_url": "https://www.nokia.com/networks/",
+ "documentation_url": "https://documentation.nokia.com/",
+ "product_name": "Nokia vSIM",
+ "product_url": "https://www.nokia.com/networks/products/virtualized-service-router/",
+ "registry_version": 4,
+ "status": "experimental",
+ "maintainer": "Vinicius Rocha",
+ "maintainer_email": "viniciusatr@gmail.com",
+ "usage": "Login is admin and password is admin. \n\nWe are using one IOM with one MDA 12x100G (w/ breakout).\n\nYou must add your license: file vi cf3:license.txt",
+ "first_port_name": "A/1",
+ "port_name_format": "1/1/{port1}",
+ "qemu": {
+ "adapter_type": "virtio-net-pci",
+ "adapters": 13,
+ "ram": 4096,
+ "cpus": 2,
+ "hda_disk_interface": "virtio",
+ "arch": "x86_64",
+ "console_type": "telnet",
+ "kvm": "require",
+ "options": "-nographic -smbios type=1,product=TIMOS:license-file=cf3:license.txt\\ slot=A\\ chassis=SR-1\\ card=cpm-1\\ mda/1=me12-100gb-qsfp28"
+ },
+ "images": [
+ {
+ "filename": "sros-vsr-21.7.R1.qcow2",
+ "version": "21.7.R1",
+ "md5sum": "7eed38c01350ebaf9c6105e26ce5307e",
+ "filesize": 568655872,
+ "download_url": "https://customer.nokia.com/support/s/",
+ "compression": "zip"
+ }
+ ],
+ "versions": [
+ {
+ "name": "21.7.R1",
+ "images": {
+ "hda_disk_image": "sros-vsr-21.7.R1.qcow2"
+ }
+ }
+ ]
+}
diff --git a/gns3server/appliances/ntopng.gns3a b/gns3server/appliances/ntopng.gns3a
index 6c5b58c6..2f33c3ef 100644
--- a/gns3server/appliances/ntopng.gns3a
+++ b/gns3server/appliances/ntopng.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a8ca42e8-37f0-4bbb-a028-557eb882f909",
"name": "ntopng",
"category": "guest",
"description": "ntopng is the next generation version of the original ntop, a network traffic probe that shows the network usage, similar to what the popular top Unix command does. ntopng is based on libpcap and it has been written in a portable way in order to virtually run on every Unix platform, MacOSX and on Windows as well. ntopng users can use a a web browser to navigate through ntop (that acts as a web server) traffic information and get a dump of the network status. In the latter case, ntopng can be seen as a simple RMON-like agent with an embedded web interface.",
diff --git a/gns3server/appliances/onos.gns3a b/gns3server/appliances/onos.gns3a
index 848dac12..28f7f6ab 100644
--- a/gns3server/appliances/onos.gns3a
+++ b/gns3server/appliances/onos.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a5d624de-9af2-4e7e-b8e1-055df9aaa446",
"name": "Onos",
"category": "multilayer_switch",
"description": "The Open Network Operating System (ONOS) is a software defined networking (SDN) OS for service providers that has scalability, high availability, high performance and abstractions to make it easy to create apps and services. The platform is based on a solid architecture and has quickly matured to be feature rich and production ready. The community has grown to include over 50 partners and collaborators that contribute to all aspects of the project including interesting use cases such as CORD",
diff --git a/gns3server/appliances/op5-monitor.gns3a b/gns3server/appliances/op5-monitor.gns3a
index d6adc3f7..70f97de9 100644
--- a/gns3server/appliances/op5-monitor.gns3a
+++ b/gns3server/appliances/op5-monitor.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "9a1aaa70-b666-4f8a-94ff-239254ca1b8a",
"name": "OP5 Monitor",
"category": "guest",
"description": "Over 200,000 IT staff across medium to large enterprises worldwide are currently using OP5 Monitor as their preferred network monitoring software.\nOP5 Monitor allows you to take control of your IT, enabling your network to be more responsive, more reliable and even faster than ever before. With unparalleled scalability, OP5 Monitor grows as your company grows, so you'll understand why we say this is the last network monitor you'll ever need to purchase.",
diff --git a/gns3server/appliances/open-media-vault.gns3a b/gns3server/appliances/open-media-vault.gns3a
index 6bc5ef04..26c7fbe0 100644
--- a/gns3server/appliances/open-media-vault.gns3a
+++ b/gns3server/appliances/open-media-vault.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "6fe715ad-4c27-4f65-97f7-f8c1d7cd3e0a",
"name": "OpenMediaVault",
"category": "guest",
"description": "openmediavault is the next generation network attached storage (NAS) solution based on Debian Linux. It contains services like SSH, (S)FTP, SMB/CIFS, DAAP media server, RSync, BitTorrent client and many more.",
@@ -7,7 +8,7 @@
"documentation_url": "hhttps://docs.openmediavault.org",
"product_name": "OpenMediaVault",
"product_url": "https://www.openmediavault.org/",
- "registry_version": 3,
+ "registry_version": 4,
"status": "stable",
"maintainer": "Savio D'souza",
"maintainer_email": "savio2002@yahoo.in",
@@ -17,21 +18,29 @@
"adapter_type": "e1000",
"adapters": 1,
"ram": 2048,
- "hda_disk_interface": "ide",
- "hdb_disk_interface": "ide",
+ "hda_disk_interface": "sata",
+ "hdb_disk_interface": "sata",
"arch": "x86_64",
"console_type": "vnc",
"boot_priority": "dc",
"kvm": "require"
},
"images": [
+ {
+ "filename": "openmediavault_5.6.13-amd64.iso",
+ "version": "5.6.13",
+ "md5sum": "f08b41a5111fffca0355d53e26ec47ab",
+ "filesize": 652214272,
+ "download_url": "https://www.openmediavault.org/download.html",
+ "direct_download_url": "https://sourceforge.net/projects/openmediavault/files/5.6.13/openmediavault_5.6.13-amd64.iso/download"
+ },
{
"filename": "openmediavault_5.5.11-amd64.iso",
"version": "5.5.11",
"md5sum": "76baad8e13dd49bee9b4b4a6936b7296",
"filesize": 608174080,
"download_url": "https://www.openmediavault.org/download.html",
- "direct_download_url": "https://sourceforge.net/projects/openmediavault/files/latest/download"
+ "direct_download_url": "https://sourceforge.net/projects/openmediavault/files/5.5.11/openmediavault_5.5.11-amd64.iso/download"
},
{
"filename": "empty30G.qcow2",
@@ -43,6 +52,14 @@
}
],
"versions": [
+ {
+ "name": "5.6.13",
+ "images": {
+ "hda_disk_image": "empty30G.qcow2",
+ "hdb_disk_image": "empty30G.qcow2",
+ "cdrom_image": "openmediavault_5.6.13-amd64.iso"
+ }
+ },
{
"name": "5.5.11",
"images": {
diff --git a/gns3server/appliances/openbsd.gns3a b/gns3server/appliances/openbsd.gns3a
index 87bd0738..d39c956d 100644
--- a/gns3server/appliances/openbsd.gns3a
+++ b/gns3server/appliances/openbsd.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "88903903-8e64-4439-bc4f-a0ed45e29e56",
"name": "OpenBSD",
"category": "guest",
"description": "The OpenBSD project produces a FREE, multi-platform 4.4BSD-based UNIX-like operating system. Our efforts emphasize portability, standardization, correctness, proactive security and integrated cryptography. As an example of the effect OpenBSD has, the popular OpenSSH software comes from OpenBSD.",
diff --git a/gns3server/appliances/opennac.gns3a b/gns3server/appliances/opennac.gns3a
index 37e9e45a..f189c9c4 100644
--- a/gns3server/appliances/opennac.gns3a
+++ b/gns3server/appliances/opennac.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "83a83c12-7265-4761-87f3-e37f2254badb",
"name": "OpenNAC",
"category": "guest",
"description": "openNAC is an opensource Network Access Control for corporate LAN / WAN environments. It enables authentication, authorization and audit policy-based all access to network. It supports diferent network vendors like Cisco, Alcatel, 3Com or Extreme Networks, and different clients like PCs with Windows or Linux, Mac,devices like smartphones and tablets. Based on open source components and self-development It is based on industry standards such as FreeRadius, 802.1x, AD, ldap, ...It is very extensible, new features can be incorporated because it is architectured in plugins. Easily integrated with existing systems Last but not least, It provides value added services such as configuration management, network, backup configurations, Network Discovery and Network Monitoring. Download the OVA, then extract the VMDK (tar -xvf FILE.ova), then convert to qcow2 (qemu-img convert -O qcow2 FILE.vmdk FILE.qcow2).",
diff --git a/gns3server/appliances/opensuse.gns3a b/gns3server/appliances/opensuse.gns3a
index 6abdd916..8c1d8731 100644
--- a/gns3server/appliances/opensuse.gns3a
+++ b/gns3server/appliances/opensuse.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "260d25d8-7cbf-4cc9-9163-7d502fef84b3",
"name": "openSUSE",
"category": "guest",
"description": "openSUSE is a free and Linux-based operating system for PC, Laptop or Server. The openSUSE project is a community program sponsored by Novell. It is a general purpose operating system built on top of the Linux kernel, developed by the community-supported openSUSE Project and sponsored by SUSE and a number of other companies.",
diff --git a/gns3server/appliances/openvswitch-management.gns3a b/gns3server/appliances/openvswitch-management.gns3a
index 398acff7..a9637293 100644
--- a/gns3server/appliances/openvswitch-management.gns3a
+++ b/gns3server/appliances/openvswitch-management.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "1e9ff21e-4de8-4ae1-bde8-ed905ea96838",
"name": "Open vSwitch management",
"category": "multilayer_switch",
"description": "Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. This is a version of the appliance with a management interface on eth0.",
diff --git a/gns3server/appliances/openvswitch.gns3a b/gns3server/appliances/openvswitch.gns3a
index c35b6a68..e792689a 100644
--- a/gns3server/appliances/openvswitch.gns3a
+++ b/gns3server/appliances/openvswitch.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "fa32278f-cefb-4291-b94e-771457bd419f",
"name": "Open vSwitch",
"category": "multilayer_switch",
"description": "Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.",
diff --git a/gns3server/appliances/openwrt-realview.gns3a b/gns3server/appliances/openwrt-realview.gns3a
index 91598813..ee520702 100644
--- a/gns3server/appliances/openwrt-realview.gns3a
+++ b/gns3server/appliances/openwrt-realview.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "c15b0dda-3ac2-4990-9a90-f6d0ead6935b",
"name": "OpenWrt Realview",
"category": "router",
"description": "OpenWrt is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers). Unlike many other distributions for these routers, OpenWrt is built from the ground up to be a full-featured, easily modifiable operating system for your router. In practice, this means that you can have all the features you need with none of the bloat, powered by a Linux kernel that's more recent than most other distributions.\n\nThe realview platform is meant for use with QEMU for emulating an ARM system.",
diff --git a/gns3server/appliances/openwrt.gns3a b/gns3server/appliances/openwrt.gns3a
index a8b8fca8..1007d903 100644
--- a/gns3server/appliances/openwrt.gns3a
+++ b/gns3server/appliances/openwrt.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "5a6f68c9-62ac-4b80-80cb-959398fb2c03",
"name": "OpenWrt",
"category": "router",
"description": "OpenWrt is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers). Unlike many other distributions for these routers, OpenWrt is built from the ground up to be a full-featured, easily modifiable operating system for your router. In practice, this means that you can have all the features you need with none of the bloat, powered by a Linux kernel that's more recent than most other distributions.",
@@ -22,6 +23,24 @@
"kvm": "allow"
},
"images": [
+ {
+ "filename": "openwrt-21.02.0-x86-64-generic-ext4-combined.img",
+ "version": "21.02.0",
+ "md5sum": "1ba2a5c5c05e592c36a469a8ecd3bcf5",
+ "filesize": 126353408,
+ "download_url": "https://downloads.openwrt.org/releases/21.02.0/targets/x86/64/",
+ "direct_download_url": "https://downloads.openwrt.org/releases/21.02.0/targets/x86/64/openwrt-21.02.0-x86-64-generic-ext4-combined.img.gz",
+ "compression": "gzip"
+ },
+ {
+ "filename": "openwrt-19.07.8-x86-64-combined-ext4.img",
+ "version": "19.07.8",
+ "md5sum": "a9d9776a96968a2042484330f285cae3",
+ "filesize": 285736960,
+ "download_url": "https://downloads.openwrt.org/releases/19.07.8/targets/x86/64/",
+ "direct_download_url": "https://downloads.openwrt.org/releases/19.07.8/targets/x86/64/openwrt-19.07.8-x86-64-combined-ext4.img",
+ "compression": "gzip"
+ },
{
"filename": "openwrt-19.07.7-x86-64-combined-ext4.img",
"version": "19.07.7",
@@ -168,6 +187,18 @@
}
],
"versions": [
+ {
+ "name": "21.02.0",
+ "images": {
+ "hda_disk_image": "openwrt-21.02.0-x86-64-generic-ext4-combined.img"
+ }
+ },
+ {
+ "name": "19.07.8",
+ "images": {
+ "hda_disk_image": "openwrt-19.07.8-x86-64-combined-ext4.img"
+ }
+ },
{
"name": "19.07.7",
"images": {
diff --git a/gns3server/appliances/opnsense.gns3a b/gns3server/appliances/opnsense.gns3a
index b5039076..9da90e76 100644
--- a/gns3server/appliances/opnsense.gns3a
+++ b/gns3server/appliances/opnsense.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "b103d66a-dd2a-4cf5-8e16-8a96e1660f70",
"name": "OPNsense",
"category": "firewall",
"description": "OPNsense is an open source, easy-to-use and easy-to-build FreeBSD based firewall and routing platform. OPNsense includes most of the features available in expensive commercial firewalls, and more in many cases. It brings the rich feature set of commercial offerings with the benefits of open and verifiable sources.\n\nOPNsense started as a fork of pfSense\u00ae and m0n0wall in 2014, with its first official release in January 2015. The project has evolved very quickly while still retaining familiar aspects of both m0n0wall and pfSense. A strong focus on security and code quality drives the development of the project.",
diff --git a/gns3server/appliances/ostinato.gns3a b/gns3server/appliances/ostinato.gns3a
index 7e72c1e9..585b67ef 100644
--- a/gns3server/appliances/ostinato.gns3a
+++ b/gns3server/appliances/ostinato.gns3a
@@ -1,24 +1,28 @@
{
+ "appliance_id": "915a93b4-b78f-47b4-9a6e-cadc25d55c0a",
"name": "Ostinato",
"category": "guest",
- "description": "Ostinato is an open-source, cross-platform network packet crafter/traffic generator and analyzer with a friendly GUI. Craft and send packets of several streams with different protocols at different rates.",
+ "description": "Packet crafter and traffic generator for network engineers",
"vendor_name": "Ostinato",
- "vendor_url": "http://ostinato.org/",
- "documentation_url": "http://ostinato.org/docs.html",
+ "vendor_url": "https://ostinato.org/",
+ "documentation_url": "https://ostinato.org/docs",
"product_name": "Ostinato",
- "product_url": "http://ostinato.org/",
- "registry_version": 3,
- "status": "experimental",
- "maintainer": "Bernhard Ehlers",
- "maintainer_email": "be@bernhard-ehlers.de",
- "usage": "Use interfaces starting with eth1 as traffic interfaces, eth0 is only for the (optional) management of the server/drone.",
- "symbol": "ostinato-3d-icon.svg",
- "port_name_format": "eth{0}",
+ "product_url": "https://ostinato.org/",
+ "registry_version": 4,
+ "status": "stable",
+ "availability": "service-contract",
+ "maintainer": "Srivats P",
+ "maintainer_email": "support@ostinato.org",
+ "symbol": ":/symbols/affinity/circle/gray/cog.svg",
+ "first_port_name": "eth0/mgmt",
+ "port_name_format": "eth{port1}",
+ "linked_clone": true,
"qemu": {
"adapter_type": "e1000",
"adapters": 4,
"ram": 256,
- "hda_disk_interface": "ide",
+ "cpus": 2,
+ "hda_disk_interface": "sata",
"arch": "i386",
"console_type": "vnc",
"kvm": "allow",
@@ -26,33 +30,18 @@
},
"images": [
{
- "filename": "ostinato-0.9-1.qcow2",
- "version": "0.9",
- "md5sum": "00b4856ec9fffbcbcab7a8f757355d69",
- "filesize": 101646336,
- "download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/index.html",
- "direct_download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/ostinato-0.9-1.qcow2"
- },
- {
- "filename": "ostinato-0.8-1.qcow2",
- "version": "0.8",
- "md5sum": "12e990ba695103cfac82f8771b8015d4",
- "filesize": 57344000,
- "download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/index.html",
- "direct_download_url": "http://www.bernhard-ehlers.de/projects/ostinato4gns3/ostinato-0.8-1.qcow2"
+ "filename": "ostinatostd-1.1-1.qcow2",
+ "version": "1.1",
+ "md5sum": "aa027e83cefea1c38d0102eb2f28956e",
+ "filesize": 134217728,
+ "download_url": "https://ostinato.org/pricing/gns3"
}
],
"versions": [
{
- "name": "0.9",
+ "name": "1.1",
"images": {
- "hda_disk_image": "ostinato-0.9-1.qcow2"
- }
- },
- {
- "name": "0.8",
- "images": {
- "hda_disk_image": "ostinato-0.8-1.qcow2"
+ "hda_disk_image": "ostinatostd-1.1-1.qcow2"
}
}
]
diff --git a/gns3server/appliances/packetfence-zen.gns3a b/gns3server/appliances/packetfence-zen.gns3a
index 55028ad3..6a6a8dea 100644
--- a/gns3server/appliances/packetfence-zen.gns3a
+++ b/gns3server/appliances/packetfence-zen.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "c5b386b4-f722-432c-a36e-d124ff551748",
"name": "PacketFence ZEN",
"category": "guest",
"description": "PacketFence is a fully supported, trusted, Free and Open Source network access control (NAC) solution. Boasting an impressive feature set including a captive-portal for registration and remediation, centralized wired and wireless management, 802.1X support, layer-2 isolation of problematic devices, integration with the Snort IDS and the Nessus vulnerability scanner; PacketFence can be used to effectively secure networks - from small to very large heterogeneous networks.",
diff --git a/gns3server/appliances/pan-vm-fw.gns3a b/gns3server/appliances/pan-vm-fw.gns3a
index a0bb01d5..25f8725e 100644
--- a/gns3server/appliances/pan-vm-fw.gns3a
+++ b/gns3server/appliances/pan-vm-fw.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "18c4b920-e467-46c3-a74d-b9e0eed1891f",
"name": "PA-VM",
"category": "firewall",
"description": "The VM-Series combines next-generation firewall security and advanced threat prevention to protect your virtualized environments from advanced cyberthreats. The VM-Series natively analyzes all traffic in a single pass to determine the application identity, the content within, and the user identity.",
diff --git a/gns3server/appliances/parrot-os.gns3a b/gns3server/appliances/parrot-os.gns3a
index f2347c80..e9270803 100644
--- a/gns3server/appliances/parrot-os.gns3a
+++ b/gns3server/appliances/parrot-os.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "9660509e-ae0c-4c70-a4bc-dff156058924",
"name": "ParrotOS",
"category": "guest",
"description": " Parrot is a GNU/Linux distribution based on Debian Testing and designed with Security, Development and Privacy in mind. It includes a full portable laboratory for security and digital forensics experts, but it also includes all you need to develop your own software or protect your privacy while surfing the net.",
diff --git a/gns3server/appliances/pfsense.gns3a b/gns3server/appliances/pfsense.gns3a
index 329f2a24..bead2dc7 100644
--- a/gns3server/appliances/pfsense.gns3a
+++ b/gns3server/appliances/pfsense.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "f7792111-df9a-42eb-bbac-b798495d68f3",
"name": "pfSense",
"category": "firewall",
"description": "The pfSense project is a free network firewall distribution, based on the FreeBSD operating system with a custom kernel and including third party free software packages for additional functionality. pfSense software, with the help of the package system, is able to provide the same functionality or more of common commercial firewalls, without any of the artificial limitations. It has successfully replaced every big name commercial firewall you can imagine in numerous installations around the world, including Check Point, Cisco PIX, Cisco ASA, Juniper, Sonicwall, Netgear, Watchguard, Astaro, and more.",
diff --git a/gns3server/appliances/proxmox-mg.gns3a b/gns3server/appliances/proxmox-mg.gns3a
index b1edf03b..588073da 100644
--- a/gns3server/appliances/proxmox-mg.gns3a
+++ b/gns3server/appliances/proxmox-mg.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "577bdb36-4f56-421a-b716-52fe8df5699d",
"name": "Proxmox MG",
"category": "firewall",
"description": "To ensure efficient email communication and business continuity, IT professionals depend on reliable spam and virus blocking software. With Proxmox Mail Gateway you get the job done.\n\nProxmox Mail Gateway helps you protect your business against all email threats like spam, viruses, phishing and trojans at the moment they emerge. The flexible architecture combined with the userfriendly, web-based management make it simple for you to control all incoming and outgoing emails. You maintain a professional email workflow and gain high business reputation as well as customer satisfaction.",
diff --git a/gns3server/appliances/puppy-linux.gns3a b/gns3server/appliances/puppy-linux.gns3a
index a0d6a435..e6bfca79 100644
--- a/gns3server/appliances/puppy-linux.gns3a
+++ b/gns3server/appliances/puppy-linux.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "3c8c2c23-0f14-4dea-9e61-72afcfe1856c",
"name": "Puppy Linux",
"category": "guest",
"description": "Puppy Linux is a unique family of Linux distributions meant for the home-user computers. It was originally created by Barry Kauler in 2003.",
diff --git a/gns3server/appliances/python-go-perl-php.gns3a b/gns3server/appliances/python-go-perl-php.gns3a
index 0e229881..6ab1298f 100644
--- a/gns3server/appliances/python-go-perl-php.gns3a
+++ b/gns3server/appliances/python-go-perl-php.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "47ca3e1f-5a35-4631-b75d-010bd9452ca8",
"name": "Python, Go, Perl, PHP",
"category": "guest",
"description": "Container with integrated Python 2 & 3, Perl, PHP, and PHP7.0 interpreters, and a Go compiler.",
diff --git a/gns3server/appliances/raspian.gns3a b/gns3server/appliances/raspian.gns3a
index b887d786..e3973693 100644
--- a/gns3server/appliances/raspian.gns3a
+++ b/gns3server/appliances/raspian.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "597a01de-4b06-4f57-bd95-8c2e53f7dad6",
"name": "Raspian",
"category": "guest",
"description": "Raspberry Pi Desktop comes pre-installed with plenty of software for education, programming and general use; including Python, Scratch, Sonic Pi, Java, and more. Appliance created to demonstrate new_appliance.py - read more at https://nextpertise.net.",
diff --git a/gns3server/appliances/rhel.gns3a b/gns3server/appliances/rhel.gns3a
index 22b3ab72..82b1e444 100644
--- a/gns3server/appliances/rhel.gns3a
+++ b/gns3server/appliances/rhel.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "0c8708a6-ff48-489b-8e61-4c1b06c300e7",
"name": "RHEL",
"category": "guest",
"description": "Red Hat Enterprise Linux Server provides core operating system functions and capabilities for application infrastructure.",
diff --git a/gns3server/appliances/riverbed-steelhead-cx.gns3a b/gns3server/appliances/riverbed-steelhead-cx.gns3a
deleted file mode 100644
index b17c6c0d..00000000
--- a/gns3server/appliances/riverbed-steelhead-cx.gns3a
+++ /dev/null
@@ -1,50 +0,0 @@
-{
- "name": "SteelHead CX 555V",
- "category": "guest",
- "description": "Riverbed SteelHead delivers not only best-in-class optimization - but essential visibility and control as companies transition to the Hybrid WAN. SteelHead CX for Virtual is available as a virtual solution on most major hypervisors including VMware vSphere, Microsoft Hyper-V and KVM. It accelerates the performance of all applications including on-premises, cloud, and SaaS across the hybrid enterprise for organizations that want to deliver the best end user experience - while leveraging the scalability and cost benefits of virtualization.\n\nSteelHead CX for Virtual uniquely delivers the best application performance along with application, network and end user visibility, and simplified control management of users, applications and networks based on business requirements and decisions.",
- "vendor_name": "Riverbed Technology",
- "vendor_url": "http://www.riverbed.com",
- "documentation_url": "https://support.riverbed.com/content/support/software/steelhead/cx-appliance.html",
- "product_name": "SteelHead CX 555V",
- "registry_version": 3,
- "status": "stable",
- "maintainer": "GNS3 Team",
- "maintainer_email": "developers@gns3.net",
- "usage": "You don't need to run the installer script when using GNS3 VM. Uncompress the downloaded archive using this command: tar xzSf \nDefault credentials: admin / password",
- "qemu": {
- "adapter_type": "virtio-net-pci",
- "adapters": 4,
- "ram": 2048,
- "hda_disk_interface": "virtio",
- "hdb_disk_interface": "virtio",
- "arch": "x86_64",
- "console_type": "telnet",
- "kvm": "require"
- },
- "images": [
- {
- "filename": "mgmt-9.2.0.img",
- "version": "9.2.0",
- "md5sum": "ca20a76b2556c0cd313d0b0de528e94d",
- "filesize": 2555772928,
- "download_url": "http://www.riverbed.com/products/steelhead/Free-90-day-Evaluation-SteelHead-CX-Virtual-Edition.html"
- },
- {
- "filename": "empty100G.qcow2",
- "version": "1.0",
- "md5sum": "1e6409a4523ada212dea2ebc50e50a65",
- "filesize": 198656,
- "download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/",
- "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download"
- }
- ],
- "versions": [
- {
- "name": "9.2.0",
- "images": {
- "hda_disk_image": "mgmt-9.2.0.img",
- "hdb_disk_image": "empty100G.qcow2"
- }
- }
- ]
-}
diff --git a/gns3server/appliances/riverbed-steelhead-ng-vcx.gns3a b/gns3server/appliances/riverbed-steelhead-ng-vcx.gns3a
new file mode 100644
index 00000000..98413969
--- /dev/null
+++ b/gns3server/appliances/riverbed-steelhead-ng-vcx.gns3a
@@ -0,0 +1,68 @@
+{
+ "appliance_id": "c21f6df8-64ab-4e24-921b-ec7f889ce32a",
+ "name": "SteelHead",
+ "category": "guest",
+ "description": "SteelHead is the Riverbed Accelerator",
+ "vendor_name": "Riverbed Technology",
+ "vendor_url": "http://www.riverbed.com",
+ "documentation_url": "https://github.com/riverbed/Riverbed-Community-Toolkit/tree/master/SteelHead/GNS3",
+ "product_name": "SteelHead",
+ "product_url": "https://support.riverbed.com/content/support/software/steelhead/cx-appliance.html",
+ "registry_version": 6,
+ "status": "stable",
+ "maintainer": "Riverbed Community",
+ "maintainer_email": "community@riverbed.com",
+ "usage": "Download the KVM image Next Generation Virtual SteelHead VCX Software Image (KVM) from https://support.riverbed.com/content/support/software/steelhead/cx-appliance.html\n Uncompress the .tgz archive using this command: tar xzSf \nDefault credentials: admin / password",
+ "symbol": "steelhead-vcx.png",
+ "first_port_name": "PRI",
+ "qemu": {
+ "adapter_type": "virtio-net-pci",
+ "adapters": 4,
+ "custom_adapters": [
+ {
+ "adapter_number": 1,
+ "port_name": "AUX"
+ },
+ {
+ "adapter_number": 2,
+ "port_name": "LAN0_0"
+ },
+ {
+ "adapter_number": 3,
+ "port_name": "WAN0_0"
+ }
+ ],
+ "ram": 2048,
+ "hda_disk_interface": "virtio",
+ "hdb_disk_interface": "virtio",
+ "arch": "x86_64",
+ "console_type": "telnet",
+ "kvm": "require"
+ },
+ "images": [
+ {
+ "filename": "mgmt.qcow2",
+ "version": "9.12.0",
+ "md5sum": "0f45d7cfb75b5e7e915dd37136411580",
+ "filesize": 2381840384,
+ "download_url": "https://support.riverbed.com/content/support/software/steelhead/cx-appliance.html#software-alert"
+ },
+ {
+ "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"
+ }
+ ],
+ "versions": [
+ {
+ "name": "9.12.0",
+ "images": {
+ "hda_disk_image": "mgmt.qcow2",
+ "hdb_disk_image": "empty100G.qcow2"
+ }
+ }
+ ]
+}
diff --git a/gns3server/appliances/rockylinux.gns3a b/gns3server/appliances/rockylinux.gns3a
index 789918d3..0f19236c 100644
--- a/gns3server/appliances/rockylinux.gns3a
+++ b/gns3server/appliances/rockylinux.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "3c38885f-71c3-4d9c-976c-cf5515b1c875",
"name": "RockyLinux",
"category": "guest",
"description": "Rocky Linux is a community enterprise operating system designed to be 100% bug-for-bug compatible with Red Hat Enterprise Linux (RHEL).",
diff --git a/gns3server/appliances/security-onion.gns3a b/gns3server/appliances/security-onion.gns3a
index 30130e39..abaf5003 100644
--- a/gns3server/appliances/security-onion.gns3a
+++ b/gns3server/appliances/security-onion.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "8bf76d21-7a7b-4708-a415-5a7ace42db3f",
"name": "Security Onion",
"category": "guest",
"description": "Security Onion is a Linux distro for intrusion detection, network security monitoring, and log management. It's based on Ubuntu and contains Snort, Suricata, Bro, OSSEC, Sguil, Squert, ELSA, Xplico, NetworkMiner, and many other security tools. The easy-to-use Setup wizard allows you to build an army of distributed sensors for your enterprise in minutes!",
diff --git a/gns3server/appliances/smoothwall.gns3a b/gns3server/appliances/smoothwall.gns3a
index 3f93db11..987cd791 100644
--- a/gns3server/appliances/smoothwall.gns3a
+++ b/gns3server/appliances/smoothwall.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "0be28230-875d-4d61-8cd8-43ed66269535",
"name": "Smoothwall Express",
"category": "firewall",
"description": "A Free firewall that includes its own security-hardened GNU/Linux operating system and an easy-to-use web interface.",
diff --git a/gns3server/appliances/sophos-iview.gns3a b/gns3server/appliances/sophos-iview.gns3a
index 7debb64e..28d131b1 100644
--- a/gns3server/appliances/sophos-iview.gns3a
+++ b/gns3server/appliances/sophos-iview.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "270475da-094f-4479-8dd4-f2b9cb7a3949",
"name": "Sophos iView",
"category": "guest",
"description": "Monitoring a distributed network across multiple locations can be a challenge. That's where Sophos iView can help. It provides you with an intelligent, uninterrupted view of your network from a single pane of glass. If you have multiple appliances, need consolidated reporting, or could just use help with log management or compliance, Sophos iView is the ideal solution.",
diff --git a/gns3server/appliances/sophos-utm.gns3a b/gns3server/appliances/sophos-utm.gns3a
index 5195f361..6bbc6cff 100644
--- a/gns3server/appliances/sophos-utm.gns3a
+++ b/gns3server/appliances/sophos-utm.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "d297f2a0-f468-4c4d-a501-a065436712a1",
"name": "Sophos UTM Home Edition",
"category": "firewall",
"description": "Sophos Free Home Use Firewall is a fully equipped software version of the Sophos UTM firewall, available at no cost for home users - no strings attached. It features full Network, Web, Mail and Web Application Security with VPN functionality and protects up to 50 IP addresses. The Sophos UTM Free Home Use firewall contains its own operating system and will overwrite all data on the computer during the installation process. Therefore, a separate, dedicated computer or VM is needed, which will change into a fully functional security appliance.",
diff --git a/gns3server/appliances/sophos-xg.gns3a b/gns3server/appliances/sophos-xg.gns3a
index cefeb5da..24f94f88 100644
--- a/gns3server/appliances/sophos-xg.gns3a
+++ b/gns3server/appliances/sophos-xg.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "2370a587-20e7-468e-ace9-7bd61063aff4",
"name": "Sophos XG Firewall",
"category": "firewall",
"description": "Sophos XG Firewall delivers the ultimate enterprise firewall performance, security, and control.\n\nFastpath packet optimization technology with up to 140Gbps throughput\nRevolutionary Security Heartbeat\u2122 for improved Advanced Threat Protection (ATP) and response\nPatented Layer-8 user identity control and visibility\nUnified App, Web, QoS, and IPS Policy simplifies management\nApp risk factor and user threat quotient monitors risk levels",
diff --git a/gns3server/appliances/stonework.gns3a b/gns3server/appliances/stonework.gns3a
index ae1d9644..1b103225 100644
--- a/gns3server/appliances/stonework.gns3a
+++ b/gns3server/appliances/stonework.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a8897d1f-5ab1-4075-b538-0acdb6785a07",
"name": "StoneWork",
"category": "router",
"description": "StoneWork is VPP and Ligato based routing platform",
diff --git a/gns3server/appliances/tacacs-gui.gns3a b/gns3server/appliances/tacacs-gui.gns3a
index 1dcbe48c..3738523e 100644
--- a/gns3server/appliances/tacacs-gui.gns3a
+++ b/gns3server/appliances/tacacs-gui.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "4e0796b3-2ce5-42a8-a1f2-e1f4beea02e1",
"name": "TacacsGUI",
"category": "guest",
"description": "TacacsGUI Free Access Control Server for Your Network Devices. GUI for powerful daemon. The project of Alexey Mochalin, based on tacacs daemon by Marc Huber",
diff --git a/gns3server/appliances/tinycore-linux.gns3a b/gns3server/appliances/tinycore-linux.gns3a
index 17e4825b..ef1e23aa 100644
--- a/gns3server/appliances/tinycore-linux.gns3a
+++ b/gns3server/appliances/tinycore-linux.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "ed6b9f98-7de2-4d61-a3ed-ad4c3e323ace",
"name": "Tiny Core Linux",
"category": "guest",
"description": "Core Linux is a smaller variant of Tiny Core without a graphical desktop.\n\nIt provides a complete Linux system using only a few MiB.",
diff --git a/gns3server/appliances/trendmicro-imsva.gns3a b/gns3server/appliances/trendmicro-imsva.gns3a
index 4991b1bc..6520be66 100644
--- a/gns3server/appliances/trendmicro-imsva.gns3a
+++ b/gns3server/appliances/trendmicro-imsva.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "16ddaaaf-575e-4baa-bcee-b5affd74bca0",
"name": "IMS VA",
"category": "firewall",
"description": "Trend Micro InterScan Messaging Security stops email threats in the cloud with global threat intelligence, protects your data with data loss prevention and encryption, and identifies targeted email attacks,ransomware, and APTs as part of the Trend Micro Network Defense Solution. The hybrid SaaS deployment combines the privacy and control of an on-premises virtual appliance with the proactive protection of a cloud-based pre-filter service. It's the enterprise-level protection you need with the highest spam and phishing detection rates-consistently #1 in quarterly Opus One competitive tests since 2011.",
diff --git a/gns3server/appliances/trendmicro-iwsva.gns3a b/gns3server/appliances/trendmicro-iwsva.gns3a
index 13fd2108..17bd1161 100644
--- a/gns3server/appliances/trendmicro-iwsva.gns3a
+++ b/gns3server/appliances/trendmicro-iwsva.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "8a0e304f-b6fe-4040-8c51-4e2d1310ff71",
"name": "IWS VA",
"category": "firewall",
"description": "Trend Micro InterScan Web Security Virtual Appliance is a secure web gateway that combines application control with zero-day exploit detection, advanced anti-malware and ransomware scanning, real-time web reputation, and flexible URL filtering to provide superior Internet threat protection.",
diff --git a/gns3server/appliances/turnkey-wordpress.gns3a b/gns3server/appliances/turnkey-wordpress.gns3a
index 978f49fb..377b6bd4 100644
--- a/gns3server/appliances/turnkey-wordpress.gns3a
+++ b/gns3server/appliances/turnkey-wordpress.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "130cb709-b000-471c-afe6-11cbaaed4bbc",
"name": "WordPress",
"category": "guest",
"description": "WordPress is a state-of-the-art publishing platform with a focus on aesthetics, web standards, and usability. It is one of the worlds most popular blog publishing applications, includes tons of powerful core functionality, extendable via literally thousands of plugins, and supports full theming. This appliance includes all the standard features in TurnKey Core too.",
diff --git a/gns3server/appliances/ubuntu-cloud.gns3a b/gns3server/appliances/ubuntu-cloud.gns3a
index 4fbc7ae2..c31af598 100644
--- a/gns3server/appliances/ubuntu-cloud.gns3a
+++ b/gns3server/appliances/ubuntu-cloud.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "46322c6c-10ba-4c6c-823c-12b3ff8b6939",
"name": "Ubuntu Cloud Guest",
"category": "guest",
"description": "The term 'Ubuntu Cloud Guest' refers to the Official Ubuntu images that are available at http://cloud-images.ubuntu.com . These images are built by Canonical. They are then registered on EC2, and compressed tarfiles are made also available for download. For using those images on a public cloud such as Amazon EC2, you simply choose an image and launch it. To use those images on a private cloud, or to run the image on a local hypervisor (such as KVM) you would need to download those images and either publish them to your private cloud, or launch them directly on a hypervisor. The following sections explain in more details how to perform each of those actions",
diff --git a/gns3server/appliances/ubuntu-docker.gns3a b/gns3server/appliances/ubuntu-docker.gns3a
index 9a9bbc20..61d218e0 100644
--- a/gns3server/appliances/ubuntu-docker.gns3a
+++ b/gns3server/appliances/ubuntu-docker.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "da783400-a388-4cb2-8299-f916e3a1cc10",
"name": "Ubuntu Docker Guest",
"category": "guest",
"description": "Ubuntu is a Debian-based Linux operating system, with Unity as its default desktop environment. It is based on free software and named after the Southern African philosophy of ubuntu (literally, \"human-ness\"), which often is translated as \"humanity towards others\" or \"the belief in a universal bond of sharing that connects all humanity\".",
diff --git a/gns3server/appliances/ubuntu-gui.gns3a b/gns3server/appliances/ubuntu-gui.gns3a
index c551da7c..5d36b2a1 100644
--- a/gns3server/appliances/ubuntu-gui.gns3a
+++ b/gns3server/appliances/ubuntu-gui.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "72623124-94a5-4911-b818-d606fb37bdf0",
"name": "Ubuntu Desktop Guest",
"category": "guest",
"description": "Ubuntu is a full-featured Linux operating system which is based on Debian distribution and freely available with both community and professional support, it comes with Unity as its default desktop environment. There are other flavors of Ubuntu available with other desktops as default like Ubuntu Gnome, Lubuntu, Xubuntu, and so on. A tightly-integrated selection of excellent applications is included, and an incredible variety of add-on software is just a few clicks away. A default installation of Ubuntu contains a wide range of software that includes LibreOffice, Firefox, Empathy, Transmission, etc.",
diff --git a/gns3server/appliances/ubuntu-server.gns3a b/gns3server/appliances/ubuntu-server.gns3a
index 5013a2dc..13cabbed 100644
--- a/gns3server/appliances/ubuntu-server.gns3a
+++ b/gns3server/appliances/ubuntu-server.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "d2a23e69-9e92-4c3f-83c8-8caa1aa58ece",
"name": "Ubuntu Server",
"category": "guest",
"description": "This is a custom Ubuntu server which comes with Canonical security updates, Xorg and Telnetd",
diff --git a/gns3server/appliances/untangle.gns3a b/gns3server/appliances/untangle.gns3a
index c17de990..38f6b1d1 100644
--- a/gns3server/appliances/untangle.gns3a
+++ b/gns3server/appliances/untangle.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "7f1e028f-0e1d-490c-974a-cadbe3402a02",
"name": "Untangle NG",
"category": "firewall",
"description": "Untangle's NG Firewall enables you to quickly and easily create the network policies that deliver the perfect balance between security and productivity. Untangle combines Unified Threat Management (UTM)-to address all of the key network threats-with policy management tools that enable you to define access and control by individuals, groups or company-wide. And with industry-leading reports, you'll have complete visibility into and control over everything that's happening on your network.",
diff --git a/gns3server/appliances/viptela-edge-genericx86-64.gns3a b/gns3server/appliances/viptela-edge-genericx86-64.gns3a
index a79151d1..34589774 100644
--- a/gns3server/appliances/viptela-edge-genericx86-64.gns3a
+++ b/gns3server/appliances/viptela-edge-genericx86-64.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "939594b1-7d88-4351-925e-5623bdc401ff",
"name": "vEdgeCloud",
"category": "router",
"description": "vEdgeCloud",
diff --git a/gns3server/appliances/viptela-smart-genericx86-64.gns3a b/gns3server/appliances/viptela-smart-genericx86-64.gns3a
index 8e3999be..040cd6f4 100644
--- a/gns3server/appliances/viptela-smart-genericx86-64.gns3a
+++ b/gns3server/appliances/viptela-smart-genericx86-64.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "cd7469ea-f082-4fba-894f-e420012de9b8",
"name": "vSmart",
"category": "router",
"description": "vSmart",
diff --git a/gns3server/appliances/viptela-vmanage-genericx86-64.gns3a b/gns3server/appliances/viptela-vmanage-genericx86-64.gns3a
index 4f7b9ef6..ad94b338 100644
--- a/gns3server/appliances/viptela-vmanage-genericx86-64.gns3a
+++ b/gns3server/appliances/viptela-vmanage-genericx86-64.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "5e6984d9-180a-41db-b822-a9d38d5cd58a",
"name": "vManage",
"category": "router",
"description": "vManage",
diff --git a/gns3server/appliances/vpp.gns3a b/gns3server/appliances/vpp.gns3a
index 95b8682a..c18af566 100644
--- a/gns3server/appliances/vpp.gns3a
+++ b/gns3server/appliances/vpp.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "f9a951fe-cafd-4b31-8c83-daef4709943e",
"name": "VPP",
"category": "router",
"description": "Vector Packet Processing (VPP) platform",
diff --git a/gns3server/appliances/vrin.gns3a b/gns3server/appliances/vrin.gns3a
index da77e45f..830e7ea7 100644
--- a/gns3server/appliances/vrin.gns3a
+++ b/gns3server/appliances/vrin.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "b91a011d-e975-45b4-9d7a-b0d296f8541f",
"name": "vRIN",
"category": "guest",
"description": "vRIN is a VM appliance capable to inject high number of routes into a network. It was tested on GNS3 topologies using VirtualBox and Qemu with up to 1M BGP routes. Runs Quagga. Supported protocols: BGP (IPv4/6), OSPF, OSPFv3, RIP v2, RIPng",
diff --git a/gns3server/appliances/vyos.gns3a b/gns3server/appliances/vyos.gns3a
index aba9a41d..7494c070 100644
--- a/gns3server/appliances/vyos.gns3a
+++ b/gns3server/appliances/vyos.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "f82b74c4-0f30-456f-a582-63daca528502",
"name": "VyOS",
"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. VyOS has a subscription LTS version and a community rolling release. The latest version in this appliance is the monthly snapshot of the rolling release track.",
@@ -11,7 +12,7 @@
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
- "usage": "Default username/password is vyos/vyos.\n\nAt first boot of versions 1.1.x/1.2.x the router will start from the cdrom. Login and then type \"install image\" and follow the instructions.",
+ "usage": "Default username/password is vyos/vyos.\n\nAt first boot the router will start from the cdrom. Login and then type \"install image\" and follow the instructions.",
"symbol": "vyos.svg",
"port_name_format": "eth{0}",
"qemu": {
@@ -26,12 +27,12 @@
},
"images": [
{
- "filename": "vyos-1.3.0-rc5-amd64.qcow2",
- "version": "1.3.0-rc5",
- "md5sum": "dd704f59afc0fccdf601cc750bf2c438",
- "filesize": 361955328,
- "download_url": "https://www.b-ehlers.de/GNS3/images/",
- "direct_download_url": "https://www.b-ehlers.de/GNS3/images/vyos-1.3.0-rc5-amd64.qcow2"
+ "filename": "vyos-1.3.0-epa1-amd64.iso",
+ "version": "1.3.0-epa1",
+ "md5sum": "a2aaa5bd3bc5827909d07a18a9de80a7",
+ "filesize": 331350016,
+ "download_url": "https://vyos.net/get/snapshots/",
+ "direct_download_url": "https://s3.amazonaws.com/s3-us.vyos.io/snapshot/vyos-1.3.0-epa1/generic-iso/vyos-1.3.0-epa1-amd64.iso"
},
{
"filename": "vyos-1.2.8-amd64.iso",
@@ -66,9 +67,10 @@
],
"versions": [
{
- "name": "1.3.0-rc5",
+ "name": "1.3.0-epa1",
"images": {
- "hda_disk_image": "vyos-1.3.0-rc5-amd64.qcow2"
+ "hda_disk_image": "empty8G.qcow2",
+ "cdrom_image": "vyos-1.3.0-epa1-amd64.iso"
}
},
{
diff --git a/gns3server/appliances/watchguard-fireboxv.gns3a b/gns3server/appliances/watchguard-fireboxv.gns3a
index 929852c0..c6ddd2f2 100644
--- a/gns3server/appliances/watchguard-fireboxv.gns3a
+++ b/gns3server/appliances/watchguard-fireboxv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "dee2b360-e1f4-487f-bd2f-2296f7167543",
"name": "WatchGuard",
"category": "firewall",
"description": "Organizations of all sizes are turning to virtualization to reduce costs and increase the efficiency, availability, and flexibility of their IT resources. But virtualization comes at a cost. Virtual environments are complex to manage and vulnerable to security threats. IT must be prepared. Now applications can be secured, resources can be maximized and your IT department can reap the rewards of having a single, unified management system - without a security risk in sight. WatchGuard FireboxV brings best-in-class network security to the world of virtualization. With real-time monitoring, multi-WAN support and scalable solutions to fit any-sized business, your virtual environments can be just as secure as your physical one.",
diff --git a/gns3server/appliances/watchguard-xtmv.gns3a b/gns3server/appliances/watchguard-xtmv.gns3a
index e0d6d3ef..62451a59 100644
--- a/gns3server/appliances/watchguard-xtmv.gns3a
+++ b/gns3server/appliances/watchguard-xtmv.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "816cedad-04ae-46e5-840d-20c2a50b6ba5",
"name": "WatchGuard",
"category": "firewall",
"description": "Organizations of all sizes are turning to virtualization to reduce costs and increase the efficiency, availability, and flexibility of their IT resources. But virtualization comes at a cost. Virtual environments are complex to manage and vulnerable to security threats. IT must be prepared. Now applications can be secured, resources can be maximized and your IT department can reap the rewards of having a single, unified management system - without a security risk in sight. WatchGuard XTMv brings best-in-class network security to the world of virtualization. With real-time monitoring, multi-WAN support and scalable solutions to fit any-sized business, your virtual environments can be just as secure as your physical one.",
diff --git a/gns3server/appliances/webterm.gns3a b/gns3server/appliances/webterm.gns3a
index de999278..ffb71d7a 100644
--- a/gns3server/appliances/webterm.gns3a
+++ b/gns3server/appliances/webterm.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "42bf9ee2-7278-4346-988a-0b6292198d4f",
"name": "webterm",
"category": "guest",
"description": "webterm is a debian based networking toolbox.\nIt contains the firefox web browser plus the following utilities: net-tools, iproute2, ping, traceroute, curl, host, iperf3, mtr, socat, ssh client, tcpdump, ab(apache benchmark) and the multicast testing tools msend/mreceive.",
diff --git a/gns3server/appliances/windows-xp+ie.gns3a b/gns3server/appliances/windows-xp+ie.gns3a
index f5aeb0c6..eedc0de2 100644
--- a/gns3server/appliances/windows-xp+ie.gns3a
+++ b/gns3server/appliances/windows-xp+ie.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "3976f732-7d50-4dba-b5f7-e2f2c17129eb",
"name": "Windows",
"category": "guest",
"description": "Microsoft Windows XP is a graphical operating system developed, marketed, and sold by Microsoft.\n\nMicrosoft has released time limited VMs for testing Internet Explorer.",
diff --git a/gns3server/appliances/windows.gns3a b/gns3server/appliances/windows.gns3a
index fb3f5a0c..98c41571 100644
--- a/gns3server/appliances/windows.gns3a
+++ b/gns3server/appliances/windows.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "9101a9be-ecc5-49ae-988c-735f5d2125de",
"name": "Windows",
"category": "guest",
"description": "Microsoft Windows, or simply Windows, is a metafamily of graphical operating systems developed, marketed, and sold by Microsoft. It consists of several families of operating systems, each of which cater to a certain sector of the computing industry with the OS typically associated with IBM PC compatible architecture.",
diff --git a/gns3server/appliances/windows_server.gns3a b/gns3server/appliances/windows_server.gns3a
index b575b72b..153391ba 100644
--- a/gns3server/appliances/windows_server.gns3a
+++ b/gns3server/appliances/windows_server.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "2b98950c-4b0c-450c-acf8-caf923ac2b28",
"name": "Windows Server",
"category": "guest",
"description": "Microsoft Windows, or simply Windows, is a metafamily of graphical operating systems developed, marketed, and sold by Microsoft. It consists of several families of operating systems, each of which cater to a certain sector of the computing industry with the OS typically associated with IBM PC compatible architecture.",
diff --git a/gns3server/appliances/zentyal-server.gns3a b/gns3server/appliances/zentyal-server.gns3a
index d451a6f5..b173b812 100644
--- a/gns3server/appliances/zentyal-server.gns3a
+++ b/gns3server/appliances/zentyal-server.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "4f5edc3d-f890-4d22-a17d-608c0dba4002",
"name": "Zentyal Server",
"category": "guest",
"description": "The on-premise Mail and Directory server. Native compatibility with Microsoft Active Directory. You can control your IT infrastructure from a single point of user management, regardless of the different offices and locations your business has. True Microsoft Outlook compatibility. Your users can continue using their favorite email clients, without any service interruptions and without having to install any plug-in or connector.",
diff --git a/gns3server/appliances/zeroshell.gns3a b/gns3server/appliances/zeroshell.gns3a
index f62cfa10..e34dc337 100644
--- a/gns3server/appliances/zeroshell.gns3a
+++ b/gns3server/appliances/zeroshell.gns3a
@@ -1,4 +1,5 @@
{
+ "appliance_id": "a210781e-471a-4628-8f43-83941c3909a6",
"name": "ZeroShell",
"category": "router",
"description": "Zeroshell is a Linux distribution for servers and embedded devices aimed at providing the main network services a LAN requires. It is available in the form of Live CD or Compact Flash image and you can configure and administer it using your web browser.",
diff --git a/gns3server/compute/base_manager.py b/gns3server/compute/base_manager.py
index 82f206d9..1d8c78e7 100644
--- a/gns3server/compute/base_manager.py
+++ b/gns3server/compute/base_manager.py
@@ -475,8 +475,7 @@ class BaseManager:
for root, dirs, files in os.walk(directory):
for file in files:
- # If filename is the same
- if s[1] == file and (s[0] == '' or os.path.basename(s[0]) == os.path.basename(root)):
+ if s[1] == file and (s[0] == '' or root == os.path.join(directory, s[0])):
path = os.path.normpath(os.path.join(root, s[1]))
if os.path.exists(path):
return path
diff --git a/gns3server/compute/base_node.py b/gns3server/compute/base_node.py
index 71ad1a2c..cfa147a8 100644
--- a/gns3server/compute/base_node.py
+++ b/gns3server/compute/base_node.py
@@ -974,7 +974,7 @@ class BaseNode:
"""
available_ram = int(psutil.virtual_memory().available / (1024 * 1024))
- percentage_left = psutil.virtual_memory().percent
+ percentage_left = 100 - psutil.virtual_memory().percent
if requested_ram > available_ram:
message = '"{}" requires {}MB of RAM to run but there is only {}MB - {}% of RAM left on "{}"'.format(
self.name, requested_ram, available_ram, percentage_left, platform.node()
diff --git a/gns3server/compute/builtin/nodes/nat.py b/gns3server/compute/builtin/nodes/nat.py
index 21deca92..29d17959 100644
--- a/gns3server/compute/builtin/nodes/nat.py
+++ b/gns3server/compute/builtin/nodes/nat.py
@@ -36,10 +36,16 @@ class Nat(Cloud):
def __init__(self, name, node_id, project, manager, ports=None):
+ allowed_interfaces = Config.instance().settings.Server.allowed_interfaces
+ if allowed_interfaces:
+ allowed_interfaces = allowed_interfaces.split(',')
if sys.platform.startswith("linux"):
nat_interface = Config.instance().settings.Server.default_nat_interface
if not nat_interface:
nat_interface = "virbr0"
+ if allowed_interfaces and nat_interface not in allowed_interfaces:
+ raise NodeError("NAT interface {} is not allowed be used on this server. "
+ "Please check the server configuration file.".format(nat_interface))
if nat_interface not in [interface["name"] for interface in gns3server.utils.interfaces.interfaces()]:
raise NodeError(f"NAT interface {nat_interface} is missing, please install libvirt")
interface = nat_interface
@@ -47,6 +53,9 @@ class Nat(Cloud):
nat_interface = Config.instance().settings.Server.default_nat_interface
if not nat_interface:
nat_interface = "vmnet8"
+ if allowed_interfaces and nat_interface not in allowed_interfaces:
+ raise NodeError("NAT interface {} is not allowed be used on this server. "
+ "Please check the server configuration file.".format(nat_interface))
interfaces = list(
filter(
lambda x: nat_interface in x.lower(),
diff --git a/gns3server/compute/docker/docker_vm.py b/gns3server/compute/docker/docker_vm.py
index 55a38e0c..29afbc9d 100644
--- a/gns3server/compute/docker/docker_vm.py
+++ b/gns3server/compute/docker/docker_vm.py
@@ -574,14 +574,9 @@ class DockerVM(BaseNode):
# https://github.com/GNS3/gns3-gui/issues/1039
try:
process = await asyncio.subprocess.create_subprocess_exec(
- "docker",
- "exec",
- "-i",
- self._cid,
- "/gns3/bin/busybox",
"script",
"-qfc",
- "while true; do TERM=vt100 /gns3/bin/busybox sh; done",
+ f"docker exec -i -t {self._cid} /gns3/bin/busybox sh -c 'while true; do TERM=vt100 /gns3/bin/busybox sh; done'",
"/dev/null",
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.STDOUT,
diff --git a/gns3server/compute/docker/resources/bin/busybox b/gns3server/compute/docker/resources/bin/busybox
deleted file mode 100755
index 68ebef5e..00000000
Binary files a/gns3server/compute/docker/resources/bin/busybox and /dev/null differ
diff --git a/gns3server/compute/docker/resources/bin/udhcpc b/gns3server/compute/docker/resources/bin/udhcpc
new file mode 100644
index 00000000..16c064d0
--- /dev/null
+++ b/gns3server/compute/docker/resources/bin/udhcpc
@@ -0,0 +1,15 @@
+#!/gns3/bin/busybox sh
+
+SCRIPT="/gns3/etc/udhcpc/default.script"
+
+if [ "$(cat "/proc/$PPID/comm" 2>/dev/null)" = ifup ]; then
+ # remove "-n" argument
+ for arg do
+ shift
+ [ "$arg" = "-n" ] || set -- "$@" "$arg"
+ done
+ # add default parameters
+ set -- -t 3 -T 2 -A 1 -b "$@"
+fi
+
+exec /tmp/gns3/bin/udhcpc -s "$SCRIPT" "$@"
diff --git a/gns3server/compute/qemu/__init__.py b/gns3server/compute/qemu/__init__.py
index 2993ddbf..2a0c48c3 100644
--- a/gns3server/compute/qemu/__init__.py
+++ b/gns3server/compute/qemu/__init__.py
@@ -152,8 +152,6 @@ class Qemu(BaseManager):
log.debug(f"Searching for Qemu binaries in '{path}'")
try:
for f in os.listdir(path):
- if f.endswith("-spice"):
- continue
if (
(f.startswith("qemu-system") or f.startswith("qemu-kvm") or f == "qemu" or f == "qemu.exe")
and os.access(os.path.join(path, f), os.X_OK)
diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py
index 3077b973..adec97db 100644
--- a/gns3server/compute/qemu/qemu_vm.py
+++ b/gns3server/compute/qemu/qemu_vm.py
@@ -146,7 +146,6 @@ class QemuVM(BaseNode):
self._initrd = ""
self._kernel_image = ""
self._kernel_command_line = ""
- self._legacy_networking = False
self._replicate_network_connection_state = True
self._create_config_disk = False
self._on_close = "power_off"
@@ -679,30 +678,6 @@ class QemuVM(BaseNode):
)
)
- @property
- def legacy_networking(self):
- """
- Returns either QEMU legacy networking commands are used.
-
- :returns: boolean
- """
-
- return self._legacy_networking
-
- @legacy_networking.setter
- def legacy_networking(self, legacy_networking):
- """
- Sets either QEMU legacy networking commands are used.
-
- :param legacy_networking: boolean
- """
-
- if legacy_networking:
- log.info(f'QEMU VM "{self._name}" [{self._id}] has enabled legacy networking')
- else:
- log.info(f'QEMU VM "{self._name}" [{self._id}] has disabled legacy networking')
- self._legacy_networking = legacy_networking
-
@property
def replicate_network_connection_state(self):
"""
@@ -1832,23 +1807,16 @@ class QemuVM(BaseNode):
def _get_qemu_img(self):
"""
Search the qemu-img binary in the same binary of the qemu binary
- for avoiding version incompatibility.
+ to avoid version incompatibility.
:returns: qemu-img path or raise an error
"""
- qemu_img_path = ""
+
qemu_path_dir = os.path.dirname(self.qemu_path)
- try:
- for f in os.listdir(qemu_path_dir):
- if f.startswith("qemu-img"):
- qemu_img_path = os.path.join(qemu_path_dir, f)
- except OSError as e:
- raise QemuError(f"Error while looking for qemu-img in {qemu_path_dir}: {e}")
-
- if not qemu_img_path:
- raise QemuError(f"Could not find qemu-img in {qemu_path_dir}")
-
- return qemu_img_path
+ qemu_image_path = shutil.which("qemu-img", path=qemu_path_dir)
+ if qemu_image_path:
+ return qemu_image_path
+ raise QemuError(f"Could not find qemu-img in {qemu_path_dir}")
async def _qemu_img_exec(self, command):
@@ -1864,27 +1832,36 @@ class QemuVM(BaseNode):
log.info(f"{self._get_qemu_img()} returned with {retcode}")
return retcode
+ async def _find_disk_file_format(self, disk):
+
+ qemu_img_path = self._get_qemu_img()
+ try:
+ output = await subprocess_check_output(qemu_img_path, "info", "--output=json", disk)
+ except subprocess.SubprocessError as e:
+ raise QemuError(f"Error received while checking Qemu disk format: {e}")
+ if output:
+ try:
+ json_data = json.loads(output)
+ except ValueError as e:
+ raise QemuError(f"Invalid JSON data returned by qemu-img: {e}")
+ return json_data.get("format")
+
async def _create_linked_clone(self, disk_name, disk_image, disk):
+
try:
qemu_img_path = self._get_qemu_img()
- command = [qemu_img_path, "create", "-o", f"backing_file={disk_image}", "-f", "qcow2", disk]
- try:
- base_qcow2 = Qcow2(disk_image)
- if base_qcow2.crypt_method:
- # Workaround for https://gitlab.com/qemu-project/qemu/-/issues/441
- # Also embed a secret name so it doesn't have to be passed to qemu -drive ...
- options = {
- "encrypt.key-secret": os.path.basename(disk_image),
- "driver": "qcow2",
- "file": {
- "driver": "file",
- "filename": disk_image,
- },
- }
- command = [qemu_img_path, "create", "-b", "json:"+json.dumps(options, separators=(',', ':')),
- "-f", "qcow2", "-u", disk, str(base_qcow2.size)]
- except Qcow2Error:
- pass # non-qcow2 base images are acceptable (e.g. vmdk, raw image)
+ backing_file_format = await self._find_disk_file_format(disk_image)
+ if not backing_file_format:
+ raise QemuError(f"Could not detect format for disk image: {disk_image}")
+ backing_options, base_qcow2 = Qcow2.backing_options(disk_image)
+ if base_qcow2 and base_qcow2.crypt_method:
+ # Workaround for https://gitlab.com/qemu-project/qemu/-/issues/441
+ # (we have to pass -u and the size). Also embed secret name.
+ command = [qemu_img_path, "create", "-b", backing_options,
+ "-F", backing_file_format, "-f", "qcow2", "-u", disk, str(base_qcow2.size)]
+ else:
+ command = [qemu_img_path, "create", "-o", "backing_file={}".format(disk_image),
+ "-F", backing_file_format, "-f", "qcow2", disk]
retcode = await self._qemu_img_exec(command)
if retcode:
@@ -2068,19 +2045,14 @@ class QemuVM(BaseNode):
if retcode == 3:
# image has leaked clusters, but is not corrupted, let's try to fix it
log.warning(f"Qemu image {disk_image} has leaked clusters")
- if (await self._qemu_img_exec([qemu_img_path, "check", "-r", "leaks", f"{disk_image}"])) == 3:
- self.project.emit(
- "log.warning",
- {"message": f"Qemu image '{disk_image}' has leaked clusters and could not be fixed"},
- )
+ if await self._qemu_img_exec([qemu_img_path, "check", "-r", "leaks", "{}".format(disk_image)]) == 3:
+ self.project.emit("log.warning", {"message": "Qemu image '{}' has leaked clusters and could not be fixed".format(disk_image)})
elif retcode == 2:
# image is corrupted, let's try to fix it
log.warning(f"Qemu image {disk_image} is corrupted")
- if (await self._qemu_img_exec([qemu_img_path, "check", "-r", "all", f"{disk_image}"])) == 2:
- self.project.emit(
- "log.warning",
- {"message": f"Qemu image '{disk_image}' is corrupted and could not be fixed"},
- )
+ if await self._qemu_img_exec([qemu_img_path, "check", "-r", "all", "{}".format(disk_image)]) == 2:
+ self.project.emit("log.warning", {"message": "Qemu image '{}' is corrupted and could not be fixed".format(disk_image)})
+ # ignore retcode == 1. One reason is that the image is encrypted and there is no encrypt.key-secret available
except (OSError, subprocess.SubprocessError) as e:
stdout = self.read_qemu_img_stdout()
raise QemuError(f"Could not check '{disk_name}' disk image: {e}\n{stdout}")
@@ -2091,10 +2063,16 @@ class QemuVM(BaseNode):
# create the disk
await self._create_linked_clone(disk_name, disk_image, disk)
else:
- # The disk exists we check if the clone works
+ backing_file_format = await self._find_disk_file_format(disk_image)
+ if not backing_file_format:
+ raise QemuError("Could not detect format for disk image: {}".format(disk_image))
+ # Rebase the image. This is in case the base image moved to a different directory,
+ # which will be the case if we imported a portable project. This uses
+ # get_abs_image_path(hdX_disk_image) and ignores the old base path embedded
+ # in the qcow2 file itself.
try:
qcow2 = Qcow2(disk)
- await qcow2.validate(qemu_img_path)
+ await qcow2.rebase(qemu_img_path, disk_image, backing_file_format)
except (Qcow2Error, OSError) as e:
raise QemuError(f"Could not use qcow2 disk image '{disk_image}' for {disk_name} {e}")
@@ -2205,16 +2183,6 @@ class QemuVM(BaseNode):
["-net", "none"]
) # we do not want any user networking back-end if no adapter is connected.
- patched_qemu = False
- if self._legacy_networking:
- qemu_version = await self.manager.get_qemu_version(self.qemu_path)
- if qemu_version:
- if parse_version(qemu_version) >= parse_version("2.9.0"):
- raise QemuError("Qemu version 2.9.0 and later doesn't support legacy networking mode")
- if parse_version(qemu_version) < parse_version("1.1.0"):
- # this is a patched Qemu if version is below 1.1.0
- patched_qemu = True
-
# Each 32 PCI device we need to add a PCI bridge with max 9 bridges
pci_devices = 4 + len(self._ethernet_adapters) # 4 PCI devices are use by default by qemu
pci_bridges = math.floor(pci_devices / 32)
@@ -2241,72 +2209,40 @@ class QemuVM(BaseNode):
if custom_mac_address:
mac = int_to_macaddress(macaddress_to_int(custom_mac_address))
- if self._legacy_networking:
- # legacy QEMU networking syntax (-net)
- if nio:
- network_options.extend(["-net", f"nic,vlan={adapter_number},macaddr={mac},model={adapter_type}"])
- if isinstance(nio, NIOUDP):
- if patched_qemu:
- # use patched Qemu syntax
- network_options.extend(
- [
- "-net",
- "udp,vlan={},name=gns3-{},sport={},dport={},daddr={}".format(
- adapter_number, adapter_number, nio.lport, nio.rport, nio.rhost
- ),
- ]
- )
- else:
- # use UDP tunnel support added in Qemu 1.1.0
- network_options.extend(
- [
- "-net",
- "socket,vlan={},name=gns3-{},udp={}:{},localaddr={}:{}".format(
- adapter_number, adapter_number, nio.rhost, nio.rport, "127.0.0.1", nio.lport
- ),
- ]
- )
- elif isinstance(nio, NIOTAP):
- network_options.extend(["-net", f"tap,name=gns3-{adapter_number},ifname={nio.tap_device}"])
- else:
- network_options.extend(["-net", f"nic,vlan={adapter_number},macaddr={mac},model={adapter_type}"])
-
+ device_string = f"{adapter_type},mac={mac}"
+ bridge_id = math.floor(pci_device_id / 32)
+ if bridge_id > 0:
+ if pci_bridges_created < bridge_id:
+ network_options.extend(["-device", f"i82801b11-bridge,id=dmi_pci_bridge{bridge_id}"])
+ network_options.extend(
+ [
+ "-device",
+ "pci-bridge,id=pci-bridge{bridge_id},bus=dmi_pci_bridge{bridge_id},chassis_nr=0x1,addr=0x{bridge_id},shpc=off".format(
+ bridge_id=bridge_id
+ ),
+ ]
+ )
+ pci_bridges_created += 1
+ addr = pci_device_id % 32
+ device_string = f"{device_string},bus=pci-bridge{bridge_id},addr=0x{addr:02x}"
+ pci_device_id += 1
+ if nio:
+ network_options.extend(["-device", f"{device_string},netdev=gns3-{adapter_number}"])
+ if isinstance(nio, NIOUDP):
+ network_options.extend(
+ [
+ "-netdev",
+ "socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(
+ adapter_number, nio.rhost, nio.rport, "127.0.0.1", nio.lport
+ ),
+ ]
+ )
+ elif isinstance(nio, NIOTAP):
+ network_options.extend(
+ ["-netdev", f"tap,id=gns3-{adapter_number},ifname={nio.tap_device},script=no,downscript=no"]
+ )
else:
- # newer QEMU networking syntax
- device_string = f"{adapter_type},mac={mac}"
- bridge_id = math.floor(pci_device_id / 32)
- if bridge_id > 0:
- if pci_bridges_created < bridge_id:
- network_options.extend(["-device", f"i82801b11-bridge,id=dmi_pci_bridge{bridge_id}"])
- network_options.extend(
- [
- "-device",
- "pci-bridge,id=pci-bridge{bridge_id},bus=dmi_pci_bridge{bridge_id},chassis_nr=0x1,addr=0x{bridge_id},shpc=off".format(
- bridge_id=bridge_id
- ),
- ]
- )
- pci_bridges_created += 1
- addr = pci_device_id % 32
- device_string = f"{device_string},bus=pci-bridge{bridge_id},addr=0x{addr:02x}"
- pci_device_id += 1
- if nio:
- network_options.extend(["-device", f"{device_string},netdev=gns3-{adapter_number}"])
- if isinstance(nio, NIOUDP):
- network_options.extend(
- [
- "-netdev",
- "socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(
- adapter_number, nio.rhost, nio.rport, "127.0.0.1", nio.lport
- ),
- ]
- )
- elif isinstance(nio, NIOTAP):
- network_options.extend(
- ["-netdev", f"tap,id=gns3-{adapter_number},ifname={nio.tap_device},script=no,downscript=no"]
- )
- else:
- network_options.extend(["-device", device_string])
+ network_options.extend(["-device", device_string])
return network_options
diff --git a/gns3server/compute/qemu/utils/qcow2.py b/gns3server/compute/qemu/utils/qcow2.py
index 52269f36..60fdc972 100644
--- a/gns3server/compute/qemu/utils/qcow2.py
+++ b/gns3server/compute/qemu/utils/qcow2.py
@@ -15,6 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+import json
import os
import asyncio
import struct
@@ -88,31 +89,50 @@ class Qcow2:
return None
return path
- async def rebase(self, qemu_img, base_image):
+ @staticmethod
+ def backing_options(base_image):
+ """
+ If the base_image is encrypted qcow2, return options for the upper layer
+ which include a secret name (equal to the basename)
+
+ :param base_image: Path to the base file (which may or may not be qcow2)
+
+ :returns: (base image string, Qcow2 object representing base image or None)
+ """
+
+ try:
+ base_qcow2 = Qcow2(base_image)
+ if base_qcow2.crypt_method:
+ # Embed a secret name so it doesn't have to be passed to qemu -drive ...
+ options = {
+ "encrypt.key-secret": os.path.basename(base_image),
+ "driver": "qcow2",
+ "file": {
+ "driver": "file",
+ "filename": base_image,
+ },
+ }
+ return ("json:"+json.dumps(options, separators=(',', ':')), base_qcow2)
+ else:
+ return (base_image, base_qcow2)
+ except Qcow2Error:
+ return (base_image, None) # non-qcow2 base images are acceptable (e.g. vmdk, raw image)
+
+ async def rebase(self, qemu_img, base_image, backing_file_format):
"""
Rebase a linked clone in order to use the correct disk
:param qemu_img: Path to the qemu-img binary
:param base_image: Path to the base image
+ :param backing_file_format: File format of the base image
"""
if not os.path.exists(base_image):
raise FileNotFoundError(base_image)
- command = [qemu_img, "rebase", "-u", "-b", base_image, self._path]
+ backing_options, _ = Qcow2.backing_options(base_image)
+ command = [qemu_img, "rebase", "-u", "-b", backing_options, "-F", backing_file_format, self._path]
process = await asyncio.create_subprocess_exec(*command)
retcode = await process.wait()
if retcode != 0:
raise Qcow2Error("Could not rebase the image")
self._reload()
-
- async def validate(self, qemu_img):
- """
- Run qemu-img info to validate the file and its backing images
-
- :param qemu_img: Path to the qemu-img binary
- """
- command = [qemu_img, "info", "--backing-chain", self._path]
- process = await asyncio.create_subprocess_exec(*command)
- retcode = await process.wait()
- if retcode != 0:
- raise Qcow2Error("Could not validate the image")
diff --git a/gns3server/controller/appliance.py b/gns3server/controller/appliance.py
index 7913f0ab..9e93ee42 100644
--- a/gns3server/controller/appliance.py
+++ b/gns3server/controller/appliance.py
@@ -16,7 +16,6 @@
# along with this program. If not, see .
import copy
-import uuid
import logging
log = logging.getLogger(__name__)
@@ -24,19 +23,12 @@ log = logging.getLogger(__name__)
class Appliance:
- def __init__(self, appliance_id, data, builtin=True):
+ def __init__(self, path, data, builtin=True):
- if appliance_id is None:
- self._id = str(uuid.uuid4())
- elif isinstance(appliance_id, uuid.UUID):
- self._id = str(appliance_id)
- else:
- self._id = appliance_id
self._data = data.copy()
+ self._id = self._data.get("appliance_id")
+ self._path = path
self._builtin = builtin
- if "appliance_id" in self._data:
- del self._data["appliance_id"]
-
if self.status != "broken":
log.debug(f'Appliance "{self.name}" [{self._id}] loaded')
@@ -44,6 +36,10 @@ class Appliance:
def id(self):
return self._id
+ @property
+ def path(self):
+ return self._path
+
@property
def status(self):
return self._data["status"]
@@ -56,14 +52,35 @@ class Appliance:
def name(self):
return self._data.get("name")
+ @property
+ def images(self):
+ return self._data.get("images")
+
+ @property
+ def versions(self):
+ return self._data.get("versions")
+
@symbol.setter
def symbol(self, new_symbol):
self._data["symbol"] = new_symbol
+ @property
+ def type(self):
+
+ if "iou" in self._data:
+ return "iou"
+ elif "dynamips" in self._data:
+ return "dynamips"
+ elif "docker" in self._data:
+ return "docker"
+ else:
+ return "qemu"
+
def asdict(self):
"""
Appliance data (a hash)
"""
+
data = copy.deepcopy(self._data)
data["builtin"] = self._builtin
return data
diff --git a/gns3server/controller/appliance_manager.py b/gns3server/controller/appliance_manager.py
index 375c778a..eb968f0d 100644
--- a/gns3server/controller/appliance_manager.py
+++ b/gns3server/controller/appliance_manager.py
@@ -16,17 +16,32 @@
# along with this program. If not, see .
import os
-import shutil
import json
-import uuid
import asyncio
+import aiofiles
+
+from typing import Tuple, List
+from aiohttp.client_exceptions import ClientError
+
+from uuid import UUID
+from pydantic import ValidationError
from .appliance import Appliance
from ..config import Config
from ..utils.asyncio import locking
from ..utils.get_resource import get_resource
from ..utils.http_client import HTTPClient
-from .controller_error import ControllerError
+from .controller_error import ControllerBadRequestError, ControllerNotFoundError, ControllerError
+from .appliance_to_template import ApplianceToTemplate
+from ..utils.images import InvalidImageError, write_image, md5sum
+from ..utils.asyncio import wait_run_in_executor
+
+from gns3server import schemas
+from gns3server.utils.images import default_images_directory
+from gns3server.db.repositories.images import ImagesRepository
+from gns3server.db.repositories.templates import TemplatesRepository
+from gns3server.services.templates import TemplatesService
+from gns3server.db.repositories.rbac import RbacRepository
import logging
@@ -44,7 +59,7 @@ class ApplianceManager:
self._appliances_etag = None
@property
- def appliances_etag(self):
+ def appliances_etag(self) -> str:
"""
:returns: ETag for downloaded appliances
"""
@@ -60,14 +75,14 @@ class ApplianceManager:
self._appliances_etag = etag
@property
- def appliances(self):
+ def appliances(self) -> dict:
"""
:returns: The dictionary of appliances managed by GNS3
"""
return self._appliances
- def appliances_path(self):
+ def appliances_path(self) -> str:
"""
Get the image storage directory
"""
@@ -77,7 +92,190 @@ class ApplianceManager:
os.makedirs(appliances_path, exist_ok=True)
return appliances_path
- def load_appliances(self, symbol_theme="Classic"):
+ def _find_appliances_from_image_checksum(self, image_checksum: str) -> List[Tuple[Appliance, str]]:
+ """
+ Find appliances that matches an image checksum.
+ """
+
+ appliances = []
+ for appliance in self._appliances.values():
+ if appliance.images:
+ for image in appliance.images:
+ if image.get("md5sum") == image_checksum:
+ appliances.append((appliance, image.get("version")))
+ return appliances
+
+ async def _download_image(
+ self,
+ image_dir: str,
+ image_name: str,
+ image_type: str,
+ image_url: str,
+ images_repo: ImagesRepository
+ ) -> None:
+ """
+ Download an image.
+ """
+
+ log.info(f"Downloading image '{image_name}' from '{image_url}'")
+ image_path = os.path.join(image_dir, image_name)
+ try:
+ async with HTTPClient.get(image_url) as response:
+ if response.status != 200:
+ raise ControllerError(f"Could not download '{image_name}' due to HTTP error code {response.status}")
+ await write_image(image_name, image_type, image_path, response.content.iter_any(), images_repo)
+ except (OSError, InvalidImageError) as e:
+ raise ControllerError(f"Could not save {image_type} image '{image_path}': {e}")
+ except ClientError as e:
+ raise ControllerError(f"Could not connect to download '{image_name}': {e}")
+ except asyncio.TimeoutError:
+ raise ControllerError(f"Timeout while downloading '{image_name}' from '{image_url}'")
+
+ async def _find_appliance_version_images(
+ self,
+ appliance: Appliance,
+ version: dict,
+ images_repo: ImagesRepository,
+ image_dir: str
+ ) -> None:
+ """
+ Find all the images belonging to a specific appliance version.
+ """
+
+ version_images = version.get("images")
+ if version_images:
+ for appliance_key, appliance_file in version_images.items():
+ for image in appliance.images:
+ if appliance_file == image.get("filename"):
+ image_checksum = image.get("md5sum")
+ image_in_db = await images_repo.get_image_by_checksum(image_checksum)
+ if image_in_db:
+ version_images[appliance_key] = image_in_db.filename
+ else:
+ # check if the image is on disk
+ image_path = os.path.join(image_dir, appliance_file)
+ if os.path.exists(image_path) and await wait_run_in_executor(md5sum, image_path) == image_checksum:
+ async with aiofiles.open(image_path, "rb") as f:
+ await write_image(appliance_file, appliance.type, image_path, f, images_repo)
+ else:
+ # download the image if there is a direct download URL
+ direct_download_url = image.get("direct_download_url")
+ if direct_download_url:
+ await self._download_image(
+ image_dir,
+ appliance_file,
+ appliance.type,
+ direct_download_url,
+ images_repo)
+ else:
+ raise ControllerError(f"Could not find '{appliance_file}'")
+
+ async def _create_template(self, template_data, templates_repo, rbac_repo, current_user):
+ """
+ Create a new template
+ """
+
+ try:
+ template_create = schemas.TemplateCreate(**template_data)
+ except ValidationError as e:
+ raise ControllerError(message=f"Could not validate template data: {e}")
+ template = await TemplatesService(templates_repo).create_template(template_create)
+ template_id = template.get("template_id")
+ await rbac_repo.add_permission_to_user_with_path(current_user.user_id, f"/templates/{template_id}/*")
+ log.info(f"Template '{template.get('name')}' has been created")
+
+ async def _appliance_to_template(self, appliance: Appliance, version: str = None) -> dict:
+ """
+ Get template data from appliance
+ """
+
+ from . import Controller
+
+ # downloading missing custom symbol for this appliance
+ if appliance.symbol and not appliance.symbol.startswith(":/symbols/"):
+ destination_path = os.path.join(Controller.instance().symbols.symbols_path(), appliance.symbol)
+ if not os.path.exists(destination_path):
+ await self._download_symbol(appliance.symbol, destination_path)
+ return ApplianceToTemplate().new_template(appliance.asdict(), version, "local") # FIXME: "local"
+
+ async def install_appliances_from_image(
+ self,
+ image_path: str,
+ image_checksum: str,
+ images_repo: ImagesRepository,
+ templates_repo: TemplatesRepository,
+ rbac_repo: RbacRepository,
+ current_user: schemas.User,
+ image_dir: str
+ ) -> None:
+ """
+ Install appliances using an image checksum
+ """
+
+ appliances_info = self._find_appliances_from_image_checksum(image_checksum)
+ for appliance, image_version in appliances_info:
+ try:
+ schemas.Appliance.parse_obj(appliance.asdict())
+ except ValidationError as e:
+ log.warning(message=f"Could not validate appliance '{appliance.id}': {e}")
+ if appliance.versions:
+ for version in appliance.versions:
+ if version.get("name") == image_version:
+ try:
+ await self._find_appliance_version_images(appliance, version, images_repo, image_dir)
+ template_data = await self._appliance_to_template(appliance, version)
+ await self._create_template(template_data, templates_repo, rbac_repo, current_user)
+ except (ControllerError, InvalidImageError) as e:
+ log.warning(f"Could not automatically create template using image '{image_path}': {e}")
+
+ async def install_appliance(
+ self,
+ appliance_id: UUID,
+ version: str,
+ images_repo: ImagesRepository,
+ templates_repo: TemplatesRepository,
+ rbac_repo: RbacRepository,
+ current_user: schemas.User
+ ) -> None:
+ """
+ Install a new appliance
+ """
+
+ appliance = self._appliances.get(str(appliance_id))
+ if not appliance:
+ raise ControllerNotFoundError(message=f"Could not find appliance '{appliance_id}'")
+
+ try:
+ schemas.Appliance.parse_obj(appliance.asdict())
+ except ValidationError as e:
+ raise ControllerError(message=f"Could not validate appliance '{appliance_id}': {e}")
+
+ if version:
+ if not appliance.versions:
+ raise ControllerBadRequestError(message=f"Appliance '{appliance_id}' do not have versions")
+
+ image_dir = default_images_directory(appliance.type)
+ for appliance_version_info in appliance.versions:
+ if appliance_version_info.get("name") == version:
+ try:
+ await self._find_appliance_version_images(appliance, appliance_version_info, images_repo, image_dir)
+ except InvalidImageError as e:
+ raise ControllerError(message=f"Image error: {e}")
+ template_data = await self._appliance_to_template(appliance, appliance_version_info)
+ return await self._create_template(template_data, templates_repo, rbac_repo, current_user)
+
+ raise ControllerNotFoundError(message=f"Could not find version '{version}' in appliance '{appliance_id}'")
+
+ else:
+ if appliance.versions:
+ # TODO: install appliance versions based on available images
+ raise ControllerBadRequestError(message=f"Selecting a version is required to install "
+ f"appliance '{appliance_id}'")
+
+ template_data = await self._appliance_to_template(appliance)
+ await self._create_template(template_data, templates_repo, rbac_repo, current_user)
+
+ def load_appliances(self, symbol_theme: str = "Classic") -> None:
"""
Loads appliance files from disk.
"""
@@ -98,25 +296,23 @@ class ApplianceManager:
if not file.endswith(".gns3a") and not file.endswith(".gns3appliance"):
continue
path = os.path.join(directory, file)
- appliance_id = uuid.uuid3(
- uuid.NAMESPACE_URL, path
- ) # Generate UUID from path to avoid change between reboots
try:
with open(path, encoding="utf-8") as f:
- appliance = Appliance(appliance_id, json.load(f), builtin=builtin)
+ appliance = Appliance(path, json.load(f), builtin=builtin)
json_data = appliance.asdict() # Check if loaded without error
if appliance.status != "broken":
+ schemas.Appliance.parse_obj(json_data)
self._appliances[appliance.id] = appliance
if not appliance.symbol or appliance.symbol.startswith(":/symbols/"):
# apply a default symbol if the appliance has none or a default symbol
default_symbol = self._get_default_symbol(json_data, symbol_theme)
if default_symbol:
appliance.symbol = default_symbol
- except (ValueError, OSError, KeyError) as e:
- log.warning("Cannot load appliance file '%s': %s", path, str(e))
+ except (ValueError, OSError, KeyError, ValidationError) as e:
+ print(f"Cannot load appliance file '{path}': {e}")
continue
- def _get_default_symbol(self, appliance, symbol_theme):
+ def _get_default_symbol(self, appliance: dict, symbol_theme: str) -> str:
"""
Returns the default symbol for a given appliance.
"""
@@ -132,7 +328,7 @@ class ApplianceManager:
return controller.symbols.get_default_symbol("qemu_guest", symbol_theme)
return controller.symbols.get_default_symbol(category, symbol_theme)
- async def download_custom_symbols(self):
+ async def download_custom_symbols(self) -> None:
"""
Download custom appliance symbols from our GitHub registry repository.
"""
@@ -151,12 +347,13 @@ class ApplianceManager:
# refresh the symbol cache
Controller.instance().symbols.list()
- async def _download_symbol(self, symbol, destination_path):
+ async def _download_symbol(self, symbol: str, destination_path: str) -> None:
"""
Download a custom appliance symbol from our GitHub registry repository.
"""
symbol_url = f"https://raw.githubusercontent.com/GNS3/gns3-registry/master/symbols/{symbol}"
+ log.info(f"Downloading symbol '{symbol}'")
async with HTTPClient.get(symbol_url) as response:
if response.status != 200:
log.warning(
@@ -174,7 +371,7 @@ class ApplianceManager:
log.warning(f"Could not write appliance symbol '{destination_path}': {e}")
@locking
- async def download_appliances(self):
+ async def download_appliances(self) -> None:
"""
Downloads appliance files from GitHub registry repository.
"""
diff --git a/gns3server/controller/appliance_to_template.py b/gns3server/controller/appliance_to_template.py
new file mode 100644
index 00000000..aee787f6
--- /dev/null
+++ b/gns3server/controller/appliance_to_template.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2021 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+import logging
+log = logging.getLogger(__name__)
+
+
+class ApplianceToTemplate:
+ """
+ Appliance installation.
+ """
+
+ def new_template(self, appliance_config, version, server):
+ """
+ Creates a new template from an appliance.
+ """
+
+ new_template = {
+ "compute_id": server,
+ "name": appliance_config["name"],
+ }
+
+ if version:
+ new_template["version"] = version.get("name")
+
+ if "usage" in appliance_config:
+ new_template["usage"] = appliance_config["usage"]
+
+ if appliance_config["category"] == "multilayer_switch":
+ new_template["category"] = "switch"
+ else:
+ new_template["category"] = appliance_config["category"]
+
+ if "symbol" in appliance_config:
+ new_template["symbol"] = appliance_config.get("symbol")
+
+ if new_template.get("symbol") is None:
+ if appliance_config["category"] == "guest":
+ if "docker" in appliance_config:
+ new_template["symbol"] = ":/symbols/docker_guest.svg"
+ else:
+ new_template["symbol"] = ":/symbols/qemu_guest.svg"
+ elif appliance_config["category"] == "router":
+ new_template["symbol"] = ":/symbols/router.svg"
+ elif appliance_config["category"] == "switch":
+ new_template["symbol"] = ":/symbols/ethernet_switch.svg"
+ elif appliance_config["category"] == "multilayer_switch":
+ new_template["symbol"] = ":/symbols/multilayer_switch.svg"
+ elif appliance_config["category"] == "firewall":
+ new_template["symbol"] = ":/symbols/firewall.svg"
+
+ if "qemu" in appliance_config:
+ new_template["template_type"] = "qemu"
+ self._add_qemu_config(new_template, appliance_config, version)
+ elif "iou" in appliance_config:
+ new_template["template_type"] = "iou"
+ self._add_iou_config(new_template, appliance_config, version)
+ elif "dynamips" in appliance_config:
+ new_template["template_type"] = "dynamips"
+ self._add_dynamips_config(new_template, appliance_config, version)
+ elif "docker" in appliance_config:
+ new_template["template_type"] = "docker"
+ self._add_docker_config(new_template, appliance_config)
+
+ return new_template
+
+ def _add_qemu_config(self, new_config, appliance_config, version):
+
+ new_config.update(appliance_config["qemu"])
+
+ # the following properties are not valid for a template
+ new_config.pop("kvm", None)
+ new_config.pop("path", None)
+ new_config.pop("arch", None)
+
+ options = appliance_config["qemu"].get("options", "")
+ if appliance_config["qemu"].get("kvm", "allow") == "disable" and "-machine accel=tcg" not in options:
+ options += " -machine accel=tcg"
+ new_config["options"] = options.strip()
+ new_config.update(version.get("images"))
+
+ if "path" in appliance_config["qemu"]:
+ new_config["qemu_path"] = appliance_config["qemu"]["path"]
+ else:
+ new_config["qemu_path"] = "qemu-system-{}".format(appliance_config["qemu"]["arch"])
+
+ if "first_port_name" in appliance_config:
+ new_config["first_port_name"] = appliance_config["first_port_name"]
+
+ if "port_name_format" in appliance_config:
+ new_config["port_name_format"] = appliance_config["port_name_format"]
+
+ if "port_segment_size" in appliance_config:
+ new_config["port_segment_size"] = appliance_config["port_segment_size"]
+
+ if "custom_adapters" in appliance_config:
+ new_config["custom_adapters"] = appliance_config["custom_adapters"]
+
+ if "linked_clone" in appliance_config:
+ new_config["linked_clone"] = appliance_config["linked_clone"]
+
+ def _add_docker_config(self, new_config, appliance_config):
+
+ new_config.update(appliance_config["docker"])
+
+ if "custom_adapters" in appliance_config:
+ new_config["custom_adapters"] = appliance_config["custom_adapters"]
+
+ def _add_dynamips_config(self, new_config, appliance_config, version):
+
+ new_config.update(appliance_config["dynamips"])
+ new_config["idlepc"] = version.get("idlepc", "")
+ new_config["image"] = version.get("images").get("image")
+
+ def _add_iou_config(self, new_config, appliance_config, version):
+
+ new_config.update(appliance_config["iou"])
+ new_config["path"] = version.get("images").get("image")
diff --git a/gns3server/controller/link.py b/gns3server/controller/link.py
index b4a02c0e..ae224b7d 100644
--- a/gns3server/controller/link.py
+++ b/gns3server/controller/link.py
@@ -174,7 +174,6 @@ class Link:
async def update_link_style(self, link_style):
if link_style != self._link_style:
self._link_style = link_style
- await self.update()
self._project.emit_notification("link.updated", self.asdict())
self._project.dump()
diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py
index ca086455..c6a046e4 100644
--- a/gns3server/controller/node.py
+++ b/gns3server/controller/node.py
@@ -25,6 +25,7 @@ from .compute import ComputeConflict, ComputeError
from .controller_error import ControllerError, ControllerTimeoutError
from .ports.port_factory import PortFactory, StandardPortFactory, DynamipsPortFactory
from ..utils.images import images_directories
+from ..config import Config
from ..utils.qt import qt_font_to_style
@@ -293,10 +294,11 @@ class Node:
if val is None:
val = ":/symbols/computer.svg"
- # No abs path, fix them (bug of 1.X)
try:
- if not val.startswith(":") and os.path.abspath(val):
- val = os.path.basename(val)
+ if not val.startswith(":") and os.path.isabs(val):
+ default_symbol_directory = Config.instance().settings.Server.symbols_path
+ if os.path.commonprefix([default_symbol_directory, val]) != default_symbol_directory:
+ val = os.path.basename(val)
except OSError:
pass
diff --git a/gns3server/controller/symbols.py b/gns3server/controller/symbols.py
index 395fb947..e601c59a 100644
--- a/gns3server/controller/symbols.py
+++ b/gns3server/controller/symbols.py
@@ -106,8 +106,7 @@ class Symbols:
theme = "Custom symbols"
symbols.append({"symbol_id": symbol_file, "filename": filename, "builtin": False, "theme": theme})
self._symbols_path[symbol_file] = os.path.join(root, filename)
-
- symbols.sort(key=lambda x: x["filename"])
+ symbols.sort(key=lambda x: x["theme"])
return symbols
def symbols_path(self):
@@ -122,6 +121,10 @@ class Symbols:
return None
return directory
+ def has_symbol(self, symbol_id):
+
+ return self._symbols_path.get(symbol_id)
+
def get_path(self, symbol_id):
try:
return self._symbols_path[symbol_id]
diff --git a/gns3server/crash_report.py b/gns3server/crash_report.py
index 9b0f379b..f9f750fe 100644
--- a/gns3server/crash_report.py
+++ b/gns3server/crash_report.py
@@ -59,7 +59,7 @@ class CrashReport:
Report crash to a third party service
"""
- DSN = "https://aefc1e0e41e94957936f8773071aebf9:056b5247d4854b81ac9162d9ccc5a503@o19455.ingest.sentry.io/38482"
+ DSN = "https://959feb527c7441068b1bf80301b6e2c4:efa6d99da4c64faa8a7d929360765b40@o19455.ingest.sentry.io/38482"
_instance = None
def __init__(self):
diff --git a/gns3server/db/models/__init__.py b/gns3server/db/models/__init__.py
index ed5f7ead..d10d0668 100644
--- a/gns3server/db/models/__init__.py
+++ b/gns3server/db/models/__init__.py
@@ -20,6 +20,7 @@ from .users import User, UserGroup
from .roles import Role
from .permissions import Permission
from .computes import Compute
+from .images import Image
from .templates import (
Template,
CloudTemplate,
diff --git a/gns3server/db/models/computes.py b/gns3server/db/models/computes.py
index 5fd1cf56..71043d88 100644
--- a/gns3server/db/models/computes.py
+++ b/gns3server/db/models/computes.py
@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-from sqlalchemy import Column, String
+from sqlalchemy import Column, String, Integer
from .base import BaseTable, GUID
@@ -28,6 +28,6 @@ class Compute(BaseTable):
name = Column(String, index=True)
protocol = Column(String)
host = Column(String)
- port = Column(String)
+ port = Column(Integer)
user = Column(String)
password = Column(String)
diff --git a/gns3server/db/models/images.py b/gns3server/db/models/images.py
new file mode 100644
index 00000000..175ab278
--- /dev/null
+++ b/gns3server/db/models/images.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+from sqlalchemy import Table, Column, String, ForeignKey, BigInteger, Integer
+from sqlalchemy.orm import relationship
+
+from .base import Base, BaseTable, GUID
+
+
+image_template_link = Table(
+ "images_templates_link",
+ Base.metadata,
+ Column("image_id", Integer, ForeignKey("images.image_id", ondelete="CASCADE")),
+ Column("template_id", GUID, ForeignKey("templates.template_id", ondelete="CASCADE"))
+)
+
+
+class Image(BaseTable):
+
+ __tablename__ = "images"
+
+ image_id = Column(Integer, primary_key=True, autoincrement=True)
+ filename = Column(String, index=True)
+ path = Column(String, unique=True)
+ image_type = Column(String)
+ image_size = Column(BigInteger)
+ checksum = Column(String, index=True)
+ checksum_algorithm = Column(String)
+ templates = relationship("Template", secondary=image_template_link, back_populates="images")
diff --git a/gns3server/db/models/permissions.py b/gns3server/db/models/permissions.py
index 4779b6af..8be3d669 100644
--- a/gns3server/db/models/permissions.py
+++ b/gns3server/db/models/permissions.py
@@ -53,19 +53,19 @@ def create_default_roles(target, connection, **kw):
default_permissions = [
{
"description": "Allow access to all endpoints",
- "methods": ["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"],
+ "methods": ["GET", "POST", "PUT", "DELETE"],
"path": "/",
"action": "ALLOW"
},
{
"description": "Allow to create and list projects",
- "methods": ["GET", "HEAD", "POST"],
+ "methods": ["GET", "POST"],
"path": "/projects",
"action": "ALLOW"
},
{
"description": "Allow to create and list templates",
- "methods": ["GET", "HEAD", "POST"],
+ "methods": ["GET", "POST"],
"path": "/templates",
"action": "ALLOW"
},
@@ -77,7 +77,7 @@ def create_default_roles(target, connection, **kw):
},
{
"description": "Allow access to all symbol endpoints",
- "methods": ["GET", "HEAD", "POST"],
+ "methods": ["GET", "POST"],
"path": "/symbols/*",
"action": "ALLOW"
},
diff --git a/gns3server/db/models/roles.py b/gns3server/db/models/roles.py
index 6cba0cc1..b531a50f 100644
--- a/gns3server/db/models/roles.py
+++ b/gns3server/db/models/roles.py
@@ -38,7 +38,7 @@ class Role(BaseTable):
__tablename__ = "roles"
role_id = Column(GUID, primary_key=True, default=generate_uuid)
- name = Column(String, unique=True)
+ name = Column(String, unique=True, index=True)
description = Column(String)
is_builtin = Column(Boolean, default=False)
permissions = relationship("Permission", secondary=permission_role_link, back_populates="roles")
diff --git a/gns3server/db/models/templates.py b/gns3server/db/models/templates.py
index 470b88cb..3086a15c 100644
--- a/gns3server/db/models/templates.py
+++ b/gns3server/db/models/templates.py
@@ -17,8 +17,10 @@
from sqlalchemy import Boolean, Column, String, Integer, ForeignKey, PickleType
+from sqlalchemy.orm import relationship
from .base import BaseTable, generate_uuid, GUID
+from .images import image_template_link
class Template(BaseTable):
@@ -27,13 +29,15 @@ class Template(BaseTable):
template_id = Column(GUID, primary_key=True, default=generate_uuid)
name = Column(String, index=True)
+ version = Column(String)
category = Column(String)
default_name_format = Column(String)
symbol = Column(String)
builtin = Column(Boolean, default=False)
- compute_id = Column(String)
usage = Column(String)
template_type = Column(String)
+ compute_id = Column(String)
+ images = relationship("Image", secondary=image_template_link, back_populates="templates")
__mapper_args__ = {
"polymorphic_identity": "templates",
@@ -197,7 +201,6 @@ class QemuTemplate(Template):
kernel_image = Column(String)
bios_image = Column(String)
kernel_command_line = Column(String)
- legacy_networking = Column(Boolean)
replicate_network_connection_state = Column(Boolean)
create_config_disk = Column(Boolean)
on_close = Column(String)
diff --git a/gns3server/db/repositories/computes.py b/gns3server/db/repositories/computes.py
index b76842cb..2ea00bbd 100644
--- a/gns3server/db/repositories/computes.py
+++ b/gns3server/db/repositories/computes.py
@@ -23,15 +23,14 @@ from sqlalchemy.ext.asyncio import AsyncSession
from .base import BaseRepository
import gns3server.db.models as models
-from gns3server.services import auth_service
from gns3server import schemas
class ComputesRepository(BaseRepository):
+
def __init__(self, db_session: AsyncSession) -> None:
super().__init__(db_session)
- self._auth_service = auth_service
async def get_compute(self, compute_id: UUID) -> Optional[models.Compute]:
diff --git a/gns3server/db/repositories/images.py b/gns3server/db/repositories/images.py
new file mode 100644
index 00000000..17bf4c71
--- /dev/null
+++ b/gns3server/db/repositories/images.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import os
+
+from typing import Optional, List
+from sqlalchemy import select, delete
+from sqlalchemy.ext.asyncio import AsyncSession
+
+from .base import BaseRepository
+
+import gns3server.db.models as models
+
+import logging
+
+log = logging.getLogger(__name__)
+
+
+class ImagesRepository(BaseRepository):
+
+ def __init__(self, db_session: AsyncSession) -> None:
+
+ super().__init__(db_session)
+
+ async def get_image(self, image_path: str) -> Optional[models.Image]:
+ """
+ Get an image by its path.
+ """
+
+ image_dir, image_name = os.path.split(image_path)
+ if image_dir:
+ query = select(models.Image).\
+ where(models.Image.filename == image_name, models.Image.path.endswith(image_path))
+ else:
+ query = select(models.Image).where(models.Image.filename == image_name)
+ result = await self._db_session.execute(query)
+ return result.scalars().one_or_none()
+
+ async def get_image_by_checksum(self, checksum: str) -> Optional[models.Image]:
+ """
+ Get an image by its checksum.
+ """
+
+ query = select(models.Image).where(models.Image.checksum == checksum)
+ result = await self._db_session.execute(query)
+ return result.scalars().first()
+
+ async def get_images(self) -> List[models.Image]:
+ """
+ Get all images.
+ """
+
+ query = select(models.Image)
+ result = await self._db_session.execute(query)
+ return result.scalars().all()
+
+ async def get_image_templates(self, image_id: int) -> Optional[List[models.Template]]:
+ """
+ Get all templates that an image belongs to.
+ """
+
+ query = select(models.Template).\
+ join(models.Template.images).\
+ filter(models.Image.image_id == image_id)
+
+ result = await self._db_session.execute(query)
+ return result.scalars().all()
+
+ async def add_image(self, image_name, image_type, image_size, path, checksum, checksum_algorithm) -> models.Image:
+ """
+ Create a new image.
+ """
+
+ db_image = models.Image(
+ image_id=None,
+ filename=image_name,
+ image_type=image_type,
+ image_size=image_size,
+ path=path,
+ checksum=checksum,
+ checksum_algorithm=checksum_algorithm
+ )
+
+ self._db_session.add(db_image)
+ await self._db_session.commit()
+ await self._db_session.refresh(db_image)
+ return db_image
+
+ async def delete_image(self, image_path: str) -> bool:
+ """
+ Delete an image.
+ """
+
+ image_dir, image_name = os.path.split(image_path)
+ if image_dir:
+ query = delete(models.Image).\
+ where(models.Image.filename == image_name, models.Image.path.endswith(image_path)).\
+ execution_options(synchronize_session=False)
+ else:
+ query = delete(models.Image).where(models.Image.filename == image_name)
+ result = await self._db_session.execute(query)
+ await self._db_session.commit()
+ return result.rowcount > 0
+
+ async def prune_images(self) -> int:
+ """
+ Prune images not attached to any template.
+ """
+
+ query = select(models.Image).\
+ filter(~models.Image.templates.any())
+ result = await self._db_session.execute(query)
+ images = result.scalars().all()
+ images_deleted = 0
+ for image in images:
+ try:
+ log.debug(f"Deleting image '{image.path}'")
+ os.remove(image.path)
+ except OSError:
+ log.warning(f"Could not delete image file {image.path}")
+ if await self.delete_image(image.filename):
+ images_deleted += 1
+ log.info(f"{images_deleted} image(s) have been deleted")
+ return images_deleted
diff --git a/gns3server/db/repositories/templates.py b/gns3server/db/repositories/templates.py
index 4e6f50b1..8fb3e4cf 100644
--- a/gns3server/db/repositories/templates.py
+++ b/gns3server/db/repositories/templates.py
@@ -15,10 +15,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+import os
+
from uuid import UUID
-from typing import List, Union
-from sqlalchemy import select, update, delete
+from typing import List, Union, Optional
+from sqlalchemy import select, delete
from sqlalchemy.ext.asyncio import AsyncSession
+from sqlalchemy.orm import selectinload
from sqlalchemy.orm.session import make_transient
from .base import BaseRepository
@@ -41,19 +44,30 @@ TEMPLATE_TYPE_TO_MODEL = {
class TemplatesRepository(BaseRepository):
+
def __init__(self, db_session: AsyncSession) -> None:
super().__init__(db_session)
async def get_template(self, template_id: UUID) -> Union[None, models.Template]:
- query = select(models.Template).where(models.Template.template_id == template_id)
+ query = select(models.Template).\
+ options(selectinload(models.Template.images)).\
+ where(models.Template.template_id == template_id)
+ result = await self._db_session.execute(query)
+ return result.scalars().first()
+
+ async def get_template_by_name_and_version(self, name: str, version: str) -> Union[None, models.Template]:
+
+ query = select(models.Template).\
+ options(selectinload(models.Template.images)).\
+ where(models.Template.name == name, models.Template.version == version)
result = await self._db_session.execute(query)
return result.scalars().first()
async def get_templates(self) -> List[models.Template]:
- query = select(models.Template)
+ query = select(models.Template).options(selectinload(models.Template.images))
result = await self._db_session.execute(query)
return result.scalars().all()
@@ -66,20 +80,14 @@ class TemplatesRepository(BaseRepository):
await self._db_session.refresh(db_template)
return db_template
- async def update_template(self, template_id: UUID, template_update: schemas.TemplateUpdate) -> schemas.Template:
+ async def update_template(self, db_template: models.Template, template_settings: dict) -> schemas.Template:
- update_values = template_update.dict(exclude_unset=True)
-
- query = update(models.Template). \
- where(models.Template.template_id == template_id). \
- values(update_values)
-
- await self._db_session.execute(query)
+ # update the fields directly because update() query couldn't work
+ for key, value in template_settings.items():
+ setattr(db_template, key, value)
await self._db_session.commit()
- template_db = await self.get_template(template_id)
- if template_db:
- await self._db_session.refresh(template_db) # force refresh of updated_at value
- return template_db
+ await self._db_session.refresh(db_template) # force refresh of updated_at value
+ return db_template
async def delete_template(self, template_id: UUID) -> bool:
@@ -88,18 +96,77 @@ class TemplatesRepository(BaseRepository):
await self._db_session.commit()
return result.rowcount > 0
- async def duplicate_template(self, template_id: UUID) -> schemas.Template:
+ async def duplicate_template(self, template_id: UUID) -> Optional[schemas.Template]:
- query = select(models.Template).where(models.Template.template_id == template_id)
+ query = select(models.Template).\
+ options(selectinload(models.Template.images)).\
+ where(models.Template.template_id == template_id)
db_template = (await self._db_session.execute(query)).scalars().first()
- if not db_template:
- return db_template
-
- # duplicate db object with new primary key (template_id)
- self._db_session.expunge(db_template)
- make_transient(db_template)
- db_template.template_id = None
- self._db_session.add(db_template)
- await self._db_session.commit()
- await self._db_session.refresh(db_template)
+ if db_template:
+ # duplicate db object with new primary key (template_id)
+ self._db_session.expunge(db_template)
+ make_transient(db_template)
+ db_template.template_id = None
+ self._db_session.add(db_template)
+ await self._db_session.commit()
+ await self._db_session.refresh(db_template)
return db_template
+
+ async def get_image(self, image_path: str) -> Optional[models.Image]:
+ """
+ Get an image by its path.
+ """
+
+ image_dir, image_name = os.path.split(image_path)
+ if image_dir:
+ query = select(models.Image).\
+ where(models.Image.filename == image_name, models.Image.path.endswith(image_path))
+ else:
+ query = select(models.Image).where(models.Image.filename == image_name)
+ result = await self._db_session.execute(query)
+ return result.scalars().one_or_none()
+
+ async def add_image_to_template(
+ self,
+ template_id: UUID,
+ image: models.Image
+ ) -> Union[None, models.Template]:
+ """
+ Add an image to template.
+ """
+
+ query = select(models.Template).\
+ options(selectinload(models.Template.images)).\
+ where(models.Template.template_id == template_id)
+ result = await self._db_session.execute(query)
+ template_in_db = result.scalars().first()
+ if not template_in_db:
+ return None
+
+ template_in_db.images.append(image)
+ await self._db_session.commit()
+ await self._db_session.refresh(template_in_db)
+ return template_in_db
+
+ async def remove_image_from_template(
+ self,
+ template_id: UUID,
+ image: models.Image
+ ) -> Union[None, models.Template]:
+ """
+ Remove an image from a template.
+ """
+
+ query = select(models.Template).\
+ options(selectinload(models.Template.images)).\
+ where(models.Template.template_id == template_id)
+ result = await self._db_session.execute(query)
+ template_in_db = result.scalars().first()
+ if not template_in_db:
+ return None
+
+ if image in template_in_db.images:
+ template_in_db.images.remove(image)
+ await self._db_session.commit()
+ await self._db_session.refresh(template_in_db)
+ return template_in_db
diff --git a/gns3server/handlers/api/compute/qemu_handler.py b/gns3server/handlers/api/compute/qemu_handler.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/gns3server/handlers/api/compute/server_handler.py b/gns3server/handlers/api/compute/server_handler.py
new file mode 100644
index 00000000..f2e15c5f
--- /dev/null
+++ b/gns3server/handlers/api/compute/server_handler.py
@@ -0,0 +1,135 @@
+
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2015 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import psutil
+import platform
+
+from gns3server.web.route import Route
+from gns3server.config import Config
+from gns3server.schemas.version import VERSION_SCHEMA
+from gns3server.schemas.server_statistics import SERVER_STATISTICS_SCHEMA
+from gns3server.compute.port_manager import PortManager
+from gns3server.utils.cpu_percent import CpuPercent
+from gns3server.utils.path import get_default_project_directory
+from gns3server.version import __version__
+from aiohttp.web import HTTPConflict
+
+
+class ServerHandler:
+
+ @Route.get(
+ r"/version",
+ description="Retrieve the server version number",
+ output=VERSION_SCHEMA)
+ def version(request, response):
+
+ config = Config.instance()
+ local_server = config.get_section_config("Server").getboolean("local", False)
+ response.json({"version": __version__, "local": local_server})
+
+ @Route.get(
+ r"/statistics",
+ description="Retrieve server statistics",
+ output=SERVER_STATISTICS_SCHEMA,
+ status_codes={
+ 200: "Statistics information returned",
+ 409: "Conflict"
+ })
+ def statistics(request, response):
+
+ try:
+ memory_total = psutil.virtual_memory().total
+ memory_free = psutil.virtual_memory().available
+ memory_used = memory_total - memory_free # actual memory usage in a cross platform fashion
+ swap_total = psutil.swap_memory().total
+ swap_free = psutil.swap_memory().free
+ swap_used = psutil.swap_memory().used
+ cpu_percent = int(CpuPercent.get())
+ load_average_percent = [int(x / psutil.cpu_count() * 100) for x in psutil.getloadavg()]
+ memory_percent = int(psutil.virtual_memory().percent)
+ swap_percent = int(psutil.swap_memory().percent)
+ disk_usage_percent = int(psutil.disk_usage(get_default_project_directory()).percent)
+ except psutil.Error as e:
+ raise HTTPConflict(text="Psutil error detected: {}".format(e))
+ response.json({"memory_total": memory_total,
+ "memory_free": memory_free,
+ "memory_used": memory_used,
+ "swap_total": swap_total,
+ "swap_free": swap_free,
+ "swap_used": swap_used,
+ "cpu_usage_percent": cpu_percent,
+ "memory_usage_percent": memory_percent,
+ "swap_usage_percent": swap_percent,
+ "disk_usage_percent": disk_usage_percent,
+ "load_average_percent": load_average_percent})
+
+ @Route.get(
+ r"/debug",
+ description="Return debug information about the compute",
+ status_codes={
+ 201: "Written"
+ })
+ def debug(request, response):
+ response.content_type = "text/plain"
+ response.text = ServerHandler._getDebugData()
+
+ @staticmethod
+ def _getDebugData():
+ try:
+ addrs = ["* {}: {}".format(key, val) for key, val in psutil.net_if_addrs().items()]
+ except UnicodeDecodeError:
+ addrs = ["INVALID ADDR WITH UNICODE CHARACTERS"]
+
+ data = """Version: {version}
+OS: {os}
+Python: {python}
+CPU: {cpu}
+Memory: {memory}
+
+Networks:
+{addrs}
+""".format(
+ version=__version__,
+ os=platform.platform(),
+ python=platform.python_version(),
+ memory=psutil.virtual_memory(),
+ cpu=psutil.cpu_times(),
+ addrs="\n".join(addrs)
+ )
+
+ try:
+ connections = psutil.net_connections()
+ # You need to be root for OSX
+ except psutil.AccessDenied:
+ connections = None
+
+ if connections:
+ data += "\n\nConnections:\n"
+ for port in PortManager.instance().tcp_ports:
+ found = False
+ for open_port in connections:
+ if open_port.laddr[1] == port:
+ found = True
+ data += "TCP {}: {}\n".format(port, found)
+ for port in PortManager.instance().udp_ports:
+ found = False
+ for open_port in connections:
+ if open_port.laddr[1] == port:
+ found = True
+ data += "UDP {}: {}\n".format(port, found)
+ return data
diff --git a/gns3server/handlers/api/controller/server_handler.py b/gns3server/handlers/api/controller/server_handler.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/gns3server/schemas/__init__.py b/gns3server/schemas/__init__.py
index 7a8ec42f..5a3e99a3 100644
--- a/gns3server/schemas/__init__.py
+++ b/gns3server/schemas/__init__.py
@@ -23,6 +23,8 @@ from .version import Version
from .controller.links import LinkCreate, LinkUpdate, Link
from .controller.computes import ComputeCreate, ComputeUpdate, AutoIdlePC, Compute
from .controller.templates import TemplateCreate, TemplateUpdate, TemplateUsage, Template
+from .controller.images import Image, ImageType
+from .controller.appliances import ApplianceVersion, Appliance
from .controller.drawings import Drawing
from .controller.gns3vm import GNS3VM
from .controller.nodes import NodeCreate, NodeUpdate, NodeDuplicate, NodeCapture, Node
diff --git a/gns3server/schemas/compute/qemu_nodes.py b/gns3server/schemas/compute/qemu_nodes.py
index de464fef..2c9d33ed 100644
--- a/gns3server/schemas/compute/qemu_nodes.py
+++ b/gns3server/schemas/compute/qemu_nodes.py
@@ -195,7 +195,6 @@ class QemuBase(BaseModel):
mac_address: Optional[str] = Field(
None, description="QEMU MAC address", regex="^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$"
)
- legacy_networking: Optional[bool] = Field(None, description="Use QEMU legagy networking commands (-net syntax)")
replicate_network_connection_state: Optional[bool] = Field(
None, description="Replicate the network connection state for links in Qemu"
)
diff --git a/gns3server/schemas/controller/appliances.py b/gns3server/schemas/controller/appliances.py
new file mode 100644
index 00000000..5af72108
--- /dev/null
+++ b/gns3server/schemas/controller/appliances.py
@@ -0,0 +1,464 @@
+#
+# Copyright (C) 2021 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 .
+
+# Generated from JSON schema using https://github.com/koxudaxi/datamodel-code-generator
+
+from enum import Enum
+from typing import List, Optional, Union
+from uuid import UUID
+from pydantic import AnyUrl, BaseModel, EmailStr, Field, confloat, conint, constr
+
+
+class Category(Enum):
+
+ router = 'router'
+ multilayer_switch = 'multilayer_switch'
+ switch = 'switch'
+ firewall = 'firewall'
+ guest = 'guest'
+
+
+class RegistryVersion(Enum):
+
+ version1 = 1
+ version2 = 2
+ version3 = 3
+ version4 = 4
+ version5 = 5
+ version6 = 6
+
+
+class Status(Enum):
+
+ stable = 'stable'
+ experimental = 'experimental'
+ broken = 'broken'
+
+
+class Availability(Enum):
+
+ free = 'free'
+ with_registration = 'with-registration'
+ free_to_try = 'free-to-try'
+ service_contract = 'service-contract'
+
+
+class ConsoleType(Enum):
+
+ telnet = 'telnet'
+ vnc = 'vnc'
+ http = 'http'
+ https = 'https'
+ none = 'none'
+
+
+class Docker(BaseModel):
+
+ adapters: int = Field(..., title='Number of ethernet adapters')
+ image: str = Field(..., title='Docker image in the Docker Hub')
+ start_command: Optional[str] = Field(
+ None,
+ title='Command executed when the container start. Empty will use the default',
+ )
+ environment: Optional[str] = Field(None, title='One KEY=VAR environment by line')
+ console_type: Optional[ConsoleType] = Field(
+ None, title='Type of console connection for the administration of the appliance'
+ )
+ console_http_port: Optional[int] = Field(
+ None, description='Internal port in the container of the HTTP server'
+ )
+ console_http_path: Optional[str] = Field(
+ None, description='Path of the web interface'
+ )
+ extra_hosts: Optional[str] = Field(
+ None, description='Hosts which will be written to /etc/hosts into container'
+ )
+ extra_volumes: Optional[List[str]] = Field(
+ None,
+ description='Additional directories to make persistent that are not included in the images VOLUME directive',
+ )
+
+
+class Iou(BaseModel):
+
+ ethernet_adapters: int = Field(..., title='Number of ethernet adapters')
+ serial_adapters: int = Field(..., title='Number of serial adapters')
+ nvram: int = Field(..., title='Host NVRAM')
+ ram: int = Field(..., title='Host RAM')
+ startup_config: str = Field(..., title='Config loaded at startup')
+
+
+class Chassis(Enum):
+
+ chassis_1720 = '1720'
+ chassis_1721 = '1721'
+ chassis_1750 = '1750'
+ chassis_1751 = '1751'
+ chassis_1760 = '1760'
+ chassis_2610 = '2610'
+ chassis_2620 = '2620'
+ chassis_2610XM = '2610XM'
+ chassis_2620XM = '2620XM'
+ chassis_2650XM = '2650XM'
+ chassis_2621 = '2621'
+ chassis_2611XM = '2611XM'
+ chassis_2621XM = '2621XM'
+ chassis_2651XM = '2651XM'
+ chassis_3620 = '3620'
+ chassis_3640 = '3640'
+ chassis_3660 = '3660'
+
+
+class Platform(Enum):
+
+ c1700 = 'c1700'
+ c2600 = 'c2600'
+ c2691 = 'c2691'
+ c3725 = 'c3725'
+ c3745 = 'c3745'
+ c3600 = 'c3600'
+ c7200 = 'c7200'
+
+
+class Midplane(Enum):
+
+ std = 'std'
+ vxr = 'vxr'
+
+
+class Npe(Enum):
+
+ npe_100 = 'npe-100'
+ npe_150 = 'npe-150'
+ npe_175 = 'npe-175'
+ npe_200 = 'npe-200'
+ npe_225 = 'npe-225'
+ npe_300 = 'npe-300'
+ npe_400 = 'npe-400'
+ npe_g2 = 'npe-g2'
+
+
+class AdapterType(Enum):
+
+ e1000 = 'e1000'
+ e1000_82544gc = 'e1000-82544gc'
+ e1000_82545em = 'e1000-82545em'
+ e1000e = 'e1000e'
+ i82550 = 'i82550'
+ i82551 = 'i82551'
+ i82557a = 'i82557a'
+ i82557b = 'i82557b'
+ i82557c = 'i82557c'
+ i82558a = 'i82558a'
+ i82558b = 'i82558b'
+ i82559a = 'i82559a'
+ i82559b = 'i82559b'
+ i82559c = 'i82559c'
+ i82559er = 'i82559er'
+ i82562 = 'i82562'
+ i82801 = 'i82801'
+ ne2k_pci = 'ne2k_pci'
+ pcnet = 'pcnet'
+ rocker = 'rocker'
+ rtl8139 = 'rtl8139'
+ virtio = 'virtio'
+ virtio_net_pci = 'virtio-net-pci'
+ vmxnet3 = 'vmxnet3'
+
+
+class DiskInterface(Enum):
+
+ ide = 'ide'
+ sata = 'sata'
+ nvme = 'nvme'
+ scsi = 'scsi'
+ sd = 'sd'
+ mtd = 'mtd'
+ floppy = 'floppy'
+ pflash = 'pflash'
+ virtio = 'virtio'
+ none = 'none'
+
+
+class Arch(Enum):
+
+ aarch64 = 'aarch64'
+ alpha = 'alpha'
+ arm = 'arm'
+ cris = 'cris'
+ i386 = 'i386'
+ lm32 = 'lm32'
+ m68k = 'm68k'
+ microblaze = 'microblaze'
+ microblazeel = 'microblazeel'
+ mips = 'mips'
+ mips64 = 'mips64'
+ mips64el = 'mips64el'
+ mipsel = 'mipsel'
+ moxie = 'moxie'
+ or32 = 'or32'
+ ppc = 'ppc'
+ ppc64 = 'ppc64'
+ ppcemb = 'ppcemb'
+ s390x = 's390x'
+ sh4 = 'sh4'
+ sh4eb = 'sh4eb'
+ sparc = 'sparc'
+ sparc64 = 'sparc64'
+ tricore = 'tricore'
+ unicore32 = 'unicore32'
+ x86_64 = 'x86_64'
+ xtensa = 'xtensa'
+ xtensaeb = 'xtensaeb'
+
+
+class ConsoleType1(Enum):
+
+ telnet = 'telnet'
+ vnc = 'vnc'
+ spice = 'spice'
+ spice_agent = 'spice+agent'
+ none = 'none'
+
+
+class BootPriority(Enum):
+
+ c = 'c'
+ d = 'd'
+ n = 'n'
+ cn = 'cn'
+ cd = 'cd'
+ dn = 'dn'
+ dc = 'dc'
+ nc = 'nc'
+ nd = 'nd'
+
+
+class Kvm(Enum):
+
+ require = 'require'
+ allow = 'allow'
+ disable = 'disable'
+
+
+class ProcessPriority(Enum):
+
+ realtime = 'realtime'
+ very_high = 'very high'
+ high = 'high'
+ normal = 'normal'
+ low = 'low'
+ very_low = 'very low'
+ null = 'null'
+
+
+class Qemu(BaseModel):
+
+ adapter_type: AdapterType = Field(..., title='Type of network adapter')
+ adapters: int = Field(..., title='Number of adapters')
+ ram: int = Field(..., title='Ram allocated to the appliance (MB)')
+ cpus: Optional[int] = Field(None, title='Number of Virtual CPU')
+ hda_disk_interface: Optional[DiskInterface] = Field(
+ None, title='Disk interface for the installed hda_disk_image'
+ )
+ hdb_disk_interface: Optional[DiskInterface] = Field(
+ None, title='Disk interface for the installed hdb_disk_image'
+ )
+ hdc_disk_interface: Optional[DiskInterface] = Field(
+ None, title='Disk interface for the installed hdc_disk_image'
+ )
+ hdd_disk_interface: Optional[DiskInterface] = Field(
+ None, title='Disk interface for the installed hdd_disk_image'
+ )
+ arch: Arch = Field(..., title='Architecture emulated')
+ console_type: ConsoleType1 = Field(
+ ..., title='Type of console connection for the administration of the appliance'
+ )
+ boot_priority: Optional[BootPriority] = Field(
+ None,
+ title='Disk boot priority. Refer to -boot option in qemu manual for more details.',
+ )
+ kernel_command_line: Optional[str] = Field(
+ None, title='Command line parameters send to the kernel'
+ )
+ kvm: Kvm = Field(..., title='KVM requirements')
+ options: Optional[str] = Field(
+ None, title='Optional additional qemu command line options'
+ )
+ cpu_throttling: Optional[confloat(ge=0.0, le=100.0)] = Field(
+ None, title='Throttle the CPU'
+ )
+ process_priority: Optional[ProcessPriority] = Field(
+ None, title='Process priority for QEMU'
+ )
+
+
+class Compression(Enum):
+
+ bzip2 = 'bzip2'
+ gzip = 'gzip'
+ lzma = 'lzma'
+ xz = 'xz'
+ rar = 'rar'
+ zip = 'zip'
+ field_7z = '7z'
+
+
+class ApplianceImage(BaseModel):
+
+ filename: str = Field(..., title='Filename')
+ version: str = Field(..., title='Version of the file')
+ md5sum: str = Field(..., title='md5sum of the file', regex='^[a-f0-9]{32}$')
+ filesize: int = Field(..., title='File size in bytes')
+ download_url: Optional[Union[AnyUrl, constr(max_length=0)]] = Field(
+ None, title='Download url where you can download the appliance from a browser'
+ )
+ direct_download_url: Optional[Union[AnyUrl, constr(max_length=0)]] = Field(
+ None,
+ title='Optional. Non authenticated url to the image file where you can download the image.',
+ )
+ compression: Optional[Compression] = Field(
+ None, title='Optional, compression type of direct download url image.'
+ )
+
+
+class ApplianceVersionImages(BaseModel):
+
+ kernel_image: Optional[str] = Field(None, title='Kernel image')
+ initrd: Optional[str] = Field(None, title='Initrd disk image')
+ image: Optional[str] = Field(None, title='OS image')
+ bios_image: Optional[str] = Field(None, title='Bios image')
+ hda_disk_image: Optional[str] = Field(None, title='Hda disk image')
+ hdb_disk_image: Optional[str] = Field(None, title='Hdc disk image')
+ hdc_disk_image: Optional[str] = Field(None, title='Hdd disk image')
+ hdd_disk_image: Optional[str] = Field(None, title='Hdd diskimage')
+ cdrom_image: Optional[str] = Field(None, title='cdrom image')
+
+
+class ApplianceVersion(BaseModel):
+
+ name: str = Field(..., title='Name of the version')
+ idlepc: Optional[str] = Field(None, regex='^0x[0-9a-f]{8}')
+ images: Optional[ApplianceVersionImages] = Field(None, title='Images used for this version')
+
+
+class DynamipsSlot(Enum):
+
+ C7200_IO_2FE = 'C7200-IO-2FE'
+ C7200_IO_FE = 'C7200-IO-FE'
+ C7200_IO_GE_E = 'C7200-IO-GE-E'
+ NM_16ESW = 'NM-16ESW'
+ NM_1E = 'NM-1E'
+ NM_1FE_TX = 'NM-1FE-TX'
+ NM_4E = 'NM-4E'
+ NM_4T = 'NM-4T'
+ PA_2FE_TX = 'PA-2FE-TX'
+ PA_4E = 'PA-4E'
+ PA_4T_ = 'PA-4T+'
+ PA_8E = 'PA-8E'
+ PA_8T = 'PA-8T'
+ PA_A1 = 'PA-A1'
+ PA_FE_TX = 'PA-FE-TX'
+ PA_GE = 'PA-GE'
+ PA_POS_OC3 = 'PA-POS-OC3'
+ C2600_MB_2FE = 'C2600-MB-2FE'
+ C2600_MB_1E = 'C2600-MB-1E'
+ C1700_MB_1FE = 'C1700-MB-1FE'
+ C2600_MB_2E = 'C2600-MB-2E'
+ C2600_MB_1FE = 'C2600-MB-1FE'
+ C1700_MB_WIC1 = 'C1700-MB-WIC1'
+ GT96100_FE = 'GT96100-FE'
+ Leopard_2FE = 'Leopard-2FE'
+ _ = ''
+
+
+class DynamipsWic(Enum):
+
+ WIC_1ENET = 'WIC-1ENET'
+ WIC_1T = 'WIC-1T'
+ WIC_2T = 'WIC-2T'
+
+
+class Dynamips(BaseModel):
+
+ chassis: Optional[Chassis] = Field(None, title='Chassis type')
+ platform: Platform = Field(..., title='Platform type')
+ ram: conint(ge=1) = Field(..., title='Amount of ram')
+ nvram: conint(ge=1) = Field(..., title='Amount of nvram')
+ startup_config: Optional[str] = Field(None, title='Config loaded at startup')
+ wic0: Optional[DynamipsWic] = None
+ wic1: Optional[DynamipsWic] = None
+ wic2: Optional[DynamipsWic] = None
+ slot0: Optional[DynamipsSlot] = None
+ slot1: Optional[DynamipsSlot] = None
+ slot2: Optional[DynamipsSlot] = None
+ slot3: Optional[DynamipsSlot] = None
+ slot4: Optional[DynamipsSlot] = None
+ slot5: Optional[DynamipsSlot] = None
+ slot6: Optional[DynamipsSlot] = None
+ midplane: Optional[Midplane] = None
+ npe: Optional[Npe] = None
+
+
+class Appliance(BaseModel):
+
+ appliance_id: UUID = Field(..., title='Appliance ID')
+ name: str = Field(..., title='Appliance name')
+ category: Category = Field(..., title='Category of the appliance')
+ description: str = Field(
+ ..., title='Description of the appliance. Could be a marketing description'
+ )
+ vendor_name: str = Field(..., title='Name of the vendor')
+ vendor_url: Union[AnyUrl, constr(max_length=0)] = Field(..., title='Website of the vendor')
+ documentation_url: Optional[Union[AnyUrl, constr(max_length=0)]] = Field(
+ None,
+ title='An optional documentation for using the appliance on vendor website',
+ )
+ product_name: str = Field(..., title='Product name')
+ product_url: Optional[Union[AnyUrl, constr(max_length=0)]] = Field(
+ None, title='An optional product url on vendor website'
+ )
+ registry_version: RegistryVersion = Field(
+ ..., title='Version of the registry compatible with this appliance'
+ )
+ status: Status = Field(..., title='Document if the appliance is working or not')
+ availability: Optional[Availability] = Field(
+ None,
+ title='About image availability: can be downloaded directly; download requires a free registration; paid but a trial version (time or feature limited) is available; not available publicly',
+ )
+ maintainer: str = Field(..., title='Maintainer name')
+ maintainer_email: Union[EmailStr, constr(max_length=0)] = Field(..., title='Maintainer email')
+ usage: Optional[str] = Field(None, title='How to use the appliance')
+ symbol: Optional[str] = Field(None, title='An optional symbol for the appliance')
+ first_port_name: Optional[str] = Field(
+ None, title='Optional name of the first networking port example: eth0'
+ )
+ port_name_format: Optional[str] = Field(
+ None, title='Optional formating of the networking port example: eth{0}'
+ )
+ port_segment_size: Optional[int] = Field(
+ None,
+ title='Optional port segment size. A port segment is a block of port. For example Ethernet0/0 Ethernet0/1 is the module 0 with a port segment size of 2',
+ )
+ linked_clone: Optional[bool] = Field(
+ None, title="False if you don't want to use a single image for all nodes"
+ )
+ docker: Optional[Docker] = Field(None, title='Docker specific options')
+ iou: Optional[Iou] = Field(None, title='IOU specific options')
+ dynamips: Optional[Dynamips] = Field(None, title='Dynamips specific options')
+ qemu: Optional[Qemu] = Field(None, title='Qemu specific options')
+ images: Optional[List[ApplianceImage]] = Field(None, title='Images for this appliance')
+ versions: Optional[List[ApplianceVersion]] = Field(None, title='Versions of the appliance')
diff --git a/gns3server/schemas/controller/images.py b/gns3server/schemas/controller/images.py
new file mode 100644
index 00000000..bee6621e
--- /dev/null
+++ b/gns3server/schemas/controller/images.py
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2021 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+from pydantic import BaseModel, Field
+from enum import Enum
+
+from .base import DateTimeModelMixin
+
+
+class ImageType(str, Enum):
+
+ qemu = "qemu"
+ ios = "ios"
+ iou = "iou"
+
+
+class ImageBase(BaseModel):
+ """
+ Common image properties.
+ """
+
+ filename: str = Field(..., description="Image name")
+ image_type: ImageType = Field(..., description="Image type")
+ image_size: int = Field(..., description="Image size in bytes")
+ checksum: str = Field(..., description="Checksum value")
+ checksum_algorithm: str = Field(..., description="Checksum algorithm")
+
+
+class Image(DateTimeModelMixin, ImageBase):
+
+ class Config:
+ orm_mode = True
diff --git a/gns3server/schemas/controller/templates/__init__.py b/gns3server/schemas/controller/templates/__init__.py
index 74866b2e..14db9982 100644
--- a/gns3server/schemas/controller/templates/__init__.py
+++ b/gns3server/schemas/controller/templates/__init__.py
@@ -41,6 +41,7 @@ class TemplateBase(BaseModel):
template_id: Optional[UUID] = None
name: Optional[str] = None
+ version: Optional[str] = None
category: Optional[Category] = None
default_name_format: Optional[str] = None
symbol: Optional[str] = None
diff --git a/gns3server/schemas/controller/templates/qemu_templates.py b/gns3server/schemas/controller/templates/qemu_templates.py
index f69eb23a..68645595 100644
--- a/gns3server/schemas/controller/templates/qemu_templates.py
+++ b/gns3server/schemas/controller/templates/qemu_templates.py
@@ -74,7 +74,6 @@ class QemuTemplate(TemplateBase):
kernel_image: Optional[str] = Field("", description="QEMU kernel image path")
bios_image: Optional[str] = Field("", description="QEMU bios image path")
kernel_command_line: Optional[str] = Field("", description="QEMU kernel command line")
- legacy_networking: Optional[bool] = Field(False, description="Use QEMU legagy networking commands (-net syntax)")
replicate_network_connection_state: Optional[bool] = Field(
True, description="Replicate the network connection state for links in Qemu"
)
diff --git a/gns3server/services/templates.py b/gns3server/services/templates.py
index c36bfeb6..569f70e8 100644
--- a/gns3server/services/templates.py
+++ b/gns3server/services/templates.py
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+import os
import uuid
import pydantic
@@ -22,9 +23,10 @@ from fastapi.encoders import jsonable_encoder
from typing import List
from gns3server import schemas
+import gns3server.db.models as models
from gns3server.db.repositories.templates import TemplatesRepository
-from gns3server.controller import Controller
from gns3server.controller.controller_error import (
+ ControllerError,
ControllerBadRequestError,
ControllerNotFoundError,
ControllerForbiddenError,
@@ -56,7 +58,7 @@ DYNAMIPS_PLATFORM_TO_SHEMA = {
# built-in templates have their compute_id set to None to tell clients to select a compute
BUILTIN_TEMPLATES = [
{
- "template_id": uuid.uuid3(uuid.NAMESPACE_DNS, "cloud"),
+ "template_id": uuid.uuid5(uuid.NAMESPACE_X500, "cloud"),
"template_type": "cloud",
"name": "Cloud",
"default_name_format": "Cloud{0}",
@@ -66,7 +68,7 @@ BUILTIN_TEMPLATES = [
"builtin": True,
},
{
- "template_id": uuid.uuid3(uuid.NAMESPACE_DNS, "nat"),
+ "template_id": uuid.uuid5(uuid.NAMESPACE_X500, "nat"),
"template_type": "nat",
"name": "NAT",
"default_name_format": "NAT{0}",
@@ -76,7 +78,7 @@ BUILTIN_TEMPLATES = [
"builtin": True,
},
{
- "template_id": uuid.uuid3(uuid.NAMESPACE_DNS, "vpcs"),
+ "template_id": uuid.uuid5(uuid.NAMESPACE_X500, "vpcs"),
"template_type": "vpcs",
"name": "VPCS",
"default_name_format": "PC{0}",
@@ -87,7 +89,7 @@ BUILTIN_TEMPLATES = [
"builtin": True,
},
{
- "template_id": uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_switch"),
+ "template_id": uuid.uuid5(uuid.NAMESPACE_X500, "ethernet_switch"),
"template_type": "ethernet_switch",
"name": "Ethernet switch",
"console_type": "none",
@@ -98,7 +100,7 @@ BUILTIN_TEMPLATES = [
"builtin": True,
},
{
- "template_id": uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_hub"),
+ "template_id": uuid.uuid5(uuid.NAMESPACE_X500, "ethernet_hub"),
"template_type": "ethernet_hub",
"name": "Ethernet hub",
"default_name_format": "Hub{0}",
@@ -108,7 +110,7 @@ BUILTIN_TEMPLATES = [
"builtin": True,
},
{
- "template_id": uuid.uuid3(uuid.NAMESPACE_DNS, "frame_relay_switch"),
+ "template_id": uuid.uuid5(uuid.NAMESPACE_X500, "frame_relay_switch"),
"template_type": "frame_relay_switch",
"name": "Frame Relay switch",
"default_name_format": "FRSW{0}",
@@ -118,7 +120,7 @@ BUILTIN_TEMPLATES = [
"builtin": True,
},
{
- "template_id": uuid.uuid3(uuid.NAMESPACE_DNS, "atm_switch"),
+ "template_id": uuid.uuid5(uuid.NAMESPACE_X500, "atm_switch"),
"template_type": "atm_switch",
"name": "ATM switch",
"default_name_format": "ATMSW{0}",
@@ -131,9 +133,11 @@ BUILTIN_TEMPLATES = [
class TemplatesService:
+
def __init__(self, templates_repo: TemplatesRepository):
self._templates_repo = templates_repo
+ from gns3server.controller import Controller
self._controller = Controller.instance()
def get_builtin_template(self, template_id: UUID) -> dict:
@@ -152,8 +156,53 @@ class TemplatesService:
templates.append(jsonable_encoder(builtin_template))
return templates
+ async def _find_image(self, image_path: str):
+
+ image = await self._templates_repo.get_image(image_path)
+ if not image or not os.path.exists(image.path):
+ raise ControllerNotFoundError(f"Image '{image_path}' could not be found")
+ return image
+
+ async def _find_images(self, template_type: str, settings: dict) -> List[models.Image]:
+
+ images_to_add_to_template = []
+ if template_type == "dynamips":
+ if settings["image"]:
+ image = await self._find_image(settings["image"])
+ if image.image_type != "ios":
+ raise ControllerBadRequestError(
+ f"Image '{image.filename}' type is not 'ios' but '{image.image_type}'"
+ )
+ images_to_add_to_template.append(image)
+ elif template_type == "iou":
+ if settings["path"]:
+ image = await self._find_image(settings["path"])
+ if image.image_type != "iou":
+ raise ControllerBadRequestError(
+ f"Image '{image.filename}' type is not 'iou' but '{image.image_type}'"
+ )
+ images_to_add_to_template.append(image)
+ elif template_type == "qemu":
+ for key, value in settings.items():
+ if key.endswith("_image") and value:
+ image = await self._find_image(value)
+ if image.image_type != "qemu":
+ raise ControllerBadRequestError(
+ f"Image '{image.filename}' type is not 'qemu' but '{image.image_type}'"
+ )
+ if image not in images_to_add_to_template:
+ images_to_add_to_template.append(image)
+ return images_to_add_to_template
+
async def create_template(self, template_create: schemas.TemplateCreate) -> dict:
+ if await self._templates_repo.get_template_by_name_and_version(template_create.name, template_create.version):
+ if template_create.version:
+ raise ControllerError(f"A template with name '{template_create.name}' and "
+ f"version {template_create.version} already exists")
+ else:
+ raise ControllerError(f"A template with name '{template_create.name}' already exists")
+
try:
# get the default template settings
template_settings = jsonable_encoder(template_create, exclude_unset=True)
@@ -167,7 +216,11 @@ class TemplatesService:
settings = dynamips_template_settings_with_defaults.dict()
except pydantic.ValidationError as e:
raise ControllerBadRequestError(f"JSON schema error received while creating new template: {e}")
+
+ images_to_add_to_template = await self._find_images(template_create.template_type, settings)
db_template = await self._templates_repo.create_template(template_create.template_type, settings)
+ for image in images_to_add_to_template:
+ await self._templates_repo.add_image_to_template(db_template.template_id, image)
template = db_template.asjson()
self._controller.notification.controller_emit("template.created", template)
return template
@@ -183,13 +236,34 @@ class TemplatesService:
raise ControllerNotFoundError(f"Template '{template_id}' not found")
return template
+ async def _remove_image(self, template_id: UUID, image_path:str) -> None:
+
+ image = await self._templates_repo.get_image(image_path)
+ await self._templates_repo.remove_image_from_template(template_id, image)
+
async def update_template(self, template_id: UUID, template_update: schemas.TemplateUpdate) -> dict:
if self.get_builtin_template(template_id):
raise ControllerForbiddenError(f"Template '{template_id}' cannot be updated because it is built-in")
- db_template = await self._templates_repo.update_template(template_id, template_update)
+ template_settings = jsonable_encoder(template_update, exclude_unset=True)
+
+ db_template = await self._templates_repo.get_template(template_id)
if not db_template:
raise ControllerNotFoundError(f"Template '{template_id}' not found")
+
+ images_to_add_to_template = await self._find_images(db_template.template_type, template_settings)
+ if db_template.template_type == "dynamips" and "image" in template_settings:
+ await self._remove_image(db_template.template_id, db_template.image)
+ elif db_template.template_type == "iou" and "path" in template_settings:
+ await self._remove_image(db_template.template_id, db_template.path)
+ elif db_template.template_type == "qemu":
+ for key in template_update.dict().keys():
+ if key.endswith("_image") and key in template_settings:
+ await self._remove_image(db_template.template_id, db_template.__dict__[key])
+
+ db_template = await self._templates_repo.update_template(db_template, template_settings)
+ for image in images_to_add_to_template:
+ await self._templates_repo.add_image_to_template(db_template.template_id, image)
template = db_template.asjson()
self._controller.notification.controller_emit("template.updated", template)
return template
diff --git a/gns3server/static/web-ui/26.a7470e50128ddf7860c4.js b/gns3server/static/web-ui/26.a7470e50128ddf7860c4.js
deleted file mode 100644
index 51fad865..00000000
--- a/gns3server/static/web-ui/26.a7470e50128ddf7860c4.js
+++ /dev/null
@@ -1 +0,0 @@
-(self.webpackChunkgns3_web_ui=self.webpackChunkgns3_web_ui||[]).push([[26],{91026:function(t,e,n){"use strict";n.r(e),n.d(e,{TopologySummaryComponent:function(){return F}});var i=n(37602),o=n(96852),s=n(14200),r=n(36889),a=n(3941),p=n(15132),c=n(40098),l=n(39095),u=n(88802),g=n(73044),d=n(59412),h=n(93386);function m(t,e){if(1&t){var n=i.EpF();i.TgZ(0,"div",2),i.NdJ("mousemove",function(t){return i.CHM(n),i.oxw().dragWidget(t)},!1,i.evT)("mouseup",function(){return i.CHM(n),i.oxw().toggleDragging(!1)},!1,i.evT),i.qZA()}}function f(t,e){1&t&&(i.O4$(),i.TgZ(0,"svg",28),i._UZ(1,"rect",29),i.qZA())}function y(t,e){1&t&&(i.O4$(),i.TgZ(0,"svg",28),i._UZ(1,"rect",30),i.qZA())}function b(t,e){1&t&&(i.O4$(),i.TgZ(0,"svg",28),i._UZ(1,"rect",31),i.qZA())}function v(t,e){if(1&t&&(i.TgZ(0,"div"),i._uU(1),i.qZA()),2&t){var n=i.oxw().$implicit;i.xp6(1),i.lnq(" ",n.console_type," ",n.console_host,":",n.console," ")}}function x(t,e){1&t&&(i.TgZ(0,"div"),i._uU(1," none "),i.qZA())}function Z(t,e){if(1&t&&(i.TgZ(0,"div",25),i.TgZ(1,"div"),i.YNc(2,f,2,0,"svg",26),i.YNc(3,y,2,0,"svg",26),i.YNc(4,b,2,0,"svg",26),i._uU(5),i.qZA(),i.YNc(6,v,2,3,"div",27),i.YNc(7,x,2,0,"div",27),i.qZA()),2&t){var n=e.$implicit;i.xp6(2),i.Q6J("ngIf","started"===n.status),i.xp6(1),i.Q6J("ngIf","suspended"===n.status),i.xp6(1),i.Q6J("ngIf","stopped"===n.status),i.xp6(1),i.hij(" ",n.name," "),i.xp6(1),i.Q6J("ngIf",null!=n.console&&null!=n.console&&"none"!=n.console_type),i.xp6(1),i.Q6J("ngIf",null==n.console||"none"===n.console_type)}}function C(t,e){1&t&&(i.O4$(),i.TgZ(0,"svg",28),i._UZ(1,"rect",29),i.qZA())}function S(t,e){1&t&&(i.O4$(),i.TgZ(0,"svg",28),i._UZ(1,"rect",31),i.qZA())}function _(t,e){if(1&t&&(i.TgZ(0,"div",25),i.TgZ(1,"div"),i.YNc(2,C,2,0,"svg",26),i.YNc(3,S,2,0,"svg",26),i._uU(4),i.qZA(),i.TgZ(5,"div"),i._uU(6),i.qZA(),i.TgZ(7,"div"),i._uU(8),i.qZA(),i.qZA()),2&t){var n=e.$implicit,o=i.oxw(2);i.xp6(2),i.Q6J("ngIf",n.connected),i.xp6(1),i.Q6J("ngIf",!n.connected),i.xp6(1),i.hij(" ",n.name," "),i.xp6(2),i.hij(" ",n.host," "),i.xp6(2),i.hij(" ",o.server.location," ")}}var w=function(t){return{lightTheme:t}},T=function(){return{right:!0,left:!0,bottom:!0,top:!0}};function E(t,e){if(1&t){var n=i.EpF();i.TgZ(0,"div",3),i.NdJ("mousedown",function(){return i.CHM(n),i.oxw().toggleDragging(!0)})("resizeStart",function(){return i.CHM(n),i.oxw().toggleDragging(!1)})("resizeEnd",function(t){return i.CHM(n),i.oxw().onResizeEnd(t)}),i.TgZ(1,"div",4),i.TgZ(2,"mat-tab-group"),i.TgZ(3,"mat-tab",5),i.NdJ("click",function(){return i.CHM(n),i.oxw().toggleTopologyVisibility(!0)}),i.TgZ(4,"div",6),i.TgZ(5,"div",7),i.TgZ(6,"mat-select",8),i.TgZ(7,"mat-optgroup",9),i.TgZ(8,"mat-option",10),i.NdJ("onSelectionChange",function(){return i.CHM(n),i.oxw().applyStatusFilter("started")}),i._uU(9,"started"),i.qZA(),i.TgZ(10,"mat-option",11),i.NdJ("onSelectionChange",function(){return i.CHM(n),i.oxw().applyStatusFilter("suspended")}),i._uU(11,"suspended"),i.qZA(),i.TgZ(12,"mat-option",12),i.NdJ("onSelectionChange",function(){return i.CHM(n),i.oxw().applyStatusFilter("stopped")}),i._uU(13,"stopped"),i.qZA(),i.qZA(),i.TgZ(14,"mat-optgroup",13),i.TgZ(15,"mat-option",14),i.NdJ("onSelectionChange",function(){return i.CHM(n),i.oxw().applyCaptureFilter("capture")}),i._uU(16,"active capture(s)"),i.qZA(),i.TgZ(17,"mat-option",15),i.NdJ("onSelectionChange",function(){return i.CHM(n),i.oxw().applyCaptureFilter("packet")}),i._uU(18,"active packet captures"),i.qZA(),i.qZA(),i.qZA(),i.qZA(),i.TgZ(19,"div",16),i.TgZ(20,"mat-select",17),i.NdJ("selectionChange",function(){return i.CHM(n),i.oxw().setSortingOrder()})("valueChange",function(t){return i.CHM(n),i.oxw().sortingOrder=t}),i.TgZ(21,"mat-option",18),i._uU(22,"sort by name ascending"),i.qZA(),i.TgZ(23,"mat-option",19),i._uU(24,"sort by name descending"),i.qZA(),i.qZA(),i.qZA(),i._UZ(25,"mat-divider",20),i.TgZ(26,"div",21),i.YNc(27,Z,8,6,"div",22),i.qZA(),i.qZA(),i.qZA(),i.TgZ(28,"mat-tab",23),i.NdJ("click",function(){return i.CHM(n),i.oxw().toggleTopologyVisibility(!1)}),i.TgZ(29,"div",6),i.TgZ(30,"div",24),i.YNc(31,_,9,5,"div",22),i.qZA(),i.qZA(),i.qZA(),i.qZA(),i.qZA(),i.qZA()}if(2&t){var o=i.oxw();i.Q6J("ngStyle",o.style)("ngClass",i.VKq(9,w,o.isLightThemeEnabled))("validateResize",o.validate)("resizeEdges",i.DdM(11,T))("enableGhostResize",!0),i.xp6(20),i.Q6J("value",o.sortingOrder),i.xp6(6),i.Q6J("ngStyle",o.styleInside),i.xp6(1),i.Q6J("ngForOf",o.filteredNodes),i.xp6(4),i.Q6J("ngForOf",o.computes)}}var F=function(){function t(t,e,n,o,s){this.nodesDataSource=t,this.projectService=e,this.computeService=n,this.linksDataSource=o,this.themeService=s,this.closeTopologySummary=new i.vpe,this.style={},this.styleInside={height:"280px"},this.subscriptions=[],this.nodes=[],this.filteredNodes=[],this.sortingOrder="asc",this.startedStatusFilterEnabled=!1,this.suspendedStatusFilterEnabled=!1,this.stoppedStatusFilterEnabled=!1,this.captureFilterEnabled=!1,this.packetFilterEnabled=!1,this.computes=[],this.isTopologyVisible=!0,this.isDraggingEnabled=!1,this.isLightThemeEnabled=!1}return t.prototype.ngOnInit=function(){var t=this;this.isLightThemeEnabled="light"===this.themeService.getActualTheme(),this.subscriptions.push(this.nodesDataSource.changes.subscribe(function(e){t.nodes=e,t.nodes.forEach(function(e){"0.0.0.0"!==e.console_host&&"0:0:0:0:0:0:0:0"!==e.console_host&&"::"!==e.console_host||(e.console_host=t.server.host)}),t.filteredNodes=e.sort("asc"===t.sortingOrder?t.compareAsc:t.compareDesc)})),this.projectService.getStatistics(this.server,this.project.project_id).subscribe(function(e){t.projectsStatistics=e}),this.computeService.getComputes(this.server).subscribe(function(e){t.computes=e}),this.style={top:"60px",right:"0px",width:"320px",height:"400px"}},t.prototype.toggleDragging=function(t){this.isDraggingEnabled=t},t.prototype.dragWidget=function(t){var e=Number(t.movementX),n=Number(t.movementY),i=Number(this.style.width.split("px")[0]),o=Number(this.style.height.split("px")[0]),s=Number(this.style.top.split("px")[0])+n;if(this.style.left){var r=Number(this.style.left.split("px")[0])+e;this.style={position:"fixed",left:r+"px",top:s+"px",width:i+"px",height:o+"px"}}else{var a=Number(this.style.right.split("px")[0])-e;this.style={position:"fixed",right:a+"px",top:s+"px",width:i+"px",height:o+"px"}}},t.prototype.validate=function(t){return!(t.rectangle.width&&t.rectangle.height&&(t.rectangle.width<290||t.rectangle.height<260))},t.prototype.onResizeEnd=function(t){this.style={position:"fixed",left:t.rectangle.left+"px",top:t.rectangle.top+"px",width:t.rectangle.width+"px",height:t.rectangle.height+"px"},this.styleInside={height:t.rectangle.height-120+"px"}},t.prototype.toggleTopologyVisibility=function(t){this.isTopologyVisible=t},t.prototype.compareAsc=function(t,e){return t.name
-
+
@@ -46,6 +46,6 @@
gtag('config', 'G-5D6FZL9923');
-
+