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
@@ -23,6 +23,7 @@ import textwrap
23
23
  import posixpath
24
24
  import socket
25
25
  import errno
26
+ import hashlib
26
27
 
27
28
 
28
29
  def force_unix_path(path):
@@ -109,3 +110,14 @@ def is_ipv6_enabled() -> bool:
109
110
  if e.errno == errno.EADDRINUSE:
110
111
  return True
111
112
  raise
113
+
114
+ def md5sum(filename):
115
+ """
116
+ Calculate the MD5 checksum of a file.
117
+ """
118
+
119
+ hash_md5 = hashlib.md5()
120
+ with open(filename, "rb") as f:
121
+ for chunk in iter(lambda: f.read(4096), b""):
122
+ hash_md5.update(chunk)
123
+ return hash_md5.hexdigest()
@@ -195,14 +195,17 @@ class ZipFile(zipfile.ZipFile):
195
195
  self._comment = comment
196
196
  self._didModify = True
197
197
 
198
- async def data_generator(self, path):
199
-
200
- async with aiofiles.open(path, "rb") as f:
201
- while True:
202
- part = await f.read(self._chunksize)
203
- if not part:
204
- break
205
- yield part
198
+ async def data_generator(self, path, islink=False):
199
+
200
+ if islink:
201
+ yield os.readlink(path).encode()
202
+ else:
203
+ async with aiofiles.open(path, "rb") as f:
204
+ while True:
205
+ part = await f.read(self._chunksize)
206
+ if not part:
207
+ break
208
+ yield part
206
209
  return
207
210
 
208
211
  async def _run_in_executor(self, task, *args, **kwargs):
@@ -268,12 +271,13 @@ class ZipFile(zipfile.ZipFile):
268
271
  raise ValueError("either (exclusively) filename or iterable shall be not None")
269
272
 
270
273
  if filename:
271
- st = os.stat(filename)
274
+ st = os.stat(filename, follow_symlinks=False)
272
275
  isdir = stat.S_ISDIR(st.st_mode)
276
+ islink = stat.S_ISLNK(st.st_mode)
273
277
  mtime = time.localtime(st.st_mtime)
274
278
  date_time = mtime[0:6]
275
279
  else:
276
- st, isdir, date_time = None, False, time.localtime()[0:6]
280
+ st, isdir, islink, date_time = None, False, False, time.localtime()[0:6]
277
281
  # Create ZipInfo instance to store file information
278
282
  if arcname is None:
279
283
  arcname = filename
@@ -331,7 +335,7 @@ class ZipFile(zipfile.ZipFile):
331
335
 
332
336
  file_size = 0
333
337
  if filename:
334
- async for buf in self.data_generator(filename):
338
+ async for buf in self.data_generator(filename, islink):
335
339
  file_size = file_size + len(buf)
336
340
  CRC = zipfile.crc32(buf, CRC) & 0xFFFFFFFF
337
341
  if cmpr:
@@ -62,42 +62,52 @@ async def list_images(image_type):
62
62
  directory = os.path.normpath(directory)
63
63
  for root, _, filenames in _os_walk(directory, recurse=recurse):
64
64
  for filename in filenames:
65
- if filename not in files:
66
- if filename.endswith(".md5sum") or filename.startswith("."):
65
+ if filename in files:
66
+ log.debug("File {} has already been found, skipping...".format(filename))
67
+ continue
68
+ if filename.endswith(".md5sum") or filename.startswith("."):
69
+ continue
70
+
71
+ files.add(filename)
72
+
73
+ # It the image is located in the standard directory the path is relative
74
+ if os.path.commonprefix([root, default_directory]) != default_directory:
75
+ path = os.path.join(root, filename)
76
+ else:
77
+ path = os.path.relpath(os.path.join(root, filename), default_directory)
78
+
79
+ filesize = os.stat(os.path.join(root, filename)).st_size
80
+ if filesize < 7:
81
+ log.debug(f"File {filename} is too small to be an image, skipping...")
82
+ continue
83
+
84
+ try:
85
+ with open(os.path.join(root, filename), "rb") as f:
86
+ # read the first 7 bytes of the file.
87
+ elf_header_start = f.read(7)
88
+ if image_type == "dynamips" and elf_header_start != b'\x7fELF\x01\x02\x01':
89
+ # IOS images must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
90
+ log.warning(f"IOS image {filename} does not start with a valid ELF magic number, skipping...")
91
+ continue
92
+ elif image_type == "iou" and elf_header_start != b'\x7fELF\x02\x01\x01' and elf_header_start != b'\x7fELF\x01\x01\x01':
93
+ # IOU images must start with the ELF magic number, be 32-bit or 64-bit, little endian and have an ELF version of 1
94
+ log.warning(f"IOU image {filename} does not start with a valid ELF magic number, skipping...")
67
95
  continue
68
- elif (
69
- ((filename.endswith(".image") or filename.endswith(".bin")) and image_type == "dynamips")
70
- or ((filename.endswith(".bin") or filename.startswith("i86bi")) and image_type == "iou")
71
- or (not filename.endswith(".bin") and not filename.endswith(".image") and image_type == "qemu")
72
- ):
73
- files.add(filename)
74
-
75
- # It the image is located in the standard directory the path is relative
76
- if os.path.commonprefix([root, default_directory]) != default_directory:
77
- path = os.path.join(root, filename)
78
- else:
79
- path = os.path.relpath(os.path.join(root, filename), default_directory)
80
-
81
- try:
82
- if image_type in ["dynamips", "iou"]:
83
- with open(os.path.join(root, filename), "rb") as f:
84
- # read the first 7 bytes of the file.
85
- elf_header_start = f.read(7)
86
- # valid IOU or IOS images must start with the ELF magic number, be 32-bit or 64-bit,
87
- # little endian and have an ELF version of 1
88
- if elf_header_start != b'\x7fELF\x02\x01\x01' and elf_header_start != b'\x7fELF\x01\x01\x01':
89
- continue
90
-
91
- images.append(
92
- {
93
- "filename": filename,
94
- "path": force_unix_path(path),
95
- "md5sum": await wait_run_in_executor(md5sum, os.path.join(root, filename)),
96
- "filesize": os.stat(os.path.join(root, filename)).st_size,
97
- }
98
- )
99
- except OSError as e:
100
- log.warning(f"Can't add image {path}: {str(e)}")
96
+ elif image_type == "qemu" and elf_header_start[:4] == b'\x7fELF':
97
+ # QEMU images should not start with an ELF magic number
98
+ log.warning(f"QEMU image {filename} starts with an ELF magic number, skipping...")
99
+ continue
100
+
101
+ images.append(
102
+ {
103
+ "filename": filename,
104
+ "path": force_unix_path(path),
105
+ "md5sum": await wait_run_in_executor(md5sum, os.path.join(root, filename)),
106
+ "filesize": filesize,
107
+ }
108
+ )
109
+ except OSError as e:
110
+ log.warning(f"Can't add image {path}: {str(e)}")
101
111
  return images
102
112
 
103
113
 
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.0rc1"
26
- __version_info__ = (3, 0, 0, -99)
25
+ __version__ = "3.0.1"
26
+ __version_info__ = (3, 0, 1, 0)
27
27
 
28
28
  if "dev" in __version__:
29
29
  try: