gns3-server 3.0.0rc1__py3-none-any.whl → 3.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of gns3-server might be problematic. Click here for more details.
- {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/METADATA +20 -19
- {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/RECORD +89 -79
- {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/WHEEL +1 -1
- gns3server/api/routes/compute/cloud_nodes.py +1 -1
- gns3server/api/routes/compute/docker_nodes.py +3 -0
- gns3server/api/routes/compute/nat_nodes.py +1 -1
- gns3server/api/routes/compute/vmware_nodes.py +1 -1
- gns3server/api/routes/compute/vpcs_nodes.py +10 -4
- gns3server/api/routes/controller/projects.py +29 -3
- gns3server/api/routes/controller/users.py +2 -2
- gns3server/api/routes/index.py +3 -3
- gns3server/api/server.py +38 -3
- gns3server/appliances/almalinux.gns3a +6 -6
- gns3server/appliances/arista-veos.gns3a +20 -514
- gns3server/appliances/cisco-7200.gns3a +26 -0
- gns3server/appliances/cisco-asav.gns3a +14 -1
- gns3server/appliances/cisco-csr1000v.gns3a +28 -2
- gns3server/appliances/cisco-iou-l2.gns3a +16 -4
- gns3server/appliances/cisco-iou-l3.gns3a +16 -4
- gns3server/appliances/cisco-vWLC.gns3a +29 -1
- gns3server/appliances/fortigate.gns3a +3 -3
- gns3server/appliances/hbcd-pe.gns3a +62 -0
- gns3server/appliances/innovaphone-app.gns3a +50 -0
- gns3server/appliances/innovaphone-ipva.gns3a +78 -0
- gns3server/appliances/mikrotik-chr.gns3a +30 -99
- gns3server/appliances/nixos.gns3a +52 -0
- gns3server/appliances/opnsense.gns3a +13 -0
- gns3server/appliances/pfsense.gns3a +14 -0
- gns3server/appliances/reactos.gns3a +10 -10
- gns3server/appliances/truenas.gns3a +104 -0
- gns3server/appliances/ubuntu-cloud.gns3a +35 -20
- gns3server/appliances/ubuntu-gui.gns3a +13 -0
- gns3server/appliances/viptela-edge-genericx86-64.gns3a +28 -2
- gns3server/appliances/viptela-smart-genericx86-64.gns3a +27 -1
- gns3server/appliances/viptela-vmanage-genericx86-64.gns3a +32 -4
- gns3server/appliances/vyos.gns3a +95 -98
- gns3server/compute/base_node.py +1 -0
- gns3server/compute/docker/docker_vm.py +56 -2
- gns3server/compute/docker/resources/init.sh +5 -2
- gns3server/compute/dynamips/__init__.py +0 -4
- gns3server/compute/dynamips/nodes/router.py +20 -0
- gns3server/compute/iou/iou_vm.py +22 -12
- gns3server/compute/notification_manager.py +2 -2
- gns3server/compute/qemu/qemu_vm.py +0 -5
- gns3server/controller/__init__.py +35 -25
- gns3server/controller/appliance_manager.py +2 -4
- gns3server/controller/compute.py +1 -1
- gns3server/controller/export_project.py +18 -14
- gns3server/controller/import_project.py +21 -0
- gns3server/controller/node.py +10 -8
- gns3server/controller/notification.py +4 -4
- gns3server/controller/project.py +88 -5
- gns3server/controller/symbols.py +1 -1
- gns3server/controller/topology.py +1 -1
- gns3server/crash_report.py +1 -1
- gns3server/db/models/templates.py +1 -0
- gns3server/db/repositories/pools.py +1 -1
- gns3server/db/tasks.py +1 -1
- gns3server/db_migrations/versions/9a5292aa4389_add_mac_address_field_in_docker_.py +27 -0
- gns3server/disks/empty100G.qcow2 +0 -0
- gns3server/disks/empty200G.qcow2 +0 -0
- gns3server/disks/empty30G.qcow2 +0 -0
- gns3server/disks/empty8G.qcow2 +0 -0
- gns3server/schemas/compute/docker_nodes.py +1 -0
- gns3server/schemas/compute/ethernet_switch_nodes.py +1 -1
- gns3server/schemas/config.py +1 -1
- gns3server/schemas/controller/templates/cloud_templates.py +2 -2
- gns3server/schemas/controller/templates/docker_templates.py +4 -3
- gns3server/schemas/controller/templates/dynamips_templates.py +5 -5
- gns3server/schemas/controller/templates/ethernet_hub_templates.py +1 -1
- gns3server/schemas/controller/templates/ethernet_switch_templates.py +2 -2
- gns3server/schemas/controller/templates/iou_templates.py +2 -2
- gns3server/schemas/controller/templates/qemu_templates.py +12 -12
- gns3server/schemas/controller/templates/virtualbox_templates.py +4 -5
- gns3server/schemas/controller/templates/vmware_templates.py +4 -4
- gns3server/schemas/controller/templates/vpcs_templates.py +2 -2
- gns3server/static/favicon.ico +0 -0
- gns3server/static/redoc.standalone.js +1782 -0
- gns3server/static/swagger-ui-bundle.js +2 -0
- gns3server/static/swagger-ui.css +3 -0
- gns3server/static/web-ui/index.html +1 -1
- gns3server/static/web-ui/{main.4185a8e61824af0d.js → main.e55eeff5c0ba1cf4.js} +1 -1
- gns3server/utils/__init__.py +12 -0
- gns3server/utils/asyncio/aiozipstream.py +15 -11
- gns3server/utils/images.py +45 -35
- gns3server/version.py +2 -2
- {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/LICENSE +0 -0
- {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/entry_points.txt +0 -0
- {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/top_level.txt +0 -0
|
@@ -426,22 +426,48 @@ async def import_project(
|
|
|
426
426
|
status_code=status.HTTP_201_CREATED,
|
|
427
427
|
response_model=schemas.Project,
|
|
428
428
|
responses={**responses, 409: {"model": schemas.ErrorMessage, "description": "Could not duplicate project"}},
|
|
429
|
-
dependencies=[Depends(has_privilege("Project.
|
|
429
|
+
dependencies=[Depends(has_privilege("Project.Audit"))]
|
|
430
430
|
)
|
|
431
431
|
async def duplicate_project(
|
|
432
432
|
project_data: schemas.ProjectDuplicate,
|
|
433
|
-
project: Project = Depends(dep_project)
|
|
433
|
+
project: Project = Depends(dep_project),
|
|
434
|
+
current_user: schemas.User = Depends(get_current_active_user),
|
|
435
|
+
rbac_repo: RbacRepository = Depends(get_repository(RbacRepository)),
|
|
436
|
+
pools_repo: ResourcePoolsRepository = Depends(get_repository(ResourcePoolsRepository))
|
|
434
437
|
) -> schemas.Project:
|
|
435
438
|
"""
|
|
436
439
|
Duplicate a project.
|
|
437
440
|
|
|
438
|
-
Required privilege: Project.
|
|
441
|
+
Required privilege: Project.Audit
|
|
439
442
|
"""
|
|
440
443
|
|
|
444
|
+
pool_memberships = await pools_repo.get_resource_memberships(project.id)
|
|
445
|
+
|
|
446
|
+
# check if the project can be duplicated somewhere (either in a pool or in the root)
|
|
447
|
+
if not current_user.is_superadmin:
|
|
448
|
+
can_be_duplicated_somewhere = False
|
|
449
|
+
if pool_memberships:
|
|
450
|
+
for pool in pool_memberships:
|
|
451
|
+
if await rbac_repo.check_user_has_privilege(current_user.user_id, f"/pools/{pool.resource_pool_id}", "Project.Allocate"):
|
|
452
|
+
can_be_duplicated_somewhere = True
|
|
453
|
+
break
|
|
454
|
+
|
|
455
|
+
if not can_be_duplicated_somewhere and not await rbac_repo.check_user_has_privilege(current_user.user_id, "/projects", "Project.Allocate"):
|
|
456
|
+
log.warning(f"Project {project.name} cannot be duplicated anywhere")
|
|
457
|
+
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
|
|
458
|
+
|
|
441
459
|
reset_mac_addresses = project_data.reset_mac_addresses
|
|
442
460
|
new_project = await project.duplicate(
|
|
443
461
|
name=project_data.name, reset_mac_addresses=reset_mac_addresses
|
|
444
462
|
)
|
|
463
|
+
|
|
464
|
+
# Add the new project in the same resource pools if the duplicated project belongs to any
|
|
465
|
+
if pool_memberships:
|
|
466
|
+
resource_create = schemas.ResourceCreate(resource_id=new_project.id, resource_type="project", name=new_project.name)
|
|
467
|
+
resource = await pools_repo.create_resource(resource_create)
|
|
468
|
+
for pool in pool_memberships:
|
|
469
|
+
await pools_repo.add_resource_to_pool(pool.resource_pool_id, resource)
|
|
470
|
+
|
|
445
471
|
return new_project.asdict()
|
|
446
472
|
|
|
447
473
|
|
|
@@ -54,7 +54,7 @@ async def login(
|
|
|
54
54
|
) -> schemas.Token:
|
|
55
55
|
"""
|
|
56
56
|
Default user login method using forms (x-www-form-urlencoded).
|
|
57
|
-
Example: curl http://host:port/v3/users/login -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin&password=admin"
|
|
57
|
+
Example: curl -X POST http://host:port/v3/access/users/login -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin&password=admin"
|
|
58
58
|
"""
|
|
59
59
|
|
|
60
60
|
user = await users_repo.authenticate_user(username=form_data.username, password=form_data.password)
|
|
@@ -76,7 +76,7 @@ async def authenticate(
|
|
|
76
76
|
) -> schemas.Token:
|
|
77
77
|
"""
|
|
78
78
|
Alternative authentication method using json.
|
|
79
|
-
Example: curl http://host:port/v3/users/authenticate -d '{"username": "admin", "password": "admin"}' -H "Content-Type: application/json"
|
|
79
|
+
Example: curl -X POST http://host:port/v3/access/users/authenticate -d '{"username": "admin", "password": "admin"}' -H "Content-Type: application/json"
|
|
80
80
|
"""
|
|
81
81
|
|
|
82
82
|
user = await users_repo.authenticate_user(username=user_credentials.username, password=user_credentials.password)
|
gns3server/api/routes/index.py
CHANGED
|
@@ -27,20 +27,20 @@ router = APIRouter()
|
|
|
27
27
|
templates = Jinja2Templates(directory=os.path.join("gns3server", "templates"))
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
@router.get("/")
|
|
30
|
+
@router.get("/", include_in_schema=False)
|
|
31
31
|
async def root():
|
|
32
32
|
|
|
33
33
|
return RedirectResponse("/static/web-ui/bundled", status_code=308) # permanent redirect
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
@router.get("/debug", response_class=HTMLResponse, deprecated=True)
|
|
36
|
+
@router.get("/debug", response_class=HTMLResponse, deprecated=True, include_in_schema=False)
|
|
37
37
|
def debug(request: Request):
|
|
38
38
|
|
|
39
39
|
kwargs = {"request": request, "gns3_version": __version__, "gns3_host": request.client.host}
|
|
40
40
|
return templates.TemplateResponse("index.html", kwargs)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
@router.get("/static/web-ui/{file_path:path}", description="Web user interface")
|
|
43
|
+
@router.get("/static/web-ui/{file_path:path}", description="Web user interface", include_in_schema=False)
|
|
44
44
|
async def web_ui(file_path: str):
|
|
45
45
|
|
|
46
46
|
file_path = os.path.normpath(file_path).strip("/")
|
gns3server/api/server.py
CHANGED
|
@@ -19,15 +19,20 @@
|
|
|
19
19
|
FastAPI app
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
import time
|
|
23
|
-
|
|
24
22
|
from fastapi import FastAPI, Request, HTTPException, status
|
|
25
23
|
from fastapi.middleware.cors import CORSMiddleware
|
|
26
24
|
from fastapi.responses import JSONResponse
|
|
27
25
|
from fastapi.exceptions import RequestValidationError
|
|
26
|
+
from fastapi.staticfiles import StaticFiles
|
|
28
27
|
from sqlalchemy.exc import SQLAlchemyError
|
|
29
28
|
from uvicorn.main import Server as UvicornServer
|
|
30
29
|
|
|
30
|
+
from fastapi.openapi.docs import (
|
|
31
|
+
get_redoc_html,
|
|
32
|
+
get_swagger_ui_html,
|
|
33
|
+
get_swagger_ui_oauth2_redirect_html,
|
|
34
|
+
)
|
|
35
|
+
|
|
31
36
|
from gns3server.controller.controller_error import (
|
|
32
37
|
ControllerError,
|
|
33
38
|
ControllerNotFoundError,
|
|
@@ -51,7 +56,11 @@ log = logging.getLogger(__name__)
|
|
|
51
56
|
def get_application() -> FastAPI:
|
|
52
57
|
|
|
53
58
|
application = FastAPI(
|
|
54
|
-
title="GNS3 controller API",
|
|
59
|
+
title="GNS3 controller API",
|
|
60
|
+
description="This page describes the public controller API for GNS3",
|
|
61
|
+
version="v3",
|
|
62
|
+
docs_url=None,
|
|
63
|
+
redoc_url=None
|
|
55
64
|
)
|
|
56
65
|
|
|
57
66
|
application.add_middleware(
|
|
@@ -66,6 +75,7 @@ def get_application() -> FastAPI:
|
|
|
66
75
|
application.add_event_handler("shutdown", tasks.create_shutdown_handler(application))
|
|
67
76
|
application.include_router(index.router, tags=["Index"])
|
|
68
77
|
application.include_router(controller.router, prefix="/v3")
|
|
78
|
+
application.mount("/static", StaticFiles(packages=[('gns3server', 'static')]), name="static")
|
|
69
79
|
application.mount("/v3/compute", compute_api, name="compute")
|
|
70
80
|
|
|
71
81
|
return application
|
|
@@ -85,6 +95,31 @@ def handle_exit(*args, **kwargs):
|
|
|
85
95
|
|
|
86
96
|
UvicornServer.handle_exit = handle_exit
|
|
87
97
|
|
|
98
|
+
# Configure self-hosting JavaScript and CSS for docs
|
|
99
|
+
@app.get("/docs", include_in_schema=False)
|
|
100
|
+
async def custom_swagger_ui_html():
|
|
101
|
+
return get_swagger_ui_html(
|
|
102
|
+
openapi_url=app.openapi_url,
|
|
103
|
+
title=app.title + " - Swagger UI",
|
|
104
|
+
oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
|
|
105
|
+
swagger_js_url="/static/swagger-ui-bundle.js",
|
|
106
|
+
swagger_css_url="/static/swagger-ui.css",
|
|
107
|
+
swagger_favicon_url="/static/favicon.ico"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
|
|
111
|
+
async def swagger_ui_redirect():
|
|
112
|
+
return get_swagger_ui_oauth2_redirect_html()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@app.get("/redoc", include_in_schema=False)
|
|
116
|
+
async def redoc_html():
|
|
117
|
+
return get_redoc_html(
|
|
118
|
+
openapi_url=app.openapi_url,
|
|
119
|
+
title=app.title + " - ReDoc",
|
|
120
|
+
redoc_js_url="/static/redoc.standalone.js",
|
|
121
|
+
redoc_favicon_url="/static/favicon.ico"
|
|
122
|
+
)
|
|
88
123
|
|
|
89
124
|
@app.exception_handler(ControllerError)
|
|
90
125
|
async def controller_error_handler(request: Request, exc: ControllerError):
|
|
@@ -30,24 +30,24 @@
|
|
|
30
30
|
"version": "9.2",
|
|
31
31
|
"md5sum": "c5bc76e8c95ac9f810a3482c80a54cc7",
|
|
32
32
|
"filesize": 563347456,
|
|
33
|
-
"download_url": "https://
|
|
34
|
-
"direct_download_url": "https://
|
|
33
|
+
"download_url": "https://vault.almalinux.org/9.2/cloud/x86_64/images/",
|
|
34
|
+
"direct_download_url": "https://vault.almalinux.org/9.2/cloud/x86_64/images/AlmaLinux-9-GenericCloud-9.2-20230513.x86_64.qcow2"
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"filename": "AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2",
|
|
38
38
|
"version": "8.8",
|
|
39
39
|
"md5sum": "3958c5fc25770ef63cf97aa5d93f0a0b",
|
|
40
40
|
"filesize": 565444608,
|
|
41
|
-
"download_url": "https://
|
|
42
|
-
"direct_download_url": "https://
|
|
41
|
+
"download_url": "https://vault.almalinux.org/8.8/cloud/x86_64/images/",
|
|
42
|
+
"direct_download_url": "https://vault.almalinux.org/8.8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2"
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"filename": "AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2",
|
|
46
46
|
"version": "8.7",
|
|
47
47
|
"md5sum": "b2b8c7fd3b6869362f3f8ed47549c804",
|
|
48
48
|
"filesize": 566231040,
|
|
49
|
-
"download_url": "https://
|
|
50
|
-
"direct_download_url": "https://
|
|
49
|
+
"download_url": "https://vault.almalinux.org/8.7/cloud/x86_64/images/",
|
|
50
|
+
"direct_download_url": "https://vault.almalinux.org/8.7/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2"
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"filename": "almalinux-cloud-init-data.iso",
|