Skip to content

Commit

Permalink
Merge pull request #3644 from GNS3/2.2
Browse files Browse the repository at this point in the history
Release v2.2.50
  • Loading branch information
grossmj authored Oct 21, 2024
2 parents fccfc01 + 9b5713d commit a3a0be8
Show file tree
Hide file tree
Showing 15 changed files with 149 additions and 75 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Change Log

## 2.2.50 21/10/2024

* Fix issue when pid file contains invalid data
* Add comment to indicate sentry-sdk is optional. Ref https://github.com/GNS3/gns3-server/issues/2423
* Improve information provided when uploading invalid appliance image. Fixes #3637
* Use "experimental features" option to force listening for HTTP notification streams. Ref #3579
* Fix to allow packet capture on more than 6 links. Fixes #3594
* Support for configuring MAC address in Docker containers
* Add KRDC to pre-configured VNC console commands

## 2.2.49 06/08/2024

* Upgrade jsonschema and sentry-sdk packages
Expand Down
20 changes: 0 additions & 20 deletions appveyor.yml

This file was deleted.

8 changes: 7 additions & 1 deletion gns3/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from .symbol import Symbol
from .local_server_config import LocalServerConfig
from .settings import LOCAL_SERVER_SETTINGS

from gns3.local_config import LocalConfig
from gns3.utils import parse_version

import logging
Expand Down Expand Up @@ -416,19 +418,23 @@ def _startListenNotifications(self):
self._notification_stream = None

# Qt websocket before Qt 5.6 doesn't support auth
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.6.0") or parse_version(QtCore.PYQT_VERSION_STR) < parse_version("5.6.0"):
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.6.0") or parse_version(QtCore.PYQT_VERSION_STR) < parse_version("5.6.0") or LocalConfig.instance().experimental():

self._notification_stream = Controller.instance().createHTTPQuery("GET", "/notifications", self._endListenNotificationCallback,
downloadProgressCallback=self._event_received,
networkManager=self._notification_network_manager,
timeout=None,
showProgress=False,
ignoreErrors=True)
url = self._http_client.url() + '/notifications'
log.info("Listening for controller notifications on '{}'".format(url))

else:
self._notification_stream = self._http_client.connectWebSocket(self._websocket, "/notifications/ws")
self._notification_stream.textMessageReceived.connect(self._websocket_event_received)
self._notification_stream.error.connect(self._websocket_error)
self._notification_stream.sslErrors.connect(self._sslErrorsSlot)
log.info("Listening for controller notifications on '{}'".format(self._notification_stream.requestUrl().toString()))

