gns3-server 3.0.1__py3-none-any.whl → 3.0.3__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 (30) hide show
  1. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/METADATA +22 -21
  2. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/RECORD +29 -27
  3. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/WHEEL +1 -1
  4. gns3server/api/routes/compute/iou_nodes.py +1 -1
  5. gns3server/api/routes/controller/images.py +58 -21
  6. gns3server/api/routes/controller/templates.py +23 -2
  7. gns3server/appliances/alpine-cloud.gns3a +56 -0
  8. gns3server/appliances/stormshield-eva.gns3a +50 -0
  9. gns3server/compute/docker/__init__.py +1 -1
  10. gns3server/compute/virtualbox/virtualbox_vm.py +29 -25
  11. gns3server/controller/__init__.py +27 -18
  12. gns3server/controller/appliance_manager.py +2 -2
  13. gns3server/controller/compute.py +7 -2
  14. gns3server/crash_report.py +1 -1
  15. gns3server/db/repositories/images.py +22 -3
  16. gns3server/db/repositories/templates.py +11 -0
  17. gns3server/db/tasks.py +120 -79
  18. gns3server/main.py +40 -2
  19. gns3server/server.py +26 -41
  20. gns3server/services/authentication.py +9 -6
  21. gns3server/static/web-ui/index.html +1 -1
  22. gns3server/static/web-ui/main.2e807eb4bc32f838.js +1 -0
  23. gns3server/utils/asyncio/__init__.py +4 -12
  24. gns3server/utils/asyncio/pool.py +1 -4
  25. gns3server/utils/images.py +17 -4
  26. gns3server/version.py +2 -2
  27. gns3server/static/web-ui/main.e55eeff5c0ba1cf4.js +0 -1
  28. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/LICENSE +0 -0
  29. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/entry_points.txt +0 -0
  30. {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: gns3-server
3
- Version: 3.0.1
3
+ Version: 3.0.3
4
4
  Summary: GNS3 graphical interface for the GNS3 server.
5
5
  Author-email: Jeremy Grossmann <developers@gns3.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -690,47 +690,48 @@ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
690
690
  Classifier: Natural Language :: English
691
691
  Classifier: Operating System :: POSIX :: Linux
692
692
  Classifier: Programming Language :: Python :: 3 :: Only
693
- Classifier: Programming Language :: Python :: 3.8
694
693
  Classifier: Programming Language :: Python :: 3.9
695
694
  Classifier: Programming Language :: Python :: 3.10
696
695
  Classifier: Programming Language :: Python :: 3.11
697
696
  Classifier: Programming Language :: Python :: 3.12
697
+ Classifier: Programming Language :: Python :: 3.13
698
698
  Classifier: Programming Language :: Python :: Implementation :: CPython
699
- Requires-Python: >=3.8
699
+ Requires-Python: >=3.9
700
700
  Description-Content-Type: text/markdown
701
701
  License-File: LICENSE
702
- Requires-Dist: uvicorn==0.32.0
703
- Requires-Dist: pydantic==2.9.2
704
- Requires-Dist: fastapi==0.115.5
705
- Requires-Dist: python-multipart==0.0.16
706
- Requires-Dist: websockets==13.1
702
+ Requires-Dist: uvicorn==0.33.0
703
+ Requires-Dist: pydantic==2.10.4
704
+ Requires-Dist: fastapi==0.115.6
705
+ Requires-Dist: python-multipart==0.0.20
706
+ Requires-Dist: websockets==14.1
707
707
  Requires-Dist: aiohttp<3.11,>=3.10.10
708
- Requires-Dist: async-timeout==4.0.3
708
+ Requires-Dist: async-timeout==5.0.1; python_version < "3.11"
709
709
  Requires-Dist: aiofiles<25.0,>=24.1.0
710
- Requires-Dist: Jinja2<3.2,>=3.1.4
711
- Requires-Dist: sentry-sdk<2.18,>=2.17
712
- Requires-Dist: psutil>=6.1.0
710
+ Requires-Dist: Jinja2<3.2,>=3.1.5
711
+ Requires-Dist: sentry-sdk<2.20,>=2.19.2
712
+ Requires-Dist: psutil>=6.1.1
713
713
  Requires-Dist: distro>=1.9.0
714
714
  Requires-Dist: py-cpuinfo<10.0,>=9.0.0
715
+ Requires-Dist: greenlet==3.1.1
715
716
  Requires-Dist: sqlalchemy==2.0.36
716
717
  Requires-Dist: aiosqlite==0.20.0
717
- Requires-Dist: alembic==1.13.3
718
- Requires-Dist: bcrypt==4.2.0
719
- Requires-Dist: python-jose[cryptography]==3.3.0
718
+ Requires-Dist: alembic==1.14.0
719
+ Requires-Dist: bcrypt==4.2.1
720
+ Requires-Dist: joserfc==1.0.1
720
721
  Requires-Dist: email-validator==2.2.0
721
- Requires-Dist: watchfiles==0.24.0
722
+ Requires-Dist: watchdog==6.0.0
722
723
  Requires-Dist: zstandard==0.23.0
723
724
  Requires-Dist: platformdirs<3,>=2.4.0
724
725
  Requires-Dist: importlib-resources>=1.3; python_version <= "3.9"
725
726
  Requires-Dist: truststore>=0.10.0; python_version >= "3.10"
726
727
  Provides-Extra: dev
727
- Requires-Dist: pytest==8.3.3; extra == "dev"
728
+ Requires-Dist: pytest==8.3.4; extra == "dev"
728
729
  Requires-Dist: flake8==7.1.1; extra == "dev"
729
730
  Requires-Dist: pytest-timeout==2.3.1; extra == "dev"
730
- Requires-Dist: pytest-asyncio==0.21.2; extra == "dev"
731
+ Requires-Dist: pytest-asyncio==0.25.2; extra == "dev"
731
732
  Requires-Dist: requests==2.32.3; extra == "dev"
732
- Requires-Dist: httpx==0.27.2; extra == "dev"
733
- Requires-Dist: httpx_ws==0.6.2; extra == "dev"
733
+ Requires-Dist: httpx==0.28.1; extra == "dev"
734
+ Requires-Dist: httpx_ws==0.7.1; extra == "dev"
734
735
 
735
736
  # GNS3 server repository
736
737
 
@@ -2,11 +2,11 @@ gns3server/__init__.py,sha256=7t93V0ASczMyzTR7up2g0FBQ6Rm1eC8wxyysMKUeAKE,716
2
2
  gns3server/__main__.py,sha256=5CO8WDwpzZ2BRo3Ct95MhMGxyXQ3QsHBcWt3jPlcLb0,736
3
3
  gns3server/alembic.ini,sha256=XWHHdJ3QOHO3NJh5LK6bMHT6kv7GzAr26X1hs43DH4o,3086
4
4
  gns3server/config.py,sha256=3UmjwcthW-gMKbLEPzygzrEVJYza-H1IWRjJZ_L1-tg,9244
5
- gns3server/crash_report.py,sha256=nUDfhsd9WLbYOEXpvgVJR0--mggDB4fpy-U3SDCiRPA,6021
5
+ gns3server/crash_report.py,sha256=P0BmchoJI4xWYRtE81S3owlIDJHQtKAMS8FVEzkdCZM,6021
6
6
  gns3server/logger.py,sha256=zjHjyyqK74YMVPdjjznj03xWO42Kx3RDeVnZflT-0eI,5309
7
- gns3server/main.py,sha256=w16TCAYfTmdKsrCjm7rt4hlwsaMfLiWxw8598K4B3zA,2286
8
- gns3server/server.py,sha256=6wtW4I0nKXkuIbJAn0h_xgpiOrGjQpnLgs1Ngj8p5Dw,13362
9
- gns3server/version.py,sha256=62q_NlnEdUU9OlLnmYb4TXBYGDYIqieOYV-jSQOp8bY,1462
7
+ gns3server/main.py,sha256=_bLqv2j1TqgYjDFpSCs-6cUTjJ4_fWDQEFQdGKheIeE,4392
8
+ gns3server/server.py,sha256=KMwIfPvYNw0He5DSyenFuLvr7mlxZlS5azDXKQIVlms,11795
9
+ gns3server/version.py,sha256=3PAMFzRKLzMB1Esc-6vn50dgeeMGnInni-eVSFpYsc8,1462
10
10
  gns3server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  gns3server/api/server.py,sha256=LQAKxtBaVxylgVTqRpVhdwACdkaibDryOSUT2us5PUk,7972
12
12
  gns3server/api/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -22,7 +22,7 @@ gns3server/api/routes/compute/ethernet_hub_nodes.py,sha256=-V2NmAroWZCwR0GqP2nAO
22
22
  gns3server/api/routes/compute/ethernet_switch_nodes.py,sha256=28-EOAb0ukocg3dyMptMg7Z3Nzjk4ZA2mhO5OA8cbfc,7975
23
23
  gns3server/api/routes/compute/frame_relay_switch_nodes.py,sha256=3N1qM-J0QnvB6YO-V2G6R7xReX96ZuP-PyR2htsLM-I,7709
24
24
  gns3server/api/routes/compute/images.py,sha256=6GkZgfDVF3agi7PvOOHVsd7ijUxu6xiQ-3Zc2Jfqlvs,4679
25
- gns3server/api/routes/compute/iou_nodes.py,sha256=BndYiH4MzOhP1EPmsifDqASBsI9i05J0IS01hKl_uzA,10518
25
+ gns3server/api/routes/compute/iou_nodes.py,sha256=0HyPzUJs7Yrh73j9oxiIz9x6OjQTJBYc0Fk-DosTxjI,10531
26
26
  gns3server/api/routes/compute/nat_nodes.py,sha256=WiXCr-mPMsbM3ZF9TDxS15OYm5jzsfPjirGYCeLWd3E,7472
27
27
  gns3server/api/routes/compute/notifications.py,sha256=klAacqbts6slBYDBcEGv_fUw1S9sXMQktdVHNDLBZHc,2993
28
28
  gns3server/api/routes/compute/projects.py,sha256=KhsKfy0zrqh4EDumQXuMf8EkYMENdLcA6Aaxnvhiy18,8107
@@ -40,7 +40,7 @@ gns3server/api/routes/controller/controller.py,sha256=6S8pMz5aj47RSrFeGP8CTuGYs8
40
40
  gns3server/api/routes/controller/drawings.py,sha256=E76kffF_AqXtdY684snU507uAalLNVv-0l2eXe0b5WM,4076
41
41
  gns3server/api/routes/controller/gns3vm.py,sha256=7uwJYx7PSkol6_trM8uN4g_XL7SNds8_r0EMC8UyNHM,2035
42
42
  gns3server/api/routes/controller/groups.py,sha256=Haqy3lzYRS1-FcS15yXEeAPz6k7-sD1_RaPxPVZc85A,6962
43
- gns3server/api/routes/controller/images.py,sha256=YnMf_WL_u5k0SMsOVulTVyJPIov2N6PLgP4hA79EqyM,8993
43
+ gns3server/api/routes/controller/images.py,sha256=MJiMxvmG6P3BNd71tQ5EYbpd7xotm2VJRBYujY1hYV8,10334
44
44
  gns3server/api/routes/controller/links.py,sha256=LgqmdVUUwtpipDhDzRdzUyKpsr1Or-t-E05SXAzGNkA,8464
45
45
  gns3server/api/routes/controller/nodes.py,sha256=WeWmKVDU7aG9GeW4ZbvD79P12Ov0jTIZ5lw4fJjWq8s,18855
46
46
  gns3server/api/routes/controller/pools.py,sha256=FCSqEmRxRvjMKM_iGwERxUrukJEGczV_XRpa8mSZmFw,7806
@@ -49,7 +49,7 @@ gns3server/api/routes/controller/projects.py,sha256=1I5QL3rB35POkfBoObPH0xbUz-Nk
49
49
  gns3server/api/routes/controller/roles.py,sha256=IQ-9BcUDOWqFpxSU7CEZWuEZ6H0VaWv4AfHxT0NZ8ME,6089
50
50
  gns3server/api/routes/controller/snapshots.py,sha256=GMBL2nQJp8VJRpo7LpzHSBhPn1SJbvjs0HugDFqCOYE,3559
51
51
  gns3server/api/routes/controller/symbols.py,sha256=D_fD-j421LJjiO0Rtgo82psxm4WLgN1psVqTdc4psSw,3825
52
- gns3server/api/routes/controller/templates.py,sha256=jivFmT0JsPwRbixv4urF4CEknt5dX_bjezTpgVTIDvc,6280
52
+ gns3server/api/routes/controller/templates.py,sha256=ZeD3eT2x__FvCqRLc85AukOkpHnBCwg1msYL826uqBI,7296
53
53
  gns3server/api/routes/controller/users.py,sha256=cwf11_V1gZ-DThKILGlPZq-g6C4PuAJPU8HyEu5FdVU,8056
54
54
  gns3server/api/routes/controller/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  gns3server/api/routes/controller/dependencies/authentication.py,sha256=-XeUWr21hYkQovqUhcctinPuLqk-q6803evBSTMHtNM,3979
@@ -61,6 +61,7 @@ gns3server/appliances/a10-vthunder.gns3a,sha256=TyEaFP2MagSKBvRFBWB5VD6wcYG4E-jt
61
61
  gns3server/appliances/aaa.gns3a,sha256=A0ZxwwR74BlNR28Fe-tyDCdGe5widI_CceIXrAqYmU4,785
62
62
  gns3server/appliances/alcatel-7750.gns3a,sha256=Sj1WcE--zdIWgf3-DQ-AFBTz41_p6UC9I9iZ3av6TaI,2775
63
63
  gns3server/appliances/almalinux.gns3a,sha256=F37VYRnx0twhNxibZsAN9BKjISl1zu-6hwjOTsWjh0Y,3642
64
+ gns3server/appliances/alpine-cloud.gns3a,sha256=V6ZQ1yiT7Ou03840aplPaWweeufmtcK3KzqpszQW_8s,2285
64
65
  gns3server/appliances/alpine-linux-virt.gns3a,sha256=0BDnDSVRIllXk6Tpuyk1G2vWv9uiwyaCmdd_vYyBK-g,2567
65
66
  gns3server/appliances/alpine-linux.gns3a,sha256=LZs8KQNJQtmpUn7uVOmLlb23kjQHc9Vbrhk-VzwT68o,810
66
67
  gns3server/appliances/arista-ceos.gns3a,sha256=_N88hNErMaD4Wt7AcL4EfGpaohsMhvXWqFkvgcgPeiE,2316
@@ -239,6 +240,7 @@ gns3server/appliances/sophos-iview.gns3a,sha256=5oTP_tQMgCRj-gwz0UyHTR5HSeOMLotu
239
240
  gns3server/appliances/sophos-utm.gns3a,sha256=QtvZ-WDRoAGQsPtP0SCFWMcNA64FkK_X32pUVWvk_Xk,9607
240
241
  gns3server/appliances/sophos-xg.gns3a,sha256=jlghrtfuFGVfFxXFbaYMSTJY3abs1RyuMtTYnj2vGnk,9488
241
242
  gns3server/appliances/stonework.gns3a,sha256=BlagJsXI6Ib_NarXAl7y5HRMaUC8_GriQ8ZGu8B556w,849
243
+ gns3server/appliances/stormshield-eva.gns3a,sha256=DyQN8kJdmvmSj-EXEG7nd-jYvQyENr2WxEF3rI7-TRU,2085
242
244
  gns3server/appliances/tacacs-gui.gns3a,sha256=j35G1eqLB3Krd1RQxpuQcUqsBEcLY2urWjNl0RHBDlo,2191
243
245
  gns3server/appliances/tinycore-linux.gns3a,sha256=ezaMlB_pGZzL52hlV_Yd2IxNNMEwJyd7YVyxP2rqLPc,2818
244
246
  gns3server/appliances/trendmicro-imsva.gns3a,sha256=APIe4SKcVIlaPEfe9ugtf4IP25qiAM69dy53OKodSks,2642
@@ -284,7 +286,7 @@ gns3server/compute/builtin/nodes/cloud.py,sha256=r3tq0b-7uvM9xHRVtNx65Dv3D69_TDO
284
286
  gns3server/compute/builtin/nodes/ethernet_hub.py,sha256=_aPL_bKpvYY_REHRcUlkSLMobN4ZhhGGCJLgQNHUvtc,2708
285
287
  gns3server/compute/builtin/nodes/ethernet_switch.py,sha256=Xc59N3kM9nuzLjHlgllRI3pzXtDQdc2SsCucdZxMebs,2733
286
288
  gns3server/compute/builtin/nodes/nat.py,sha256=rs1M_VZ42zhtb0RmukD7zHEEpR80WAACZykY9ETN0MQ,3804
287
- gns3server/compute/docker/__init__.py,sha256=Lk5Xc4zND2oD9gp-780oGEyj0JfN9gxGkzJ9feibDqg,12470
289
+ gns3server/compute/docker/__init__.py,sha256=DqR1b_qZQnS9Ej4kN6_w3fmYzNdf3N1Hw_UudcmIwOs,12476
288
290
  gns3server/compute/docker/docker_error.py,sha256=Rj5QDgOFt8ENZy23nDI8J-gmtt8-lDDtlNdmK70d_tg,904
289
291
  gns3server/compute/docker/docker_vm.py,sha256=4IQdr-5rL5ylnhPNPaCzU65EZLRSH1yKTWzwuu3cuco,49601
290
292
  gns3server/compute/docker/resources/init.sh,sha256=7BxZQm5TXOmDk-TVc0zJmXOX5Jx3azOOnpbPJohF_x0,2868
@@ -375,7 +377,7 @@ gns3server/compute/ubridge/ubridge_error.py,sha256=cyaHkJXstCd1RJCd5Z3xcmz9Gz8o9
375
377
  gns3server/compute/ubridge/ubridge_hypervisor.py,sha256=GpQPeqnyWUldr2RXz36N87g0K1XOUgTr-JkU4AB2Mwk,9215
376
378
  gns3server/compute/virtualbox/__init__.py,sha256=Ul6lAKxdKJNKXP_v4sHo_Kr53davcFnIH280ZDDhqKo,8014
377
379
  gns3server/compute/virtualbox/virtualbox_error.py,sha256=xiJkTmC6-dKylwEsm2zY1ptoojCyogaK2AIWhVSXFbU,813
378
- gns3server/compute/virtualbox/virtualbox_vm.py,sha256=HKPRJ24a2FV3jT7enn-U5t_tJNQK-u4Qtlg7PKewqXk,46886
380
+ gns3server/compute/virtualbox/virtualbox_vm.py,sha256=iEFfPU2dbWlsYNEHL0QnCIUyauxB-AiHu-iTuZaEfeQ,47143
379
381
  gns3server/compute/vmware/__init__.py,sha256=yu09nv0AqfmNPMKtU2XxrpAuxc8zhQBI-aQtqeIKcCo,29166
380
382
  gns3server/compute/vmware/vmware_error.py,sha256=2yJUpG2xTal5rkBbi1HJ8QmfIH9ipRrUjtVaIVEsxtc,805
381
383
  gns3server/compute/vmware/vmware_vm.py,sha256=WSEuEgtdrLDajGVsRRcgvaOzPepB_5ORrfFUx7rpYgo,35898
@@ -388,11 +390,11 @@ gns3server/configs/ios_etherswitch_startup-config.txt,sha256=zf1QafnlBe729AsDcqL
388
390
  gns3server/configs/iou_l2_base_startup-config.txt,sha256=LYtQ1pOsmLzEg6DjObmB7PvOhMP93DZkQDFvXh1b2IU,1726
389
391
  gns3server/configs/iou_l3_base_startup-config.txt,sha256=zF3Ovq-jKZY0UpiAe8VqhlTzcA7ms1JHWY67vj5gmJQ,1495
390
392
  gns3server/configs/vpcs_base_config.txt,sha256=HsThZLGuqANwIjYrCUklQlvHQq6owMdzlXDDE2aWrBQ,199
391
- gns3server/controller/__init__.py,sha256=Hw1Af7wEi6obaiaQtp5a3D-DejwX94kcvPCbKEpN5gA,24898
393
+ gns3server/controller/__init__.py,sha256=VRKkV0SqZOs99A4LbZV7Is_705_K62PVj7vcg0rsEes,25423
392
394
  gns3server/controller/appliance.py,sha256=xxHdtgBHFN85hxeg3kS6SLyFYDJp3llTSr0LXupByr0,2128
393
- gns3server/controller/appliance_manager.py,sha256=sJD7A9J1bvaLfSycvxaISCVER8AVUvFcW0EytqHqehQ,20984
395
+ gns3server/controller/appliance_manager.py,sha256=cOCHFdxFhpjnoW1de2LdcE0K_ptVw6DKPxedbXALt3A,20996
394
396
  gns3server/controller/appliance_to_template.py,sha256=nM4PIbPxXqYUq7B1oyLhyGz3ZC2QAdk7qClMVTdlJQo,5224
395
- gns3server/controller/compute.py,sha256=rvhJq5GlmBKD9a4bmaDM3rQHmhC0u-ctRaF7JvXYE1k,25469
397
+ gns3server/controller/compute.py,sha256=OamRdq5cZDXSx5QpDIHeq7RWvTWtXtSvcJUua2S9pzE,25581
396
398
  gns3server/controller/controller_error.py,sha256=pYW8eY3VZeBl6nSUOUQh-47pbeKfRtSwbkLiWpleHoo,2071
397
399
  gns3server/controller/drawing.py,sha256=yMN46Ev0dV-wBA4P4g0xzq-XU1qHVcKGmwriO_0GvsU,7179
398
400
  gns3server/controller/export_project.py,sha256=uN5NeMCy1ajMhrEWOli6lHsJNQCI6eRatMss4_kX8vE,12917
@@ -426,7 +428,7 @@ gns3server/controller/ports/serial_port.py,sha256=FdyfxZN1VGn6_DqEE4p8OBkO-IUaFM
426
428
  gns3server/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
427
429
  gns3server/core/tasks.py,sha256=Zo5pCs4LKBUb1I9mgWgQ_h0Bj-_n33-zeCNFZ5xQQl0,3329
428
430
  gns3server/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
429
- gns3server/db/tasks.py,sha256=MjyVRBvnirDhGSe7iPuei6hy7laojECdPfNyGo9dJBM,9334
431
+ gns3server/db/tasks.py,sha256=aK2USujpgxIP4nlEH8MgGp3CPpZc6B_3TudYJwD-t7Q,10145
430
432
  gns3server/db/models/__init__.py,sha256=X3jpiZd7WqERqYmrtalcAvWatfnSL5NaKrgvZPHRs8k,1192
431
433
  gns3server/db/models/acl.py,sha256=jpcCWTEMAEHDQG5mdHhAYkX80oiPc5pQ9LQ9UoJluFI,1776
432
434
  gns3server/db/models/base.py,sha256=E73cXMoRr85tOaDEPcMCtfBMxdd1H_vIPU0wKiCGC2w,3419
@@ -440,10 +442,10 @@ gns3server/db/models/users.py,sha256=78037IGFag5Fp7NlIWywycYF5otMWGmsMSROrPvmZK0
440
442
  gns3server/db/repositories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
441
443
  gns3server/db/repositories/base.py,sha256=a6HZJ4mu9GVpdUCZseA65xy8nzrkN_M00WLFKYVmCzM,874
442
444
  gns3server/db/repositories/computes.py,sha256=Km00JeclL6xDZ_863keGTiU38lZ-ufQhKmiU8hvWEj8,3445
443
- gns3server/db/repositories/images.py,sha256=9q4iKsEybNyq2IilfTZ5HgWhJO92LuBEnQC6SueMFo8,4742
445
+ gns3server/db/repositories/images.py,sha256=UNNxXTxo04Ih-hwbJMmSwKom5XC88qcwNL3meamq9wI,5547
444
446
  gns3server/db/repositories/pools.py,sha256=2Iqwg1DPuEr1e47trjBtSHLPwuRP7PtxVpMUA6VyY3M,7569
445
447
  gns3server/db/repositories/rbac.py,sha256=vkWFp2OiehaETpaff_-_BHFQJZxX1wiukqmdj0rAbQk,15052
446
- gns3server/db/repositories/templates.py,sha256=ut-HtgblS_Sr8q1BxP0dGAXhOvpmwxK5B7N2yzj8T-E,6479
448
+ gns3server/db/repositories/templates.py,sha256=b6v7mxPWVhPTrF6J-fzwi86pdMDJIlotAz_gHSGRajI,6875
447
449
  gns3server/db/repositories/users.py,sha256=e1NCZFR8f00MvwovBwXbn0oEo8lAo1okEC01DSuJY2E,9914
448
450
  gns3server/db_migrations/README,sha256=JNt8RkbFUWF8Ba9uw0bCvMvNW7PONXJvDhREDLOy61o,171
449
451
  gns3server/db_migrations/env.py,sha256=mieif6012ww6wn9JPReZy1WvZHVsTyojbesYpqSE8qw,2782
@@ -524,7 +526,7 @@ gns3server/schemas/controller/templates/virtualbox_templates.py,sha256=8DZEUBe2l
524
526
  gns3server/schemas/controller/templates/vmware_templates.py,sha256=_W7ObQArm1aMd6ANGOzhV8A8C4IEuIGvOAvlVu5x3ag,2843
525
527
  gns3server/schemas/controller/templates/vpcs_templates.py,sha256=cAPdGve1OJCPaSdYLZfxFwidkTL4pzaJxfdtVKI8bFE,1400
526
528
  gns3server/services/__init__.py,sha256=Qdb0EuWkPSLx9HeWcV8lJ1qPez288e7vgpCNLNGbvxw,753
527
- gns3server/services/authentication.py,sha256=jOIrJW4VMaAf_0zz-1TCyN35sJ2ekDbjRhKFGj4MuGE,3473
529
+ gns3server/services/authentication.py,sha256=-8nABBBN0co-xDCBjeu9ZMVrlQNq-7QmX4JjAuKHZ_A,3630
528
530
  gns3server/services/computes.py,sha256=ZcHb7HXxdVjtV0N0ggxOkvDL7mFpemisXLwXMrNNmpQ,3411
529
531
  gns3server/services/templates.py,sha256=w_8grcTPVMXFWGqF40aBQ2OeXK5WDd-yQ4OD6q9jKIg,14211
530
532
  gns3server/static/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -560,8 +562,8 @@ gns3server/static/web-ui/NotoSans-Regular.bb384defbe36eaec.svg,sha256=uECuQtpAPz
560
562
  gns3server/static/web-ui/NotoSans-Regular.e6139cb1663a1c57.ttf,sha256=NPyxxROGVf4PlLBl3aiZC8bvHIpeR0bbt37H7hWtNGI,512588
561
563
  gns3server/static/web-ui/ReleaseNotes.txt,sha256=uag7ABM-yXleLBxhtetbpVOCssZPXcd_lLMyUAdQsn4,5527
562
564
  gns3server/static/web-ui/favicon.ico,sha256=ucy7cQDhOulawYo6ntAIV_MhtjtJjx-3q6tQb8HEDpk,5430
563
- gns3server/static/web-ui/index.html,sha256=Y5NmkKO3FodIF5PNfMyqjTzLoULkxbj0C9Xkt76k1zA,11546
564
- gns3server/static/web-ui/main.e55eeff5c0ba1cf4.js,sha256=TVRGMvBf99gE94FKPiDNYJ7acMu7nBFZXUSCAsx510k,4320056
565
+ gns3server/static/web-ui/index.html,sha256=f6KgIQQ6ibSMrVOuCTqQSkV9ex13YKgQnpHnGscR1ao,11546
566
+ gns3server/static/web-ui/main.2e807eb4bc32f838.js,sha256=wQapR8yTeSICPR5T-gQZDZgR_8uaxWADeqBecwnTE-U,4319609
565
567
  gns3server/static/web-ui/polyfills.319c79dd175e50d0.js,sha256=sQPX0SyLyUHk_0gvODKsdL3-lQsQ_whJeMgxx6tO04A,38362
566
568
  gns3server/static/web-ui/roboto-latin-100.539f0a96b40596f7.woff2,sha256=EoI9WFYFI4EhVUr_i7BgojXcNvN-_Z-x5-bqGpYivDU,15808
567
569
  gns3server/static/web-ui/roboto-latin-100.5ba994dac3e79ea8.woff,sha256=xOrU3p96_yN9BrUw6thBPRNXQn9qkllENCu04rHc5tA,20368
@@ -1225,27 +1227,27 @@ gns3server/utils/file_watcher.py,sha256=CF-5dB-RVSj8xuVxJ9siSpf3QOnXpw3n2IkjCzRg
1225
1227
  gns3server/utils/get_resource.py,sha256=WWW4mejsye6Tpw5UmIT6drfcUDqs-YhLxSlQaNboRDg,1534
1226
1228
  gns3server/utils/hostname.py,sha256=XUswUi47n-LfUbMiZ5AOs_Crl6lln606nhttEaJanpA,3342
1227
1229
  gns3server/utils/http_client.py,sha256=MD-yZA2VjQonqOlPiU4SXo9AjQWDYFFP0ZeZzz680EI,2318
1228
- gns3server/utils/images.py,sha256=Jm-mCUSKwsXP1yWKjSwWOye0_473b0eSbWE0jGHOT8U,14439
1230
+ gns3server/utils/images.py,sha256=v7kPc3iDN6E84naQcS9OUHpZLQ2xfY5syeqY0p_bZ4Y,14840
1229
1231
  gns3server/utils/interfaces.py,sha256=DwsZXwPxmc5E-QwquzMqAfQRLrrt-GyYUjUDxFKqEZo,8981
1230
1232
  gns3server/utils/notification_queue.py,sha256=EO2vHr_Lkxiq9NP-6u6eDsVvFNKbe-QSZqHADU-Ynss,2688
1231
1233
  gns3server/utils/path.py,sha256=m4kj9NoFMLQfMAEG1HJ97x-zAdw0bxq-14tCwaIOSKc,2348
1232
1234
  gns3server/utils/picture.py,sha256=xC6KASep9RHUNzcb6scL5POPNZ04uROXJmTub3INpto,6160
1233
1235
  gns3server/utils/qt.py,sha256=rNABILwh9iqK6XCqBOjjk60ELPPaI7DFQWfKrORk2Kk,1461
1234
1236
  gns3server/utils/vmnet.py,sha256=_7foMqHldwH2kXMtgkpEqOKMJAU7reGI42v1Svnj3gw,9981
1235
- gns3server/utils/asyncio/__init__.py,sha256=59dy1xA7Uvmcmp5CWdiqteP8eRAiXdMdbj3ZwVQ-Vxc,4781
1237
+ gns3server/utils/asyncio/__init__.py,sha256=43PKts4ppmCaFgfepYsI3BfhuqV77gnIudzdWk0umaw,4522
1236
1238
  gns3server/utils/asyncio/aiozipstream.py,sha256=cZF-ASUuqLtXN1vJaDW2PfvSE9O4BjV55yGapelo1Ko,18984
1237
1239
  gns3server/utils/asyncio/embed_shell.py,sha256=J9a3ibTi9AlRJ4YvFAhPmjz68lla0pNgzN31JMMkJXY,11490
1238
1240
  gns3server/utils/asyncio/input_stream.py,sha256=hUnspj9z0X-mvTLi5EMTXpfQLAIIUvEfgjh-7zMug8Y,14560
1239
- gns3server/utils/asyncio/pool.py,sha256=syIRSzff_BE-JsVovFkdem9N0Gb8-5zWpS27DB_Ksnc,2171
1241
+ gns3server/utils/asyncio/pool.py,sha256=EV8ZMPmLe6vIsGjN9QrcxP1XZxjucxlIrWXtJkdd4Iw,2014
1240
1242
  gns3server/utils/asyncio/raw_command_server.py,sha256=Thr023djzxIriw5Au3Y5BMAeQ6R7KNttOy-1Gs_gPvI,4671
1241
1243
  gns3server/utils/asyncio/serial.py,sha256=VNhqaRkN9Mk3Z30CD6wMNfdTNqlY5YUbMyrAwuBsvXM,2333
1242
1244
  gns3server/utils/asyncio/telnet_server.py,sha256=dteUIryUX25iRr5-dMkdBYSTNZQZfLKnw00Y4C87ewc,16752
1243
1245
  gns3server/utils/zipfile_zstd/__init__.py,sha256=QXfnwyxx_CDJdAgOzqqBAD_7WDudc9VN03U0Gfccr5I,163
1244
1246
  gns3server/utils/zipfile_zstd/_patcher.py,sha256=RCMj1y8OrIJheEGnuERDH0l2hvLaFl5wa_IZNiTpBbU,380
1245
1247
  gns3server/utils/zipfile_zstd/_zipfile.py,sha256=KvAeNmWZHu2LHuUOZ8_Tnu_dRi3NOIWM6I3hg_c7NsQ,2189
1246
- gns3_server-3.0.1.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
1247
- gns3_server-3.0.1.dist-info/METADATA,sha256=zaBKSX0ONVpKe4Ltl86liwChiiZ6ilUlYVSCcyREMLA,48284
1248
- gns3_server-3.0.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
1249
- gns3_server-3.0.1.dist-info/entry_points.txt,sha256=kgHc6rA0RfDOTAkTDSwgWXKHWG4r5mQ-SsmpCHNgXPI,92
1250
- gns3_server-3.0.1.dist-info/top_level.txt,sha256=GvKJnXIKLBmewtHjQXkvmtz79ZW51IsfCoPMbHoWehQ,11
1251
- gns3_server-3.0.1.dist-info/RECORD,,
1248
+ gns3_server-3.0.3.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
1249
+ gns3_server-3.0.3.dist-info/METADATA,sha256=_V6rn5lk6NS_o5mfEpZ4thVMDOLbsU9YOwCz9_jpid8,48323
1250
+ gns3_server-3.0.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
1251
+ gns3_server-3.0.3.dist-info/entry_points.txt,sha256=kgHc6rA0RfDOTAkTDSwgWXKHWG4r5mQ-SsmpCHNgXPI,92
1252
+ gns3_server-3.0.3.dist-info/top_level.txt,sha256=GvKJnXIKLBmewtHjQXkvmtz79ZW51IsfCoPMbHoWehQ,11
1253
+ gns3_server-3.0.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -284,7 +284,7 @@ async def start_iou_node_capture(
284
284
  """
285
285
 
286
286
  pcap_file_path = os.path.join(node.project.capture_working_directory(), node_capture_data.capture_file_name)
287
- await node.start_capture(adapter_number, pcap_file_path)
287
+ await node.start_capture(adapter_number, port_number, pcap_file_path)
288
288
  return {"pcap_file_path": str(pcap_file_path)}
289
289
 
290
290
 
@@ -27,11 +27,11 @@ from fastapi.encoders import jsonable_encoder
27
27
  from starlette.requests import ClientDisconnect
28
28
  from sqlalchemy.orm.exc import MultipleResultsFound
29
29
  from typing import List, Optional
30
- from gns3server import schemas
31
30
 
31
+ from gns3server import schemas
32
32
  from gns3server.config import Config
33
33
  from gns3server.compute.qemu import Qemu
34
- from gns3server.utils.images import InvalidImageError, write_image, read_image_info, default_images_directory
34
+ from gns3server.utils.images import InvalidImageError, write_image, read_image_info, default_images_directory, get_builtin_disks
35
35
  from gns3server.db.repositories.images import ImagesRepository
36
36
  from gns3server.db.repositories.templates import TemplatesRepository
37
37
  from gns3server.db.repositories.rbac import RbacRepository
@@ -51,7 +51,6 @@ log = logging.getLogger(__name__)
51
51
 
52
52
  router = APIRouter()
53
53
 
54
-
55
54
  @router.post(
56
55
  "/qemu/{image_path:path}",
57
56
  response_model=schemas.Image,
@@ -175,6 +174,61 @@ async def upload_image(
175
174
  return image
176
175
 
177
176
 
177
+ @router.delete(
178
+ "/prune",
179
+ status_code=status.HTTP_204_NO_CONTENT,
180
+ dependencies=[Depends(has_privilege("Image.Allocate"))]
181
+ )
182
+ async def prune_images(
183
+ images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
184
+ ) -> None:
185
+ """
186
+ Prune images not attached to any template.
187
+
188
+ Required privilege: Image.Allocate
189
+ """
190
+
191
+ skip_images = get_builtin_disks()
192
+ await images_repo.prune_images(skip_images)
193
+
194
+
195
+ @router.post(
196
+ "/install",
197
+ status_code=status.HTTP_204_NO_CONTENT,
198
+ dependencies=[Depends(has_privilege("Image.Allocate"))]
199
+ )
200
+ async def install_images(
201
+ images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
202
+ templates_repo: TemplatesRepository = Depends(get_repository(TemplatesRepository))
203
+ ) -> None:
204
+ """
205
+ Attempt to automatically create templates based on image checksums.
206
+
207
+ Required privilege: Image.Allocate
208
+ """
209
+
210
+ skip_images = get_builtin_disks()
211
+ images = await images_repo.get_images()
212
+ for image in images:
213
+ if skip_images and image.filename in skip_images:
214
+ log.debug(f"Skipping image '{image.path}' for image installation")
215
+ continue
216
+ templates = await images_repo.get_image_templates(image.image_id)
217
+ if templates:
218
+ # the image is already used by a template
219
+ log.warning(f"Image '{image.path}' is used by one or more templates")
220
+ continue
221
+ await Controller.instance().appliance_manager.install_appliances_from_image(
222
+ image.path,
223
+ image.checksum,
224
+ images_repo,
225
+ templates_repo,
226
+ None,
227
+ None,
228
+ os.path.dirname(image.path)
229
+ )
230
+
231
+
178
232
  @router.get(
179
233
  "/{image_path:path}",
180
234
  response_model=schemas.Image,
@@ -218,7 +272,7 @@ async def delete_image(
218
272
  image = await images_repo.get_image(image_path)
219
273
  except MultipleResultsFound:
220
274
  raise ControllerBadRequestError(f"Image '{image_path}' matches multiple images. "
221
- f"Please include the relative path of the image")
275
+ f"Please include the absolute path of the image")
222
276
 
223
277
  if not image:
224
278
  raise ControllerNotFoundError(f"Image '{image_path}' not found")
@@ -236,20 +290,3 @@ async def delete_image(
236
290
  success = await images_repo.delete_image(image_path)
237
291
  if not success:
238
292
  raise ControllerError(f"Image '{image_path}' could not be deleted")
239
-
240
-
241
- @router.post(
242
- "/prune",
243
- status_code=status.HTTP_204_NO_CONTENT,
244
- dependencies=[Depends(has_privilege("Image.Allocate"))]
245
- )
246
- async def prune_images(
247
- images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
248
- ) -> None:
249
- """
250
- Prune images not attached to any template.
251
-
252
- Required privilege: Image.Allocate
253
- """
254
-
255
- await images_repo.prune_images()
@@ -18,6 +18,7 @@
18
18
  API routes for templates.
19
19
  """
20
20
 
21
+ import os
21
22
  import hashlib
22
23
  import json
23
24
 
@@ -34,6 +35,8 @@ from gns3server.db.repositories.templates import TemplatesRepository
34
35
  from gns3server.services.templates import TemplatesService
35
36
  from gns3server.db.repositories.rbac import RbacRepository
36
37
  from gns3server.db.repositories.images import ImagesRepository
38
+ from gns3server.controller.controller_error import ControllerError
39
+ from gns3server.utils.images import get_builtin_disks
37
40
 
38
41
  from .dependencies.authentication import get_current_active_user
39
42
  from .dependencies.rbac import has_privilege
@@ -132,10 +135,28 @@ async def delete_template(
132
135
  Required privilege: Template.Allocate
133
136
  """
134
137
 
138
+ images = await templates_repo.get_template_images(template_id)
135
139
  await TemplatesService(templates_repo).delete_template(template_id)
136
140
  await rbac_repo.delete_all_ace_starting_with_path(f"/templates/{template_id}")
137
- if prune_images:
138
- await images_repo.prune_images()
141
+ if prune_images and images:
142
+ skip_images = get_builtin_disks()
143
+ for image in images:
144
+ if image.filename in skip_images:
145
+ continue
146
+ templates = await images_repo.get_image_templates(image.image_id)
147
+ if templates:
148
+ template_names = ", ".join([template.name for template in templates])
149
+ raise ControllerError(f"Image '{image.path}' is used by one or more templates: {template_names}")
150
+
151
+ try:
152
+ os.remove(image.path)
153
+ except OSError:
154
+ log.warning(f"Could not delete image file {image.path}")
155
+
156
+ print(f"Deleting image '{image.path}'")
157
+ success = await images_repo.delete_image(image.path)
158
+ if not success:
159
+ raise ControllerError(f"Image '{image.path}' could not removed from the database")
139
160
 
140
161
 
141
162
  @router.get(
@@ -0,0 +1,56 @@
1
+ {
2
+ "appliance_id": "edbaa01e-2032-4ee2-bb9f-dd5c4d84c270",
3
+ "name": "Alpine Cloud Guest",
4
+ "category": "guest",
5
+ "description": "Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox.",
6
+ "vendor_name": "Alpine Linux Development Team",
7
+ "vendor_url": "http://alpinelinux.org",
8
+ "vendor_logo_url": "https://raw.githubusercontent.com/GNS3/gns3-registry/master/vendor-logos/Alpine Linux.png",
9
+ "documentation_url": "http://wiki.alpinelinux.org",
10
+ "product_name": "Alpine Linux",
11
+ "product_url": "https://www.alpinelinux.org/cloud/",
12
+ "registry_version": 4,
13
+ "status": "stable",
14
+ "maintainer": "GNS3 Team",
15
+ "maintainer_email": "developers@gns3.net",
16
+ "usage": "\nUsername: alpine\nPassword: alpine",
17
+ "port_name_format": "Ethernet{0}",
18
+ "qemu": {
19
+ "adapter_type": "virtio-net-pci",
20
+ "adapters": 1,
21
+ "ram": 1024,
22
+ "hda_disk_interface": "virtio",
23
+ "arch": "x86_64",
24
+ "console_type": "telnet",
25
+ "boot_priority": "c",
26
+ "kvm": "require",
27
+ "options": "-nographic"
28
+ },
29
+ "images": [
30
+ {
31
+ "filename": "generic_alpine-3.21.2-x86_64-bios-cloudinit-r0.qcow2",
32
+ "version": "3.21.2",
33
+ "md5sum": "b40825dff2867e0ffaffbc4c87674462",
34
+ "filesize": 189726720,
35
+ "download_url": "https://www.alpinelinux.org/cloud/",
36
+ "direct_download_url": "https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/cloud/generic_alpine-3.21.2-x86_64-bios-cloudinit-r0.qcow2"
37
+ },
38
+ {
39
+ "filename": "alpine-cloud-init-data.iso",
40
+ "version": "1.0",
41
+ "md5sum": "b1b4b16cc3bf0250c0fa377c19c97683",
42
+ "filesize": 374784,
43
+ "download_url": "https://github.com/GNS3/gns3-registry/tree/master/cloud-init/alpine-cloud",
44
+ "direct_download_url": "https://github.com/GNS3/gns3-registry/raw/master/cloud-init/alpine-cloud/alpine-cloud-init-data.iso"
45
+ }
46
+ ],
47
+ "versions": [
48
+ {
49
+ "name": "3.21.2",
50
+ "images": {
51
+ "hda_disk_image": "generic_alpine-3.21.2-x86_64-bios-cloudinit-r0.qcow2",
52
+ "cdrom_image": "alpine-cloud-init-data.iso"
53
+ }
54
+ }
55
+ ]
56
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "appliance_id": "60801097-332e-4f40-a63e-8ad62047c01f",
3
+ "name": "Stormshield EVA",
4
+ "category": "firewall",
5
+ "description": "Stormshield EVA (Elastic Virtual Appliance) is a french virtual firewall designed to protect network infrastructures. It offers advanced features such as filtering, intrusion prevention (IPS), VPN management (IPSec/SSL), and access control.",
6
+ "vendor_name": "Stormshield",
7
+ "vendor_url": "https://www.stormshield.com/",
8
+ "vendor_logo_url": "https://www.stormshield.com/wp-content/uploads/stormshield-logo.png",
9
+ "documentation_url": "https://www.stormshield.com/fr/ressourcescenter/network-security-elastic-virtual-appliances/",
10
+ "product_name": "Stormshield EVA",
11
+ "product_url": "https://www.stormshield.com/fr/produits-et-services/produits/protection-des-reseaux/nos-produits/appliances-virtuelles/",
12
+ "registry_version": 4,
13
+ "status": "stable",
14
+ "availability": "service-contract",
15
+ "maintainer": "Samy SCANNA",
16
+ "maintainer_email": "samy.scanna@outlook.com",
17
+ "usage": "After the first boot, the appliance automatically runs the configuration script to set up the password, and network interfaces.",
18
+ "symbol": "stormshield.png",
19
+ "port_name_format": "port{port1}",
20
+ "qemu": {
21
+ "adapter_type": "vmxnet3",
22
+ "adapters": 8,
23
+ "ram": 2048,
24
+ "cpus": 1,
25
+ "hda_disk_interface": "scsi",
26
+ "arch": "x86_64",
27
+ "console_type": "telnet",
28
+ "kvm": "allow",
29
+ "options": "-serial stdio",
30
+ "on_close": "shutdown_signal",
31
+ "process_priority": "normal"
32
+ },
33
+ "images": [
34
+ {
35
+ "filename": "utm-SNS-EVA-4.3.33-kvm.qcow2",
36
+ "version": "4.3.33",
37
+ "md5sum": "21d94d0e20f2e270f06c5853fd750d5b",
38
+ "filesize": 284360704,
39
+ "download_url": "https://mystormshield.eu/product/download/"
40
+ }
41
+ ],
42
+ "versions": [
43
+ {
44
+ "images": {
45
+ "hda_disk_image": "utm-SNS-EVA-4.3.33-kvm.qcow2"
46
+ },
47
+ "name": "4.3.33"
48
+ }
49
+ ]
50
+ }
@@ -115,7 +115,7 @@ class Docker(BaseManager):
115
115
  dst_path = self.resources_path()
116
116
  log.info(f"Installing Docker resources in '{dst_path}'")
117
117
  from gns3server.controller import Controller
118
- Controller.instance().install_resource_files(dst_path, "compute/docker/resources")
118
+ await Controller.instance().install_resource_files(dst_path, "compute/docker/resources")
119
119
  await self.install_busybox(dst_path)
120
120
  except OSError as e:
121
121
  raise DockerError(f"Could not install Docker resources to {dst_path}: {e}")
@@ -233,32 +233,36 @@ class VirtualBoxVM(BaseNode):
233
233
  """
234
234
  Fix the VM uuid in the case of linked clone
235
235
  """
236
- if os.path.exists(self._linked_vbox_file()):
237
- try:
238
- tree = ET.parse(self._linked_vbox_file())
239
- except ET.ParseError:
240
- raise VirtualBoxError(
241
- "Cannot modify VirtualBox linked nodes file. "
242
- "File {} is corrupted.".format(self._linked_vbox_file())
236
+
237
+ linked_vbox_file = self._linked_vbox_file()
238
+ if not os.path.exists(linked_vbox_file):
239
+ raise VirtualBoxError("Cannot find VirtualBox linked node file: {}".format(linked_vbox_file))
240
+
241
+ try:
242
+ tree = ET.parse(linked_vbox_file)
243
+ except ET.ParseError:
244
+ raise VirtualBoxError(f"Cannot modify VirtualBox linked node file. "
245
+ "File {linked_vbox_file} is corrupted.")
246
+ except OSError as e:
247
+ raise VirtualBoxError(f"Cannot modify VirtualBox linked nodes file '{self._linked_vbox_file()}': {e}")
248
+
249
+ machine = tree.getroot().find("{http://www.virtualbox.org/}Machine")
250
+ if machine is not None and machine.get("uuid") != "{" + self.id + "}":
251
+
252
+ for image in tree.getroot().findall("{http://www.virtualbox.org/}Image"):
253
+ currentSnapshot = machine.get("currentSnapshot")
254
+ if currentSnapshot:
255
+ newSnapshot = re.sub(r"\{.*\}", "{" + str(uuid.uuid4()) + "}", currentSnapshot)
256
+ shutil.move(
257
+ os.path.join(self.working_dir, self._vmname, "Snapshots", currentSnapshot) + ".vdi",
258
+ os.path.join(self.working_dir, self._vmname, "Snapshots", newSnapshot) + ".vdi"
243
259
  )
244
- except OSError as e:
245
- raise VirtualBoxError(f"Cannot modify VirtualBox linked nodes file '{self._linked_vbox_file()}': {e}")
246
-
247
- machine = tree.getroot().find("{http://www.virtualbox.org/}Machine")
248
- if machine is not None and machine.get("uuid") != "{" + self.id + "}":
249
-
250
- for image in tree.getroot().findall("{http://www.virtualbox.org/}Image"):
251
- currentSnapshot = machine.get("currentSnapshot")
252
- if currentSnapshot:
253
- newSnapshot = re.sub(r"\{.*\}", "{" + str(uuid.uuid4()) + "}", currentSnapshot)
254
- shutil.move(
255
- os.path.join(self.working_dir, self._vmname, "Snapshots", currentSnapshot) + ".vdi",
256
- os.path.join(self.working_dir, self._vmname, "Snapshots", newSnapshot) + ".vdi",
257
- )
258
- image.set("uuid", newSnapshot)
260
+ log.info(f"VirtualBox VM '{self.name}' [{self.id}] snapshot file moved from '{currentSnapshot}' to '{newSnapshot}'")
261
+ image.set("uuid", newSnapshot)
259
262
 
260
- machine.set("uuid", "{" + self.id + "}")
261
- tree.write(self._linked_vbox_file())
263
+ log.info(f"VirtualBox VM '{self.name}' [{self.id}] '{linked_vbox_file}' has been patched")
264
+ machine.set("uuid", "{" + self.id + "}")
265
+ tree.write(linked_vbox_file)
262
266
 
263
267
  async def check_hw_virtualization(self):
264
268
  """
@@ -488,7 +492,7 @@ class VirtualBoxVM(BaseNode):
488
492
 
489
493
  async def save_linked_hdds_info(self):
490
494
  """
491
- Save linked cloned hard disks information.
495
+ Save linked cloned hard disk information.
492
496
 
493
497
  :returns: disk table information
494
498
  """