mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-28 03:08:14 +00:00
commit
6f345bb1ec
10
CHANGELOG
10
CHANGELOG
@ -1,5 +1,15 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 2.2.43 19/09/2023
|
||||||
|
|
||||||
|
* Force English output for VBoxManage. Fixes #2266
|
||||||
|
* Automatically add vboxnet and DHCP server if not present for VirtualBox GNS3 VM. Ref #2266
|
||||||
|
* Fix issue with controller config saved before checking current version with previous one
|
||||||
|
* Prevent X11 socket file to be modified by Docker container
|
||||||
|
* Use the user data dir to store built-in appliances
|
||||||
|
* Catch ConnectionResetError exception when client disconnects
|
||||||
|
* Upgrade to PyQt 5.15.9 and pywin32
|
||||||
|
|
||||||
## 2.2.42 09/08/2023
|
## 2.2.42 09/08/2023
|
||||||
|
|
||||||
* Bundle web-ui v2.2.42
|
* Bundle web-ui v2.2.42
|
||||||
|
@ -26,6 +26,14 @@
|
|||||||
"kvm": "require"
|
"kvm": "require"
|
||||||
},
|
},
|
||||||
"images": [
|
"images": [
|
||||||
|
{
|
||||||
|
"filename": "openmediavault_6.5.0-amd64.iso",
|
||||||
|
"version": "6.5.0",
|
||||||
|
"md5sum": "aa40e5ca50748b139cba2f4ac704a72d",
|
||||||
|
"filesize": 941621248,
|
||||||
|
"download_url": "https://www.openmediavault.org/download.html",
|
||||||
|
"direct_download_url": "https://sourceforge.net/projects/openmediavault/files/6.5.0/openmediavault_6.5.0-amd64.iso"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"filename": "openmediavault_6.0.24-amd64.iso",
|
"filename": "openmediavault_6.0.24-amd64.iso",
|
||||||
"version": "6.0.24",
|
"version": "6.0.24",
|
||||||
@ -60,6 +68,14 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": [
|
"versions": [
|
||||||
|
{
|
||||||
|
"name": "6.5.0",
|
||||||
|
"images": {
|
||||||
|
"hda_disk_image": "empty30G.qcow2",
|
||||||
|
"hdb_disk_image": "empty30G.qcow2",
|
||||||
|
"cdrom_image": "openmediavault_6.5.0-amd64.iso"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "6.0.24",
|
"name": "6.0.24",
|
||||||
"images": {
|
"images": {
|
||||||
|
@ -59,32 +59,28 @@
|
|||||||
"version": "1.2.9-S1",
|
"version": "1.2.9-S1",
|
||||||
"md5sum": "3fece6363f9766f862e26d292d0ed5a3",
|
"md5sum": "3fece6363f9766f862e26d292d0ed5a3",
|
||||||
"filesize": 430964736,
|
"filesize": 430964736,
|
||||||
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-s1-generic-iso-image",
|
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-s1-generic-iso-image"
|
||||||
"direct_download_url": "https://s3-us.vyos.io/1.2.9-S1/vyos-1.2.9-S1-amd64.iso"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "vyos-1.2.9-S1-10G-qemu.qcow2",
|
"filename": "vyos-1.2.9-S1-10G-qemu.qcow2",
|
||||||
"version": "1.2.9-S1-KVM",
|
"version": "1.2.9-S1-KVM",
|
||||||
"md5sum": "0a70d78b80a3716d42487c02ef44f41f",
|
"md5sum": "0a70d78b80a3716d42487c02ef44f41f",
|
||||||
"filesize": 426967040,
|
"filesize": 426967040,
|
||||||
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-s1-for-kvm",
|
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-s1-for-kvm"
|
||||||
"direct_download_url": "https://s3-us.vyos.io/1.2.9-S1/vyos-1.2.9-S1-10G-qemu.qcow2"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "vyos-1.2.9-amd64.iso",
|
"filename": "vyos-1.2.9-amd64.iso",
|
||||||
"version": "1.2.9",
|
"version": "1.2.9",
|
||||||
"md5sum": "586be23b6256173e174c82d8f1f699a1",
|
"md5sum": "586be23b6256173e174c82d8f1f699a1",
|
||||||
"filesize": 430964736,
|
"filesize": 430964736,
|
||||||
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-generic-iso-image",
|
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-generic-iso-image"
|
||||||
"direct_download_url": "https://s3-us.vyos.io/1.2.9/vyos-1.2.9-amd64.iso"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "vyos-1.2.9-10G-qemu.qcow2",
|
"filename": "vyos-1.2.9-10G-qemu.qcow2",
|
||||||
"version": "1.2.9-KVM",
|
"version": "1.2.9-KVM",
|
||||||
"md5sum": "76871c7b248c32f75177c419128257ac",
|
"md5sum": "76871c7b248c32f75177c419128257ac",
|
||||||
"filesize": 427360256,
|
"filesize": 427360256,
|
||||||
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-10g-qemu-qcow2",
|
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-9-10g-qemu-qcow2"
|
||||||
"direct_download_url": "https://s3-us.vyos.io/1.2.9/vyos-1.2.9-10G-qemu.qcow2"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "vyos-1.2.8-amd64.iso",
|
"filename": "vyos-1.2.8-amd64.iso",
|
||||||
@ -93,13 +89,6 @@
|
|||||||
"filesize": 429916160,
|
"filesize": 429916160,
|
||||||
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-8-generic-iso-image"
|
"download_url": "https://support.vyos.io/en/downloads/files/vyos-1-2-8-generic-iso-image"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"filename": "vyos-1.1.8-amd64.iso",
|
|
||||||
"version": "1.1.8",
|
|
||||||
"md5sum": "95a141d4b592b81c803cdf7e9b11d8ea",
|
|
||||||
"filesize": 241172480,
|
|
||||||
"direct_download_url": "https://s3-us.vyos.io/vyos-1.1.8-amd64.iso"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"filename": "empty8G.qcow2",
|
"filename": "empty8G.qcow2",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
@ -170,13 +159,6 @@
|
|||||||
"hda_disk_image": "empty8G.qcow2",
|
"hda_disk_image": "empty8G.qcow2",
|
||||||
"cdrom_image": "vyos-1.2.8-amd64.iso"
|
"cdrom_image": "vyos-1.2.8-amd64.iso"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "1.1.8",
|
|
||||||
"images": {
|
|
||||||
"hda_disk_image": "empty8G.qcow2",
|
|
||||||
"cdrom_image": "vyos-1.1.8-amd64.iso"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,14 @@
|
|||||||
"kvm": "require"
|
"kvm": "require"
|
||||||
},
|
},
|
||||||
"images": [
|
"images": [
|
||||||
|
{
|
||||||
|
"filename": "WinDev2308Eval-disk1.vmdk",
|
||||||
|
"version": "2308",
|
||||||
|
"md5sum": "6a9b4ed6d7481f7bbf8a054c797b1eee",
|
||||||
|
"filesize": 24945341952,
|
||||||
|
"download_url": "https://download.microsoft.com/download/7/1/3/7135f2ab-8528-49fc-9252-8d5d94c697ef/WinDev2308Eval.VMWare.zip",
|
||||||
|
"compression": "zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"filename": "WinDev2212Eval-disk1.vmdk",
|
"filename": "WinDev2212Eval-disk1.vmdk",
|
||||||
"version": "2212",
|
"version": "2212",
|
||||||
@ -48,6 +56,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"versions": [
|
"versions": [
|
||||||
|
{
|
||||||
|
"name": "2308",
|
||||||
|
"images": {
|
||||||
|
"bios_image": "OVMF-edk2-stable202305.fd",
|
||||||
|
"hda_disk_image": "WinDev2308Eval-disk1.vmdk"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "2212",
|
"name": "2212",
|
||||||
"images": {
|
"images": {
|
||||||
|
@ -406,7 +406,7 @@ class DockerVM(BaseNode):
|
|||||||
await self._start_vnc()
|
await self._start_vnc()
|
||||||
params["Env"].append("QT_GRAPHICSSYSTEM=native") # To fix a Qt issue: https://github.com/GNS3/gns3-server/issues/556
|
params["Env"].append("QT_GRAPHICSSYSTEM=native") # To fix a Qt issue: https://github.com/GNS3/gns3-server/issues/556
|
||||||
params["Env"].append("DISPLAY=:{}".format(self._display))
|
params["Env"].append("DISPLAY=:{}".format(self._display))
|
||||||
params["HostConfig"]["Binds"].append("/tmp/.X11-unix/:/tmp/.X11-unix/")
|
params["HostConfig"]["Binds"].append("/tmp/.X11-unix/X{0}:/tmp/.X11-unix/X{0}:ro".format(self._display))
|
||||||
|
|
||||||
if self._extra_hosts:
|
if self._extra_hosts:
|
||||||
extra_hosts = self._format_extra_hosts(self._extra_hosts)
|
extra_hosts = self._format_extra_hosts(self._extra_hosts)
|
||||||
|
@ -109,9 +109,16 @@ class VirtualBox(BaseManager):
|
|||||||
command = [vboxmanage_path, "--nologo", subcommand]
|
command = [vboxmanage_path, "--nologo", subcommand]
|
||||||
command.extend(args)
|
command.extend(args)
|
||||||
command_string = " ".join(command)
|
command_string = " ".join(command)
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["LANG"] = "en" # force english output because we rely on it to parse the output
|
||||||
log.info("Executing VBoxManage with command: {}".format(command_string))
|
log.info("Executing VBoxManage with command: {}".format(command_string))
|
||||||
try:
|
try:
|
||||||
process = await asyncio.create_subprocess_exec(*command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
|
process = await asyncio.create_subprocess_exec(
|
||||||
|
*command,
|
||||||
|
stdout=asyncio.subprocess.PIPE,
|
||||||
|
stderr=asyncio.subprocess.PIPE,
|
||||||
|
env=env
|
||||||
|
)
|
||||||
except (OSError, subprocess.SubprocessError) as e:
|
except (OSError, subprocess.SubprocessError) as e:
|
||||||
raise VirtualBoxError("Could not execute VBoxManage: {}".format(e))
|
raise VirtualBoxError("Could not execute VBoxManage: {}".format(e))
|
||||||
|
|
||||||
|
@ -191,29 +191,28 @@ class Controller:
|
|||||||
Save the controller configuration on disk
|
Save the controller configuration on disk
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self._config_loaded is False:
|
controller_settings = dict()
|
||||||
return
|
if self._config_loaded:
|
||||||
|
controller_settings = {"computes": [],
|
||||||
|
"templates": [],
|
||||||
|
"gns3vm": self.gns3vm.__json__(),
|
||||||
|
"iou_license": self._iou_license_settings,
|
||||||
|
"appliances_etag": self._appliance_manager.appliances_etag,
|
||||||
|
"version": __version__}
|
||||||
|
|
||||||
controller_settings = {"computes": [],
|
for template in self._template_manager.templates.values():
|
||||||
"templates": [],
|
if not template.builtin:
|
||||||
"gns3vm": self.gns3vm.__json__(),
|
controller_settings["templates"].append(template.__json__())
|
||||||
"iou_license": self._iou_license_settings,
|
|
||||||
"appliances_etag": self._appliance_manager.appliances_etag,
|
|
||||||
"version": __version__}
|
|
||||||
|
|
||||||
for template in self._template_manager.templates.values():
|
for compute in self._computes.values():
|
||||||
if not template.builtin:
|
if compute.id != "local" and compute.id != "vm":
|
||||||
controller_settings["templates"].append(template.__json__())
|
controller_settings["computes"].append({"host": compute.host,
|
||||||
|
"name": compute.name,
|
||||||
for compute in self._computes.values():
|
"port": compute.port,
|
||||||
if compute.id != "local" and compute.id != "vm":
|
"protocol": compute.protocol,
|
||||||
controller_settings["computes"].append({"host": compute.host,
|
"user": compute.user,
|
||||||
"name": compute.name,
|
"password": compute.password,
|
||||||
"port": compute.port,
|
"compute_id": compute.id})
|
||||||
"protocol": compute.protocol,
|
|
||||||
"user": compute.user,
|
|
||||||
"password": compute.password,
|
|
||||||
"compute_id": compute.id})
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.makedirs(os.path.dirname(self._config_file), exist_ok=True)
|
os.makedirs(os.path.dirname(self._config_file), exist_ok=True)
|
||||||
@ -229,8 +228,7 @@ class Controller:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if not os.path.exists(self._config_file):
|
if not os.path.exists(self._config_file):
|
||||||
self._config_loaded = True
|
self.save() # this will create the config file
|
||||||
self.save()
|
|
||||||
with open(self._config_file) as f:
|
with open(self._config_file) as f:
|
||||||
controller_settings = json.load(f)
|
controller_settings = json.load(f)
|
||||||
except (OSError, ValueError) as e:
|
except (OSError, ValueError) as e:
|
||||||
@ -255,6 +253,8 @@ class Controller:
|
|||||||
if not previous_version or \
|
if not previous_version or \
|
||||||
parse_version(__version__.split("+")[0]) > parse_version(previous_version.split("+")[0]):
|
parse_version(__version__.split("+")[0]) > parse_version(previous_version.split("+")[0]):
|
||||||
self._appliance_manager.install_builtin_appliances()
|
self._appliance_manager.install_builtin_appliances()
|
||||||
|
elif not os.listdir(self._appliance_manager.builtin_appliances_path()):
|
||||||
|
self._appliance_manager.install_builtin_appliances()
|
||||||
|
|
||||||
self._appliance_manager.appliances_etag = controller_settings.get("appliances_etag")
|
self._appliance_manager.appliances_etag = controller_settings.get("appliances_etag")
|
||||||
self._appliance_manager.load_appliances()
|
self._appliance_manager.load_appliances()
|
||||||
|
@ -21,6 +21,7 @@ import uuid
|
|||||||
import asyncio
|
import asyncio
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import shutil
|
import shutil
|
||||||
|
import platformdirs
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -81,13 +82,13 @@ class ApplianceManager:
|
|||||||
os.makedirs(appliances_path, exist_ok=True)
|
os.makedirs(appliances_path, exist_ok=True)
|
||||||
return appliances_path
|
return appliances_path
|
||||||
|
|
||||||
def _builtin_appliances_path(self, delete_first=False):
|
def builtin_appliances_path(self, delete_first=False):
|
||||||
"""
|
"""
|
||||||
Get the built-in appliance storage directory
|
Get the built-in appliance storage directory
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = Config.instance()
|
appname = vendor = "GNS3"
|
||||||
appliances_dir = os.path.join(config.config_dir, "appliances")
|
appliances_dir = os.path.join(platformdirs.user_data_dir(appname, vendor, roaming=True), "appliances")
|
||||||
if delete_first:
|
if delete_first:
|
||||||
shutil.rmtree(appliances_dir, ignore_errors=True)
|
shutil.rmtree(appliances_dir, ignore_errors=True)
|
||||||
os.makedirs(appliances_dir, exist_ok=True)
|
os.makedirs(appliances_dir, exist_ok=True)
|
||||||
@ -98,7 +99,7 @@ class ApplianceManager:
|
|||||||
At startup we copy the built-in appliances files.
|
At startup we copy the built-in appliances files.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
dst_path = self._builtin_appliances_path(delete_first=True)
|
dst_path = self.builtin_appliances_path(delete_first=True)
|
||||||
log.info(f"Installing built-in appliances in '{dst_path}'")
|
log.info(f"Installing built-in appliances in '{dst_path}'")
|
||||||
from . import Controller
|
from . import Controller
|
||||||
try:
|
try:
|
||||||
@ -112,7 +113,7 @@ class ApplianceManager:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
self._appliances = {}
|
self._appliances = {}
|
||||||
for directory, builtin in ((self._builtin_appliances_path(), True,), (self._custom_appliances_path(), False,)):
|
for directory, builtin in ((self.builtin_appliances_path(), True,), (self._custom_appliances_path(), False,)):
|
||||||
if directory and os.path.isdir(directory):
|
if directory and os.path.isdir(directory):
|
||||||
for file in os.listdir(directory):
|
for file in os.listdir(directory):
|
||||||
if not file.endswith('.gns3a') and not file.endswith('.gns3appliance'):
|
if not file.endswith('.gns3a') and not file.endswith('.gns3appliance'):
|
||||||
@ -215,7 +216,7 @@ class ApplianceManager:
|
|||||||
from . import Controller
|
from . import Controller
|
||||||
Controller.instance().save()
|
Controller.instance().save()
|
||||||
json_data = await response.json()
|
json_data = await response.json()
|
||||||
appliances_dir = self._builtin_appliances_path()
|
appliances_dir = self.builtin_appliances_path()
|
||||||
downloaded_appliance_files = []
|
downloaded_appliance_files = []
|
||||||
for appliance in json_data:
|
for appliance in json_data:
|
||||||
if appliance["type"] == "file":
|
if appliance["type"] == "file":
|
||||||
|
@ -15,11 +15,13 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
import socket
|
import socket
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
from .base_gns3_vm import BaseGNS3VM
|
from .base_gns3_vm import BaseGNS3VM
|
||||||
from .gns3_vm_error import GNS3VMError
|
from .gns3_vm_error import GNS3VMError
|
||||||
@ -80,9 +82,6 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
self._system_properties[name.strip()] = value.strip()
|
self._system_properties[name.strip()] = value.strip()
|
||||||
if "API Version" in self._system_properties:
|
|
||||||
# API version is not consistent between VirtualBox versions, the key is named "API Version" in VirtualBox 7
|
|
||||||
self._system_properties["API version"] = self._system_properties.pop("API Version")
|
|
||||||
|
|
||||||
async def _check_requirements(self):
|
async def _check_requirements(self):
|
||||||
"""
|
"""
|
||||||
@ -92,16 +91,16 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
if not self._system_properties:
|
if not self._system_properties:
|
||||||
await self._get_system_properties()
|
await self._get_system_properties()
|
||||||
if "API version" not in self._system_properties:
|
if "API version" not in self._system_properties:
|
||||||
raise VirtualBoxError("Can't access to VirtualBox API version:\n{}".format(self._system_properties))
|
raise GNS3VMError("Can't access to VirtualBox API version:\n{}".format(self._system_properties))
|
||||||
from cpuinfo import get_cpu_info
|
from cpuinfo import get_cpu_info
|
||||||
cpu_info = await wait_run_in_executor(get_cpu_info)
|
cpu_info = await wait_run_in_executor(get_cpu_info)
|
||||||
vendor_id = cpu_info.get('vendor_id_raw')
|
vendor_id = cpu_info.get('vendor_id_raw')
|
||||||
if vendor_id == "GenuineIntel":
|
if vendor_id == "GenuineIntel":
|
||||||
if parse_version(self._system_properties["API version"]) < parse_version("6_1"):
|
if parse_version(self._system_properties["API version"]) < parse_version("6_1"):
|
||||||
raise VirtualBoxError("VirtualBox version 6.1 or above is required to run the GNS3 VM with nested virtualization enabled on Intel processors")
|
raise GNS3VMError("VirtualBox version 6.1 or above is required to run the GNS3 VM with nested virtualization enabled on Intel processors")
|
||||||
elif vendor_id == "AuthenticAMD":
|
elif vendor_id == "AuthenticAMD":
|
||||||
if parse_version(self._system_properties["API version"]) < parse_version("6_0"):
|
if parse_version(self._system_properties["API version"]) < parse_version("6_0"):
|
||||||
raise VirtualBoxError("VirtualBox version 6.0 or above is required to run the GNS3 VM with nested virtualization enabled on AMD processors")
|
raise GNS3VMError("VirtualBox version 6.0 or above is required to run the GNS3 VM with nested virtualization enabled on AMD processors")
|
||||||
else:
|
else:
|
||||||
log.warning("Could not determine CPU vendor: {}".format(vendor_id))
|
log.warning("Could not determine CPU vendor: {}".format(vendor_id))
|
||||||
|
|
||||||
@ -162,6 +161,44 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
async def _add_dhcp_server(self, vboxnet):
|
||||||
|
"""
|
||||||
|
Add a DHCP server for vboxnet.
|
||||||
|
|
||||||
|
:param vboxnet: vboxnet name
|
||||||
|
"""
|
||||||
|
|
||||||
|
hostonlyifs = await self._execute("list", ["hostonlyifs"])
|
||||||
|
pattern = r"IPAddress:\s+(\d+\.\d+\.\d+\.\d+)\nNetworkMask:\s+(\d+\.\d+\.\d+\.\d+)"
|
||||||
|
match = re.search(pattern, hostonlyifs)
|
||||||
|
|
||||||
|
if match:
|
||||||
|
ip_address = match.group(1)
|
||||||
|
netmask = match.group(2)
|
||||||
|
else:
|
||||||
|
raise GNS3VMError("Could not find IP address and netmask for vboxnet {}".format(vboxnet))
|
||||||
|
|
||||||
|
try:
|
||||||
|
interface = ipaddress.IPv4Interface(f"{ip_address}/{netmask}")
|
||||||
|
subnet = ipaddress.IPv4Network(str(interface.network))
|
||||||
|
dhcp_server_ip = str(interface.ip + 1)
|
||||||
|
netmask = str(subnet.netmask)
|
||||||
|
lower_ip = str(interface.ip + 2)
|
||||||
|
upper_ip = str(subnet.network_address + subnet.num_addresses - 2)
|
||||||
|
except ValueError:
|
||||||
|
raise GNS3VMError("Invalid IP address and netmask for vboxnet {}: {}/{}".format(vboxnet, ip_address, netmask))
|
||||||
|
|
||||||
|
dhcp_server_args = [
|
||||||
|
"add",
|
||||||
|
"--network=HostInterfaceNetworking-{}".format(vboxnet),
|
||||||
|
"--server-ip={}".format(dhcp_server_ip),
|
||||||
|
"--netmask={}".format(netmask),
|
||||||
|
"--lower-ip={}".format(lower_ip),
|
||||||
|
"--upper-ip={}".format(upper_ip),
|
||||||
|
"--enable"
|
||||||
|
]
|
||||||
|
await self._execute("dhcpserver", dhcp_server_args)
|
||||||
|
|
||||||
async def _check_vboxnet_exists(self, vboxnet, vboxnet_type):
|
async def _check_vboxnet_exists(self, vboxnet, vboxnet_type):
|
||||||
"""
|
"""
|
||||||
Check if the vboxnet interface exists
|
Check if the vboxnet interface exists
|
||||||
@ -264,12 +301,20 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
await self.set_hostonly_network(interface_number, first_available_vboxnet)
|
await self.set_hostonly_network(interface_number, first_available_vboxnet)
|
||||||
vboxnet = first_available_vboxnet
|
vboxnet = first_available_vboxnet
|
||||||
else:
|
else:
|
||||||
raise GNS3VMError('VirtualBox host-only network "{}" does not exist, please make the sure the network adapter {} configuration is valid for "{}"'.format(vboxnet,
|
try:
|
||||||
interface_number,
|
await self._execute("hostonlyif", ["create"])
|
||||||
self._vmname))
|
except GNS3VMError:
|
||||||
|
raise GNS3VMError('VirtualBox host-only network "{}" does not exist and could not be automatically created, please make the sure the network adapter {} configuration is valid for "{}"'.format(
|
||||||
|
vboxnet,
|
||||||
|
interface_number,
|
||||||
|
self._vmname
|
||||||
|
))
|
||||||
|
|
||||||
if backend_type == "hostonlyadapter" and not (await self._check_dhcp_server(vboxnet)):
|
if backend_type == "hostonlyadapter" and not (await self._check_dhcp_server(vboxnet)):
|
||||||
raise GNS3VMError('DHCP must be enabled on VirtualBox host-only network "{}"'.format(vboxnet))
|
try:
|
||||||
|
await self._add_dhcp_server(vboxnet)
|
||||||
|
except GNS3VMError as e:
|
||||||
|
raise GNS3VMError("Could not add DHCP server for vboxnet {}: {}, please configure manually".format(vboxnet, e))
|
||||||
|
|
||||||
vm_state = await self._get_state()
|
vm_state = await self._get_state()
|
||||||
log.info('"{}" state is {}'.format(self._vmname, vm_state))
|
log.info('"{}" state is {}'.format(self._vmname, vm_state))
|
||||||
@ -302,7 +347,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise GNS3VMError("Error while getting random port: {}".format(e))
|
raise GNS3VMError("Error while getting random port: {}".format(e))
|
||||||
|
|
||||||
if (await self._check_vbox_port_forwarding()):
|
if await self._check_vbox_port_forwarding():
|
||||||
# delete the GNS3VM NAT port forwarding rule if it exists
|
# delete the GNS3VM NAT port forwarding rule if it exists
|
||||||
log.info("Removing GNS3VM NAT port forwarding rule from interface {}".format(nat_interface_number))
|
log.info("Removing GNS3VM NAT port forwarding rule from interface {}".format(nat_interface_number))
|
||||||
await self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number), "delete", "GNS3VM"])
|
await self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number), "delete", "GNS3VM"])
|
||||||
|
@ -57,7 +57,7 @@ class CrashReport:
|
|||||||
Report crash to a third party service
|
Report crash to a third party service
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DSN = "https://226eee142b22cc399d1566b3dd4cbc86@o19455.ingest.sentry.io/38482"
|
DSN = "https://8dcaf668c2f31af6028fb4130bf2f58e@o19455.ingest.sentry.io/38482"
|
||||||
_instance = None
|
_instance = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
# or negative for a release candidate or beta (after the base version
|
# or negative for a release candidate or beta (after the base version
|
||||||
# number has been incremented)
|
# number has been incremented)
|
||||||
|
|
||||||
__version__ = "2.2.42"
|
__version__ = "2.2.43"
|
||||||
__version_info__ = (2, 2, 42, 0)
|
__version_info__ = (2, 2, 43, 0)
|
||||||
|
|
||||||
if "dev" in __version__:
|
if "dev" in __version__:
|
||||||
try:
|
try:
|
||||||
|
@ -232,8 +232,7 @@ class Route(object):
|
|||||||
response.set_status(408)
|
response.set_status(408)
|
||||||
response.json({"message": "Request canceled", "status": 408})
|
response.json({"message": "Request canceled", "status": 408})
|
||||||
raise # must raise to let aiohttp know the connection has been closed
|
raise # must raise to let aiohttp know the connection has been closed
|
||||||
except aiohttp.ClientError:
|
except (ConnectionResetError, aiohttp.ClientError):
|
||||||
log.warning("Client error")
|
|
||||||
response = Response(request=request, route=route)
|
response = Response(request=request, route=route)
|
||||||
response.set_status(408)
|
response.set_status(408)
|
||||||
response.json({"message": "Client error", "status": 408})
|
response.json({"message": "Client error", "status": 408})
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
jsonschema>=4.17.3,<4.18; python_version >= '3.7'
|
jsonschema>=4.17.3,<4.18; python_version >= '3.7' # v4.17.3 is the last version to support Python 3.7
|
||||||
jsonschema==3.2.0; python_version < '3.7' # v3.2.0 is the last version to support Python 3.6
|
jsonschema==3.2.0; python_version < '3.7' # v3.2.0 is the last version to support Python 3.6
|
||||||
aiohttp>=3.8.4,<3.9
|
aiohttp>=3.8.5,<3.9
|
||||||
aiohttp-cors>=0.7.0,<0.8
|
aiohttp-cors>=0.7.0,<0.8
|
||||||
aiofiles>=23.1.0,<23.2; python_version >= '3.7'
|
aiofiles>=23.2.1,<23.3; python_version >= '3.7'
|
||||||
aiofiles==0.8.0; python_version < '3.7' # v0.8.0 is the last version to support Python 3.6
|
aiofiles==0.8.0; python_version < '3.7' # v0.8.0 is the last version to support Python 3.6
|
||||||
Jinja2>=3.1.2,<3.2; python_version >= '3.7'
|
Jinja2>=3.1.2,<3.2; python_version >= '3.7'
|
||||||
Jinja2==3.0.3; python_version < '3.7' # v3.0.3 is the last version to support Python 3.6
|
Jinja2==3.0.3; python_version < '3.7' # v3.0.3 is the last version to support Python 3.6
|
||||||
sentry-sdk==1.29.2,<1.30
|
sentry-sdk==1.31.0,<1.32
|
||||||
psutil==5.9.5
|
psutil==5.9.5
|
||||||
async-timeout>=4.0.2,<4.1
|
async-timeout>=4.0.2,<4.1
|
||||||
distro>=1.8.0
|
distro>=1.8.0
|
||||||
py-cpuinfo>=9.0.0,<10.0
|
py-cpuinfo>=9.0.0,<10.0
|
||||||
|
platformdirs>=2.4.0
|
||||||
importlib-resources>=1.3; python_version <= '3.9'
|
importlib-resources>=1.3; python_version <= '3.9'
|
||||||
truststore>=0.7.0; python_version >= '3.10'
|
truststore>=0.8.0; python_version >= '3.10'
|
||||||
setuptools>=60.8.1; python_version >= '3.7'
|
setuptools>=60.8.1; python_version >= '3.7'
|
||||||
setuptools==59.6.0; python_version < '3.7' # v59.6.0 is the last version to support Python 3.6
|
setuptools==59.6.0; python_version < '3.7' # v59.6.0 is the last version to support Python 3.6
|
||||||
|
@ -182,7 +182,7 @@ async def test_create_vnc(compute_project, manager):
|
|||||||
"Binds": [
|
"Binds": [
|
||||||
"{}:/gns3:ro".format(get_resource("compute/docker/resources")),
|
"{}:/gns3:ro".format(get_resource("compute/docker/resources")),
|
||||||
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network")),
|
"{}:/gns3volumes/etc/network".format(os.path.join(vm.working_dir, "etc", "network")),
|
||||||
'/tmp/.X11-unix/:/tmp/.X11-unix/'
|
"/tmp/.X11-unix/X{0}:/tmp/.X11-unix/X{0}:ro".format(vm._display)
|
||||||
],
|
],
|
||||||
"Privileged": True
|
"Privileged": True
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
-rrequirements.txt
|
-rrequirements.txt
|
||||||
|
|
||||||
pywin32==305
|
pywin32==306
|
||||||
wmi==1.5.1
|
wmi==1.5.1
|
||||||
|
Loading…
Reference in New Issue
Block a user