def stopListenNotifications(self):
if self._notification_stream:
Expand Down
2 changes: 1 addition & 1 deletion gns3/crash_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class CrashReport:
Report crash to a third party service
"""

DSN = "https://4cbe2abf0323ef3136a900d624b12567@o19455.ingest.us.sentry.io/38506"
DSN = "https://2f7ebda845810e764bfd049a40cc09e3@o19455.ingest.us.sentry.io/38506"
_instance = None

def __init__(self):
Expand Down
16 changes: 13 additions & 3 deletions gns3/dialogs/appliance_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,19 @@ def _importPushButtonClickedSlot(self, *args):
image = Image(self._appliance.template_type(), path, filename=disk["filename"])
try:
if "md5sum" in disk and image.md5sum != disk["md5sum"]:
reply = QtWidgets.QMessageBox.question(self, "Add appliance",
"This is not the correct file. The MD5 sum is {} and should be {}.\nDo you want to accept it at your own risks?".format(image.md5sum, disk["md5sum"]),
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
reply = QtWidgets.QMessageBox.question(
self,
"Add appliance",
"This is not the correct file.\n\n"
"MD5 checksum\n"
f"actual:\t{image.md5sum}\n"
f"expected:\t{disk['md5sum']}\n\n"
"File size\n"
f"actual:\t{image.filesize} bytes\n"
f"expected:\t{disk['filesize']} bytes\n\n"
"Do you want to accept it at your own risks?",
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No
)
if reply == QtWidgets.QMessageBox.No:
return
except OSError as e:
Expand Down
8 changes: 6 additions & 2 deletions gns3/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from .qt import sip
import uuid

from .qt import QtCore
from .qt import QtCore, QtNetwork
from .controller import Controller


Expand Down Expand Up @@ -78,6 +78,7 @@ def __init__(self, source_node, source_port, destination_node, destination_port,
self._deleting = False
self._capture_file_path = None
self._capture_file = None
self._network_manager = None
self._response_stream = None
self._capture_compute_id = None
self._initialized = False
Expand Down Expand Up @@ -117,12 +118,15 @@ def _parseResponse(self, result):
else:
self._capture_file = QtCore.QFile(self._capture_file_path)
self._capture_file.open(QtCore.QFile.WriteOnly)
if self._network_manager is None:
self._network_manager = QtNetwork.QNetworkAccessManager(self)
self._response_stream = Controller.instance().get("/projects/{project_id}/links/{link_id}/pcap".format(project_id=self.project().id(), link_id=self._link_id),
None,
showProgress=False,
downloadProgressCallback=self._downloadPcapProgress,
ignoreErrors=True, # If something is wrong avoid disconnect us from server
timeout=None)
timeout=None,
networkManager=self._network_manager)
log.debug("Has successfully started capturing packets on link {} to '{}'".format(self._link_id, self._capture_file_path))
else:
self._response_stream = None
Expand Down
12 changes: 10 additions & 2 deletions gns3/local_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ def isMainGui():

if os.path.exists(pid_path):
try:
with open(pid_path) as f:
with open(pid_path, encoding="utf-8") as f:
pid = int(f.read())
if pid != my_pid:
try:
Expand All @@ -498,9 +498,17 @@ def isMainGui():
return False
else:
return True
except (OSError, ValueError) as e:
except OSError as e:
log.critical("Can't read pid file %s: %s", pid_path, str(e))
return False
except ValueError as e:
log.warning("Invalid data in pid file %s: %s", pid_path, str(e))
try:
# try removing the file since it contains invalid data
os.remove(pid_path)
except OSError:
log.critical("Can't remove pid file %s", pid_path)
return False

try:
with open(pid_path, 'w+') as f:
Expand Down
4 changes: 4 additions & 0 deletions gns3/modules/docker/docker_vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def __init__(self, module, server, project):
docker_vm_settings = {"image": "",
"usage": "",
"adapters": DOCKER_CONTAINER_SETTINGS["adapters"],
"mac_address": DOCKER_CONTAINER_SETTINGS["mac_address"],
"custom_adapters": DOCKER_CONTAINER_SETTINGS["custom_adapters"],
"start_command": DOCKER_CONTAINER_SETTINGS["start_command"],
"environment": DOCKER_CONTAINER_SETTINGS["environment"],
Expand Down Expand Up @@ -88,6 +89,9 @@ def info(self):
port_name=port.name(),
port_description=port.description())

if port.macAddress():
port_info += " MAC address is {mac_address}\n".format(mac_address=port.macAddress())

usage = "\n" + self._settings.get("usage")
return info + port_info + usage

Expand Down
33 changes: 32 additions & 1 deletion gns3/modules/docker/pages/docker_vm_configuration_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
Configuration page for Docker images.
"""

import re

from gns3.qt import QtWidgets
from gns3.node import Node
from gns3.dialogs.custom_adapters_configuration_dialog import CustomAdaptersConfigurationDialog
Expand Down Expand Up @@ -69,15 +71,25 @@ def _customAdaptersConfigurationSlot(self):

if self._node:
adapters = self._settings["adapters"]
base_mac_address = self._settings["mac_address"]
else:
adapters = self.uiAdapterSpinBox.value()
mac = self.uiMacAddrLineEdit.text()
if mac != ":::::":
if not re.search(r"""^([0-9a-fA-F]{2}[:]){5}[0-9a-fA-F]{2}$""", mac):
QtWidgets.QMessageBox.critical(self, "MAC address", "Invalid MAC address (format required: hh:hh:hh:hh:hh:hh)")
return
else:
base_mac_address = mac
else:
base_mac_address = ""

ports = []
for adapter_number in range(0, adapters):
port_name = "eth{}".format(adapter_number)
ports.append(port_name)

dialog = CustomAdaptersConfigurationDialog(ports, self._custom_adapters, parent=self)
dialog = CustomAdaptersConfigurationDialog(ports, self._custom_adapters, "TAP", {"TAP": "Default"}, base_mac_address, parent=self)
dialog.show()
dialog.exec_()

