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.

Files changed (89) hide show
  1. {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/METADATA +20 -19
  2. {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/RECORD +89 -79
  3. {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/WHEEL +1 -1
  4. gns3server/api/routes/compute/cloud_nodes.py +1 -1
  5. gns3server/api/routes/compute/docker_nodes.py +3 -0
  6. gns3server/api/routes/compute/nat_nodes.py +1 -1
  7. gns3server/api/routes/compute/vmware_nodes.py +1 -1
  8. gns3server/api/routes/compute/vpcs_nodes.py +10 -4
  9. gns3server/api/routes/controller/projects.py +29 -3
  10. gns3server/api/routes/controller/users.py +2 -2
  11. gns3server/api/routes/index.py +3 -3
  12. gns3server/api/server.py +38 -3
  13. gns3server/appliances/almalinux.gns3a +6 -6
  14. gns3server/appliances/arista-veos.gns3a +20 -514
  15. gns3server/appliances/cisco-7200.gns3a +26 -0
  16. gns3server/appliances/cisco-asav.gns3a +14 -1
  17. gns3server/appliances/cisco-csr1000v.gns3a +28 -2
  18. gns3server/appliances/cisco-iou-l2.gns3a +16 -4
  19. gns3server/appliances/cisco-iou-l3.gns3a +16 -4
  20. gns3server/appliances/cisco-vWLC.gns3a +29 -1
  21. gns3server/appliances/fortigate.gns3a +3 -3
  22. gns3server/appliances/hbcd-pe.gns3a +62 -0
  23. gns3server/appliances/innovaphone-app.gns3a +50 -0
  24. gns3server/appliances/innovaphone-ipva.gns3a +78 -0
  25. gns3server/appliances/mikrotik-chr.gns3a +30 -99
  26. gns3server/appliances/nixos.gns3a +52 -0
  27. gns3server/appliances/opnsense.gns3a +13 -0
  28. gns3server/appliances/pfsense.gns3a +14 -0
  29. gns3server/appliances/reactos.gns3a +10 -10
  30. gns3server/appliances/truenas.gns3a +104 -0
  31. gns3server/appliances/ubuntu-cloud.gns3a +35 -20
  32. gns3server/appliances/ubuntu-gui.gns3a +13 -0
  33. gns3server/appliances/viptela-edge-genericx86-64.gns3a +28 -2
  34. gns3server/appliances/viptela-smart-genericx86-64.gns3a +27 -1
  35. gns3server/appliances/viptela-vmanage-genericx86-64.gns3a +32 -4
  36. gns3server/appliances/vyos.gns3a +95 -98
  37. gns3server/compute/base_node.py +1 -0
  38. gns3server/compute/docker/docker_vm.py +56 -2
  39. gns3server/compute/docker/resources/init.sh +5 -2
  40. gns3server/compute/dynamips/__init__.py +0 -4
  41. gns3server/compute/dynamips/nodes/router.py +20 -0
  42. gns3server/compute/iou/iou_vm.py +22 -12
  43. gns3server/compute/notification_manager.py +2 -2
  44. gns3server/compute/qemu/qemu_vm.py +0 -5
  45. gns3server/controller/__init__.py +35 -25
  46. gns3server/controller/appliance_manager.py +2 -4
  47. gns3server/controller/compute.py +1 -1
  48. gns3server/controller/export_project.py +18 -14
  49. gns3server/controller/import_project.py +21 -0
  50. gns3server/controller/node.py +10 -8
  51. gns3server/controller/notification.py +4 -4
  52. gns3server/controller/project.py +88 -5
  53. gns3server/controller/symbols.py +1 -1
  54. gns3server/controller/topology.py +1 -1
  55. gns3server/crash_report.py +1 -1
  56. gns3server/db/models/templates.py +1 -0
  57. gns3server/db/repositories/pools.py +1 -1
  58. gns3server/db/tasks.py +1 -1
  59. gns3server/db_migrations/versions/9a5292aa4389_add_mac_address_field_in_docker_.py +27 -0
  60. gns3server/disks/empty100G.qcow2 +0 -0
  61. gns3server/disks/empty200G.qcow2 +0 -0
  62. gns3server/disks/empty30G.qcow2 +0 -0
  63. gns3server/disks/empty8G.qcow2 +0 -0
  64. gns3server/schemas/compute/docker_nodes.py +1 -0
  65. gns3server/schemas/compute/ethernet_switch_nodes.py +1 -1
  66. gns3server/schemas/config.py +1 -1
  67. gns3server/schemas/controller/templates/cloud_templates.py +2 -2
  68. gns3server/schemas/controller/templates/docker_templates.py +4 -3
  69. gns3server/schemas/controller/templates/dynamips_templates.py +5 -5
  70. gns3server/schemas/controller/templates/ethernet_hub_templates.py +1 -1
  71. gns3server/schemas/controller/templates/ethernet_switch_templates.py +2 -2
  72. gns3server/schemas/controller/templates/iou_templates.py +2 -2
  73. gns3server/schemas/controller/templates/qemu_templates.py +12 -12
  74. gns3server/schemas/controller/templates/virtualbox_templates.py +4 -5
  75. gns3server/schemas/controller/templates/vmware_templates.py +4 -4
  76. gns3server/schemas/controller/templates/vpcs_templates.py +2 -2
  77. gns3server/static/favicon.ico +0 -0
  78. gns3server/static/redoc.standalone.js +1782 -0
  79. gns3server/static/swagger-ui-bundle.js +2 -0
  80. gns3server/static/swagger-ui.css +3 -0
  81. gns3server/static/web-ui/index.html +1 -1
  82. gns3server/static/web-ui/{main.4185a8e61824af0d.js → main.e55eeff5c0ba1cf4.js} +1 -1
  83. gns3server/utils/__init__.py +12 -0
  84. gns3server/utils/asyncio/aiozipstream.py +15 -11
  85. gns3server/utils/images.py +45 -35
  86. gns3server/version.py +2 -2
  87. {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/LICENSE +0 -0
  88. {gns3_server-3.0.0rc1.dist-info → gns3_server-3.0.1.dist-info}/entry_points.txt +0 -0
  89. {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.Allocate"))]
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.Allocate
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)
@@ -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", description="This page describes the public controller API for GNS3", version="v3"
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://repo.almalinux.org/almalinux/9/cloud/x86_64/images/",
34
- "direct_download_url": "https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-9.2-20230513.x86_64.qcow2"
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://repo.almalinux.org/almalinux/8/cloud/x86_64/images/",
42
- "direct_download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.8-20230524.x86_64.qcow2"
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://repo.almalinux.org/almalinux/8/cloud/x86_64/images/",
50
- "direct_download_url": "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-8.7-20221111.x86_64.qcow2"
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",