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.
- {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/METADATA +22 -21
- {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/RECORD +29 -27
- {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/WHEEL +1 -1
- gns3server/api/routes/compute/iou_nodes.py +1 -1
- gns3server/api/routes/controller/images.py +58 -21
- gns3server/api/routes/controller/templates.py +23 -2
- gns3server/appliances/alpine-cloud.gns3a +56 -0
- gns3server/appliances/stormshield-eva.gns3a +50 -0
- gns3server/compute/docker/__init__.py +1 -1
- gns3server/compute/virtualbox/virtualbox_vm.py +29 -25
- gns3server/controller/__init__.py +27 -18
- gns3server/controller/appliance_manager.py +2 -2
- gns3server/controller/compute.py +7 -2
- gns3server/crash_report.py +1 -1
- gns3server/db/repositories/images.py +22 -3
- gns3server/db/repositories/templates.py +11 -0
- gns3server/db/tasks.py +120 -79
- gns3server/main.py +40 -2
- gns3server/server.py +26 -41
- gns3server/services/authentication.py +9 -6
- gns3server/static/web-ui/index.html +1 -1
- gns3server/static/web-ui/main.2e807eb4bc32f838.js +1 -0
- gns3server/utils/asyncio/__init__.py +4 -12
- gns3server/utils/asyncio/pool.py +1 -4
- gns3server/utils/images.py +17 -4
- gns3server/version.py +2 -2
- gns3server/static/web-ui/main.e55eeff5c0ba1cf4.js +0 -1
- {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/LICENSE +0 -0
- {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/entry_points.txt +0 -0
- {gns3_server-3.0.1.dist-info → gns3_server-3.0.3.dist-info}/top_level.txt +0 -0
|
@@ -97,18 +97,10 @@ async def wait_for_process_termination(process, timeout=10):
|
|
|
97
97
|
:param timeout: Timeout in seconds
|
|
98
98
|
"""
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return
|
|
105
|
-
else:
|
|
106
|
-
while timeout > 0:
|
|
107
|
-
if process.returncode is not None:
|
|
108
|
-
return
|
|
109
|
-
await asyncio.sleep(0.1)
|
|
110
|
-
timeout -= 0.1
|
|
111
|
-
raise asyncio.TimeoutError()
|
|
100
|
+
try:
|
|
101
|
+
await asyncio.wait_for(process.wait(), timeout=timeout)
|
|
102
|
+
except ProcessLookupError:
|
|
103
|
+
return
|
|
112
104
|
|
|
113
105
|
|
|
114
106
|
async def _check_process(process, termination_callback):
|
gns3server/utils/asyncio/pool.py
CHANGED
|
@@ -40,10 +40,7 @@ class Pool:
|
|
|
40
40
|
while len(self._tasks) > 0 or len(pending) > 0:
|
|
41
41
|
while len(self._tasks) > 0 and len(pending) < self._concurrency:
|
|
42
42
|
task, args, kwargs = self._tasks.pop(0)
|
|
43
|
-
|
|
44
|
-
t = asyncio.create_task(task(*args, **kwargs))
|
|
45
|
-
else:
|
|
46
|
-
t = asyncio.get_event_loop().create_task(task(*args, **kwargs))
|
|
43
|
+
t = asyncio.create_task(task(*args, **kwargs))
|
|
47
44
|
pending.add(t)
|
|
48
45
|
(done, pending) = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED)
|
|
49
46
|
for task in done:
|
gns3server/utils/images.py
CHANGED
|
@@ -20,6 +20,11 @@ import stat
|
|
|
20
20
|
import aiofiles
|
|
21
21
|
import shutil
|
|
22
22
|
|
|
23
|
+
try:
|
|
24
|
+
import importlib_resources
|
|
25
|
+
except ImportError:
|
|
26
|
+
from importlib import resources as importlib_resources
|
|
27
|
+
|
|
23
28
|
from typing import List, AsyncGenerator
|
|
24
29
|
from ..config import Config
|
|
25
30
|
from . import force_unix_path
|
|
@@ -111,6 +116,14 @@ async def list_images(image_type):
|
|
|
111
116
|
return images
|
|
112
117
|
|
|
113
118
|
|
|
119
|
+
def get_builtin_disks() -> List[str]:
|
|
120
|
+
builtin_disks = []
|
|
121
|
+
for entry in importlib_resources.files('gns3server').joinpath("disks").iterdir():
|
|
122
|
+
if entry.is_file():
|
|
123
|
+
builtin_disks.append(entry.name)
|
|
124
|
+
return builtin_disks
|
|
125
|
+
|
|
126
|
+
|
|
114
127
|
async def read_image_info(path: str, expected_image_type: str = None) -> dict:
|
|
115
128
|
|
|
116
129
|
header_magic_len = 7
|
|
@@ -118,7 +131,7 @@ async def read_image_info(path: str, expected_image_type: str = None) -> dict:
|
|
|
118
131
|
async with aiofiles.open(path, "rb") as f:
|
|
119
132
|
image_header = await f.read(header_magic_len) # read the first 7 bytes of the file
|
|
120
133
|
if len(image_header) >= header_magic_len:
|
|
121
|
-
detected_image_type = check_valid_image_header(image_header)
|
|
134
|
+
detected_image_type = check_valid_image_header(path, image_header)
|
|
122
135
|
if expected_image_type and detected_image_type != expected_image_type:
|
|
123
136
|
raise InvalidImageError(f"Detected image type for '{path}' is {detected_image_type}, "
|
|
124
137
|
f"expected type is {expected_image_type}")
|
|
@@ -302,7 +315,7 @@ class InvalidImageError(Exception):
|
|
|
302
315
|
return self._message
|
|
303
316
|
|
|
304
317
|
|
|
305
|
-
def check_valid_image_header(data: bytes, allow_raw_image: bool = False) -> str:
|
|
318
|
+
def check_valid_image_header(path: str, data: bytes, allow_raw_image: bool = False) -> str:
|
|
306
319
|
|
|
307
320
|
if data[:7] == b'\x7fELF\x01\x02\x01':
|
|
308
321
|
# for IOS images: file must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
|
|
@@ -317,7 +330,7 @@ def check_valid_image_header(data: bytes, allow_raw_image: bool = False) -> str:
|
|
|
317
330
|
else:
|
|
318
331
|
if allow_raw_image is True:
|
|
319
332
|
return "qemu"
|
|
320
|
-
raise InvalidImageError("
|
|
333
|
+
raise InvalidImageError(f"{path}: could not detect image type, please make sure it is a valid image")
|
|
321
334
|
|
|
322
335
|
|
|
323
336
|
async def write_image(
|
|
@@ -342,7 +355,7 @@ async def write_image(
|
|
|
342
355
|
async for chunk in stream:
|
|
343
356
|
if check_image_header and len(chunk) >= header_magic_len:
|
|
344
357
|
check_image_header = False
|
|
345
|
-
image_type = check_valid_image_header(chunk, allow_raw_image)
|
|
358
|
+
image_type = check_valid_image_header(image_path, chunk, allow_raw_image)
|
|
346
359
|
await f.write(chunk)
|
|
347
360
|
checksum.update(chunk)
|
|
348
361
|
|
gns3server/version.py
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
# or negative for a release candidate or beta (after the base version
|
|
23
23
|
# number has been incremented)
|
|
24
24
|
|
|
25
|
-
__version__ = "3.0.
|
|
26
|
-
__version_info__ = (3, 0,
|
|
25
|
+
__version__ = "3.0.3"
|
|
26
|
+
__version_info__ = (3, 0, 3, 0)
|
|
27
27
|
|
|
28
28
|
if "dev" in __version__:
|
|
29
29
|
try:
|