Expand Down Expand Up @@ -150,6 +162,13 @@ def loadSettings(self, settings, node=None, group=False):
self.uiSymbolLineEdit.hide()
self.uiSymbolToolButton.hide()

# load the MAC address setting
self.uiMacAddrLineEdit.setInputMask("HH:HH:HH:HH:HH:HH;_")
if settings["mac_address"]:
self.uiMacAddrLineEdit.setText(settings["mac_address"])
else:
self.uiMacAddrLineEdit.clear()

self.uiUsageTextEdit.setPlainText(settings["usage"])

def _networkConfigEditSlot(self):
Expand Down Expand Up @@ -199,6 +218,18 @@ def saveSettings(self, settings, node=None, group=False):
else:
settings["name"] = name

# check and save the MAC address
mac = self.uiMacAddrLineEdit.text()
if mac != ":::::":
if not re.search(r"""^([0-9a-fA-F]{2}[:]){5}[0-9a-fA-F]{2}$""", mac):
QtWidgets.QMessageBox.critical(self, "MAC address", "Invalid MAC address (format required: hh:hh:hh:hh:hh:hh)")
if node:
raise ConfigurationError()
else:
settings["mac_address"] = mac
else:
settings["mac_address"] = None

if not node:
# these are template settings
settings["category"] = self.uiCategoryComboBox.itemData(self.uiCategoryComboBox.currentIndex())
Expand Down
1 change: 1 addition & 0 deletions gns3/modules/docker/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"name": "",
"image": "",
"adapters": 1,
"mac_address": "",
"custom_adapters": [],
"environment": "",
"console_type": "telnet",
Expand Down
40 changes: 25 additions & 15 deletions gns3/modules/docker/ui/docker_vm_configuration_page.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>938</width>
<height>872</height>
<width>504</width>
<height>560</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -103,27 +103,37 @@
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="uiMacAddrLabel">
<property name="text">
<string>Base MAC:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="uiMacAddrLineEdit"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="uiCustomAdaptersLabel">
<property name="text">
<string>Custom adapters:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<widget class="QPushButton" name="uiCustomAdaptersConfigurationPushButton">
<property name="text">
<string>&amp;Configure custom adapters</string>
</property>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QLabel" name="uiConsoleTypeLabel">
<property name="text">
<string>Console type:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetNoConstraint</enum>
Expand Down Expand Up @@ -166,14 +176,14 @@
</item>
</layout>
</item>
<item row="8" column="0">
<item row="9" column="0">
<widget class="QLabel" name="uiConsoleResolutionLabel">
<property name="text">
<string>VNC console resolution:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="9" column="1">
<widget class="QComboBox" name="uiConsoleResolutionComboBox">
<item>
<property name="text">
Expand Down Expand Up @@ -227,14 +237,14 @@
</item>
</widget>
</item>
<item row="9" column="0">
<item row="10" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>HTTP port in the container:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QSpinBox" name="uiConsoleHttpPortSpinBox">
<property name="minimum">
<number>1</number>
Expand All @@ -244,17 +254,17 @@
</property>
</widget>
</item>
<item row="10" column="0">
<item row="11" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>HTTP path:</string>
</property>
</widget>
</item>
<item row="10" column="1">
<item row="11" column="1">
<widget class="QLineEdit" name="uiHttpConsolePathLineEdit"/>
</item>
<item row="11" column="0">
<item row="12" column="0">
<widget class="QLabel" name="uiEnvironmentLabel">
<property name="text">
<string>Environment variables:
Expand All @@ -268,17 +278,17 @@
</property>
</widget>
</item>
<item row="11" column="1">
<item row="12" column="1">
<widget class="QTextEdit" name="uiEnvironmentTextEdit"/>
</item>
<item row="12" column="0">
<item row="13" column="0">
<widget class="QLabel" name="uiNetworkConfigLabel">
<property name="text">
<string>Network configuration</string>
</property>
</widget>
</item>
<item row="12" column="1">
<item row="13" column="1">
<widget class="QPushButton" name="uiNetworkConfigEditButton">
<property name="text">
<string>Edit</string>
Expand Down
Loading

0 comments on commit a3a0be8

Please sign in to comment.