mirror of
https://github.com/GNS3/gns3-gui.git
synced 2026-05-31 16:00:30 +03:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b5713df03 | ||
|
|
6df7dc4730 | ||
|
|
e84ef8bf13 | ||
|
|
f7703e3fa2 | ||
|
|
de8b9bc8f1 | ||
|
|
f21a530729 | ||
|
|
be2b5eecf6 | ||
|
|
2d4f6e6ecf | ||
|
|
c152de84de | ||
|
|
d34e7b377c | ||
|
|
74c55241cf | ||
|
|
6edb9c9303 | ||
|
|
5d14dd9ab8 | ||
|
|
0c7cae2222 | ||
|
|
9b882924c0 | ||
|
|
fccfc01f2e | ||
|
|
46872c664d | ||
|
|
89166b9d35 | ||
|
|
d0421e8b1f | ||
|
|
b35ce7303d | ||
|
|
47432568e6 | ||
|
|
42ea34ca6c | ||
|
|
9f3598d36d | ||
|
|
8df248a1e6 | ||
|
|
7196aeb3cf | ||
|
|
38657f4112 | ||
|
|
84017fa0f1 | ||
|
|
3aa5a5369f | ||
|
|
0ed791b946 | ||
|
|
133732b7ae | ||
|
|
2ed48def9f | ||
|
|
279a91d402 | ||
|
|
4906678d13 | ||
|
|
a5ff9318f0 | ||
|
|
faa802d59c | ||
|
|
01b5b8bfa8 | ||
|
|
b22c5c8442 | ||
|
|
141e7d8307 | ||
|
|
a6c7e0be59 | ||
|
|
fcea25dcbb | ||
|
|
f29c065164 | ||
|
|
c6b5494ce6 | ||
|
|
02b14f6aea | ||
|
|
e2cc378aee | ||
|
|
854e1fded6 |
@@ -10,7 +10,7 @@ jobs:
|
||||
name: Add issue to project
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/add-to-project@v0.4.0
|
||||
- uses: actions/add-to-project@v1.0.1
|
||||
with:
|
||||
project-url: https://github.com/orgs/GNS3/projects/3
|
||||
github-token: ${{ secrets.ADD_NEW_ISSUES_TO_PROJECT }}
|
||||
|
||||
73
.github/workflows/codeql.yml
vendored
73
.github/workflows/codeql.yml
vendored
@@ -15,62 +15,79 @@ on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '27 6 * * 2'
|
||||
- cron: '17 22 * * 6'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Use only 'java' to analyze code written in Java, Kotlin or both
|
||||
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
include:
|
||||
- language: python
|
||||
build-mode: none
|
||||
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# If the analyze step fails for one of the languages you are analyzing with
|
||||
# "We were unable to automatically build your code", modify the matrix above
|
||||
# to set the build mode to "manual" for that language. Then modify this step
|
||||
# to build your code.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
- if: matrix.build-mode == 'manual'
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||
'languages you are analyzing, replace this with the commands to build' \
|
||||
'your code, for example:'
|
||||
echo ' make bootstrap'
|
||||
echo ' make release'
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
2
.github/workflows/testing.yml
vendored
2
.github/workflows/testing.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build and run Docker image
|
||||
run: |
|
||||
docker build -t gns3-gui-test .
|
||||
|
||||
21
CHANGELOG
21
CHANGELOG
@@ -1,5 +1,26 @@
|
||||
# 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
|
||||
* Upgrade to PyQt5 v5.15.11
|
||||
* Add shortcuts info dialog
|
||||
* Added Key Shortcuts
|
||||
|
||||
## 2.2.48.1 12/07/2024
|
||||
|
||||
* No changes
|
||||
|
||||
## 2.2.48 08/07/2024
|
||||
|
||||
* Use "experimental features" to allow bypassing hostname validation. Ref #3524
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# Run tests inside a container
|
||||
FROM ubuntu:18.04
|
||||
FROM ubuntu:latest
|
||||
MAINTAINER GNS3 Team
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y --force-yes python3.6 python3-pyqt5 python3-pip python3-pyqt5.qtsvg python3-pyqt5.qtwebsockets python3.6-dev xvfb
|
||||
RUN apt-get install -y --force-yes python3 python3-pyqt5 python3-pip python3-pyqt5.qtsvg python3-pyqt5.qtwebsockets python3-dev xvfb
|
||||
RUN apt-get clean
|
||||
|
||||
ADD dev-requirements.txt /dev-requirements.txt
|
||||
ADD requirements.txt /requirements.txt
|
||||
RUN pip3 install --no-cache-dir -r /dev-requirements.txt
|
||||
RUN python3 -m pip install --break-system-packages --no-cache-dir -r /dev-requirements.txt
|
||||
|
||||
ADD . /src
|
||||
WORKDIR /src
|
||||
|
||||
CMD xvfb-run python3.6 -m pytest -vv
|
||||
CMD xvfb-run python3 -m pytest -vv
|
||||
|
||||
20
appveyor.yml
20
appveyor.yml
@@ -1,20 +0,0 @@
|
||||
version: '{build}-{branch}'
|
||||
|
||||
image: Visual Studio 2022
|
||||
|
||||
platform: x64
|
||||
|
||||
environment:
|
||||
PYTHON: "C:\\Python38-x64"
|
||||
DISTUTILS_USE_SDK: "1"
|
||||
|
||||
install:
|
||||
- cinst nmap
|
||||
- "%PYTHON%\\python.exe -m pip install -U pip setuptools" # upgrade pip & setuptools first
|
||||
- "%PYTHON%\\python.exe -m pip install -r dev-requirements.txt"
|
||||
- "%PYTHON%\\python.exe -m pip install -r win-requirements.txt"
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- "%PYTHON%\\python.exe -m pytest -v"
|
||||
@@ -1,5 +1,4 @@
|
||||
-rrequirements.txt
|
||||
|
||||
pytest==7.2.0
|
||||
flake8==5.0.4
|
||||
pytest-timeout==2.1.0
|
||||
pytest==8.3.2
|
||||
pytest-timeout==2.3.1
|
||||
|
||||
@@ -25,6 +25,8 @@ from .qt import QtCore, QtNetwork, QtGui, QtWidgets, QtWebSockets, qpartial, qsl
|
||||
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
|
||||
@@ -416,19 +418,23 @@ class Controller(QtCore.QObject):
|
||||
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:
|
||||
|
||||
@@ -50,7 +50,7 @@ class CrashReport:
|
||||
Report crash to a third party service
|
||||
"""
|
||||
|
||||
DSN = "https://a9154d40d27d0cecfdbf5943b2ea68d5@o19455.ingest.us.sentry.io/38506"
|
||||
DSN = "https://2f7ebda845810e764bfd049a40cc09e3@o19455.ingest.us.sentry.io/38506"
|
||||
_instance = None
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@@ -543,9 +543,19 @@ Usage: {}
|
||||
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:
|
||||
|
||||
@@ -23,7 +23,7 @@ import re
|
||||
from .qt import sip
|
||||
import uuid
|
||||
|
||||
from .qt import QtCore
|
||||
from .qt import QtCore, QtNetwork
|
||||
from .controller import Controller
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ class Link(QtCore.QObject):
|
||||
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
|
||||
@@ -117,12 +118,15 @@ class Link(QtCore.QObject):
|
||||
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
|
||||
|
||||
@@ -483,7 +483,7 @@ class LocalConfig(QtCore.QObject):
|
||||
|
||||
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:
|
||||
@@ -498,9 +498,17 @@ class LocalConfig(QtCore.QObject):
|
||||
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:
|
||||
|
||||
@@ -268,6 +268,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
self.uiExportDebugInformationAction.triggered.connect(self._exportDebugInformationSlot)
|
||||
self.uiDoctorAction.triggered.connect(self._doctorSlot)
|
||||
self.uiAcademyAction.triggered.connect(self._academyActionSlot)
|
||||
self.uiShortcutsAction.triggered.connect(self._shortcutsActionSlot)
|
||||
|
||||
# browsers tool bar connections
|
||||
self.uiBrowseRoutersAction.triggered.connect(self._browseRoutersActionSlot)
|
||||
@@ -979,6 +980,15 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
# start and connect to the local server if needed
|
||||
LocalServer.instance().localServerAutoStartIfRequired()
|
||||
|
||||
def _shortcutsActionSlot(self):
|
||||
|
||||
shortcuts_text = ""
|
||||
for action in self.findChildren(QtWidgets.QAction):
|
||||
shortcut = action.shortcut().toString()
|
||||
if shortcut:
|
||||
shortcuts_text += f"{action.toolTip()}: {shortcut}\n"
|
||||
QtWidgets.QMessageBox.information(self, "Shortcuts", shortcuts_text)
|
||||
|
||||
def _aboutQtActionSlot(self):
|
||||
"""
|
||||
Slot to display the Qt About dialog.
|
||||
|
||||
@@ -42,6 +42,7 @@ class DockerVM(Node):
|
||||
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"],
|
||||
@@ -88,6 +89,9 @@ class DockerVM(Node):
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -69,15 +71,25 @@ class DockerVMConfigurationPage(QtWidgets.QWidget, Ui_dockerVMConfigPageWidget):
|
||||
|
||||
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_()
|
||||
|
||||
@@ -150,6 +162,13 @@ class DockerVMConfigurationPage(QtWidgets.QWidget, Ui_dockerVMConfigPageWidget):
|
||||
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):
|
||||
@@ -199,6 +218,18 @@ class DockerVMConfigurationPage(QtWidgets.QWidget, Ui_dockerVMConfigPageWidget):
|
||||
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())
|
||||
|
||||
@@ -35,6 +35,7 @@ DOCKER_CONTAINER_SETTINGS = {
|
||||
"name": "",
|
||||
"image": "",
|
||||
"adapters": 1,
|
||||
"mac_address": "",
|
||||
"custom_adapters": [],
|
||||
"environment": "",
|
||||
"console_type": "telnet",
|
||||
|
||||
@@ -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">
|
||||
@@ -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>&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>
|
||||
@@ -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">
|
||||
@@ -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>
|
||||
@@ -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:
|
||||
@@ -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>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/modules/docker/ui/docker_vm_configuration_page.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.7
|
||||
# Created by: PyQt5 UI code generator 5.15.6
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
@@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_dockerVMConfigPageWidget(object):
|
||||
def setupUi(self, dockerVMConfigPageWidget):
|
||||
dockerVMConfigPageWidget.setObjectName("dockerVMConfigPageWidget")
|
||||
dockerVMConfigPageWidget.resize(938, 872)
|
||||
dockerVMConfigPageWidget.resize(504, 560)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(dockerVMConfigPageWidget)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.uiTabWidget = QtWidgets.QTabWidget(dockerVMConfigPageWidget)
|
||||
@@ -67,15 +67,21 @@ class Ui_dockerVMConfigPageWidget(object):
|
||||
self.uiAdapterSpinBox.setMinimum(1)
|
||||
self.uiAdapterSpinBox.setObjectName("uiAdapterSpinBox")
|
||||
self.gridLayout.addWidget(self.uiAdapterSpinBox, 5, 1, 1, 1)
|
||||
self.uiMacAddrLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiMacAddrLabel.setObjectName("uiMacAddrLabel")
|
||||
self.gridLayout.addWidget(self.uiMacAddrLabel, 6, 0, 1, 1)
|
||||
self.uiMacAddrLineEdit = QtWidgets.QLineEdit(self.tab)
|
||||
self.uiMacAddrLineEdit.setObjectName("uiMacAddrLineEdit")
|
||||
self.gridLayout.addWidget(self.uiMacAddrLineEdit, 6, 1, 1, 1)
|
||||
self.uiCustomAdaptersLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiCustomAdaptersLabel.setObjectName("uiCustomAdaptersLabel")
|
||||
self.gridLayout.addWidget(self.uiCustomAdaptersLabel, 6, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiCustomAdaptersLabel, 7, 0, 1, 1)
|
||||
self.uiCustomAdaptersConfigurationPushButton = QtWidgets.QPushButton(self.tab)
|
||||
self.uiCustomAdaptersConfigurationPushButton.setObjectName("uiCustomAdaptersConfigurationPushButton")
|
||||
self.gridLayout.addWidget(self.uiCustomAdaptersConfigurationPushButton, 6, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiCustomAdaptersConfigurationPushButton, 7, 1, 1, 1)
|
||||
self.uiConsoleTypeLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiConsoleTypeLabel.setObjectName("uiConsoleTypeLabel")
|
||||
self.gridLayout.addWidget(self.uiConsoleTypeLabel, 7, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiConsoleTypeLabel, 8, 0, 1, 1)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
@@ -90,10 +96,10 @@ class Ui_dockerVMConfigPageWidget(object):
|
||||
self.uiConsoleAutoStartCheckBox = QtWidgets.QCheckBox(self.tab)
|
||||
self.uiConsoleAutoStartCheckBox.setObjectName("uiConsoleAutoStartCheckBox")
|
||||
self.horizontalLayout.addWidget(self.uiConsoleAutoStartCheckBox)
|
||||
self.gridLayout.addLayout(self.horizontalLayout, 7, 1, 1, 1)
|
||||
self.gridLayout.addLayout(self.horizontalLayout, 8, 1, 1, 1)
|
||||
self.uiConsoleResolutionLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiConsoleResolutionLabel.setObjectName("uiConsoleResolutionLabel")
|
||||
self.gridLayout.addWidget(self.uiConsoleResolutionLabel, 8, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiConsoleResolutionLabel, 9, 0, 1, 1)
|
||||
self.uiConsoleResolutionComboBox = QtWidgets.QComboBox(self.tab)
|
||||
self.uiConsoleResolutionComboBox.setObjectName("uiConsoleResolutionComboBox")
|
||||
self.uiConsoleResolutionComboBox.addItem("")
|
||||
@@ -106,35 +112,35 @@ class Ui_dockerVMConfigPageWidget(object):
|
||||
self.uiConsoleResolutionComboBox.addItem("")
|
||||
self.uiConsoleResolutionComboBox.addItem("")
|
||||
self.uiConsoleResolutionComboBox.addItem("")
|
||||
self.gridLayout.addWidget(self.uiConsoleResolutionComboBox, 8, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiConsoleResolutionComboBox, 9, 1, 1, 1)
|
||||
self.label = QtWidgets.QLabel(self.tab)
|
||||
self.label.setObjectName("label")
|
||||
self.gridLayout.addWidget(self.label, 9, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.label, 10, 0, 1, 1)
|
||||
self.uiConsoleHttpPortSpinBox = QtWidgets.QSpinBox(self.tab)
|
||||
self.uiConsoleHttpPortSpinBox.setMinimum(1)
|
||||
self.uiConsoleHttpPortSpinBox.setMaximum(65535)
|
||||
self.uiConsoleHttpPortSpinBox.setObjectName("uiConsoleHttpPortSpinBox")
|
||||
self.gridLayout.addWidget(self.uiConsoleHttpPortSpinBox, 9, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiConsoleHttpPortSpinBox, 10, 1, 1, 1)
|
||||
self.label_2 = QtWidgets.QLabel(self.tab)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout.addWidget(self.label_2, 10, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.label_2, 11, 0, 1, 1)
|
||||
self.uiHttpConsolePathLineEdit = QtWidgets.QLineEdit(self.tab)
|
||||
self.uiHttpConsolePathLineEdit.setObjectName("uiHttpConsolePathLineEdit")
|
||||
self.gridLayout.addWidget(self.uiHttpConsolePathLineEdit, 10, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiHttpConsolePathLineEdit, 11, 1, 1, 1)
|
||||
self.uiEnvironmentLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiEnvironmentLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
||||
self.uiEnvironmentLabel.setWordWrap(False)
|
||||
self.uiEnvironmentLabel.setObjectName("uiEnvironmentLabel")
|
||||
self.gridLayout.addWidget(self.uiEnvironmentLabel, 11, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiEnvironmentLabel, 12, 0, 1, 1)
|
||||
self.uiEnvironmentTextEdit = QtWidgets.QTextEdit(self.tab)
|
||||
self.uiEnvironmentTextEdit.setObjectName("uiEnvironmentTextEdit")
|
||||
self.gridLayout.addWidget(self.uiEnvironmentTextEdit, 11, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiEnvironmentTextEdit, 12, 1, 1, 1)
|
||||
self.uiNetworkConfigLabel = QtWidgets.QLabel(self.tab)
|
||||
self.uiNetworkConfigLabel.setObjectName("uiNetworkConfigLabel")
|
||||
self.gridLayout.addWidget(self.uiNetworkConfigLabel, 12, 0, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiNetworkConfigLabel, 13, 0, 1, 1)
|
||||
self.uiNetworkConfigEditButton = QtWidgets.QPushButton(self.tab)
|
||||
self.uiNetworkConfigEditButton.setObjectName("uiNetworkConfigEditButton")
|
||||
self.gridLayout.addWidget(self.uiNetworkConfigEditButton, 12, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.uiNetworkConfigEditButton, 13, 1, 1, 1)
|
||||
self.uiTabWidget.addTab(self.tab, "")
|
||||
self.tab_2 = QtWidgets.QWidget()
|
||||
self.tab_2.setObjectName("tab_2")
|
||||
@@ -186,6 +192,7 @@ class Ui_dockerVMConfigPageWidget(object):
|
||||
self.uiSymbolToolButton.setText(_translate("dockerVMConfigPageWidget", "&Browse..."))
|
||||
self.uiCMDLabel.setText(_translate("dockerVMConfigPageWidget", "Start command:"))
|
||||
self.uiAdapterLabel.setText(_translate("dockerVMConfigPageWidget", "Adapters:"))
|
||||
self.uiMacAddrLabel.setText(_translate("dockerVMConfigPageWidget", "Base MAC:"))
|
||||
self.uiCustomAdaptersLabel.setText(_translate("dockerVMConfigPageWidget", "Custom adapters:"))
|
||||
self.uiCustomAdaptersConfigurationPushButton.setText(_translate("dockerVMConfigPageWidget", "&Configure custom adapters"))
|
||||
self.uiConsoleTypeLabel.setText(_translate("dockerVMConfigPageWidget", "Console type:"))
|
||||
|
||||
@@ -627,21 +627,24 @@ class Project(QtCore.QObject):
|
||||
return
|
||||
|
||||
# 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():
|
||||
path = "/projects/{project_id}/notifications".format(project_id=self._id)
|
||||
self._notification_stream = Controller.instance().createHTTPQuery("GET", path, self._endListenNotificationCallback,
|
||||
downloadProgressCallback=self._event_received,
|
||||
networkManager=self._notification_network_manager,
|
||||
timeout=None,
|
||||
showProgress=False,
|
||||
ignoreErrors=True)
|
||||
downloadProgressCallback=self._event_received,
|
||||
networkManager=self._notification_network_manager,
|
||||
timeout=None,
|
||||
showProgress=False,
|
||||
ignoreErrors=True)
|
||||
url = Controller.instance().getHttpClient().url() + path
|
||||
log.info("Listening for project notifications on '{}'".format(url))
|
||||
|
||||
else:
|
||||
path = "/projects/{project_id}/notifications/ws".format(project_id=self._id)
|
||||
self._notification_stream = Controller.instance().httpClient().connectWebSocket(self._websocket, path)
|
||||
self._notification_stream.textMessageReceived.connect(self._websocket_event_received)
|
||||
self._notification_stream.error.connect(self._websocket_error)
|
||||
self._notification_stream.sslErrors.connect(self._sslErrorsSlot)
|
||||
path = "/projects/{project_id}/notifications/ws".format(project_id=self._id)
|
||||
self._notification_stream = Controller.instance().httpClient().connectWebSocket(self._websocket, path)
|
||||
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 project notifications on '{}'".format(self._notification_stream.requestUrl().toString()))
|
||||
|
||||
def _endListenNotificationCallback(self, result, error=False, **kwargs):
|
||||
"""
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"enum": [
|
||||
"router",
|
||||
"multilayer_switch",
|
||||
"switch",
|
||||
"firewall",
|
||||
"guest"
|
||||
]
|
||||
|
||||
@@ -206,7 +206,8 @@ else:
|
||||
'TightVNC': 'vncviewer {host}:{port}',
|
||||
'Vinagre': 'vinagre {host}::{port}',
|
||||
'gvncviewer': 'gvncviewer {host}:{display}',
|
||||
'Remote Viewer': 'remote-viewer vnc://{host}:{port}'
|
||||
'Remote Viewer': 'remote-viewer vnc://{host}:{port}',
|
||||
'KRDC': 'krdc vnc://{host}:{port}'
|
||||
}
|
||||
|
||||
# default VNC console command on other systems
|
||||
|
||||
@@ -112,6 +112,7 @@ background-none;
|
||||
<addaction name="uiAcademyAction"/>
|
||||
<addaction name="uiDoctorAction"/>
|
||||
<addaction name="uiExportDebugInformationAction"/>
|
||||
<addaction name="uiShortcutsAction"/>
|
||||
<addaction name="uiAboutQtAction"/>
|
||||
<addaction name="uiAboutAction"/>
|
||||
</widget>
|
||||
@@ -644,6 +645,9 @@ background-none;
|
||||
<property name="statusTip">
|
||||
<string>Start/Resume all devices</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+B</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiStopAllAction">
|
||||
<property name="enabled">
|
||||
@@ -663,6 +667,9 @@ background-none;
|
||||
<property name="statusTip">
|
||||
<string>Stop all devices</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+E</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiConsoleAllAction">
|
||||
<property name="enabled">
|
||||
@@ -797,6 +804,9 @@ background-none;
|
||||
<property name="statusTip">
|
||||
<string>Suspend all devices</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+J</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiAddNoteAction">
|
||||
<property name="checkable">
|
||||
@@ -1147,6 +1157,9 @@ background-none;
|
||||
<property name="text">
|
||||
<string>Fit in view</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+1</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiActionFullscreen">
|
||||
<property name="text">
|
||||
@@ -1306,6 +1319,11 @@ background-none;
|
||||
<string>Reset GUI state</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="uiShortcutsAction">
|
||||
<property name="text">
|
||||
<string>&Shortcuts</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/PycharmProjects/gns3-gui/gns3/ui/main_window.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
@@ -455,6 +455,8 @@ class Ui_MainWindow(object):
|
||||
self.uiResetConsoleAllAction.setObjectName("uiResetConsoleAllAction")
|
||||
self.uiResetGUIStateAction = QtWidgets.QAction(MainWindow)
|
||||
self.uiResetGUIStateAction.setObjectName("uiResetGUIStateAction")
|
||||
self.uiShortcutsAction = QtWidgets.QAction(MainWindow)
|
||||
self.uiShortcutsAction.setObjectName("uiShortcutsAction")
|
||||
self.uiEditMenu.addAction(self.uiSelectAllAction)
|
||||
self.uiEditMenu.addAction(self.uiSelectNoneAction)
|
||||
self.uiEditMenu.addSeparator()
|
||||
@@ -479,6 +481,7 @@ class Ui_MainWindow(object):
|
||||
self.uiHelpMenu.addAction(self.uiAcademyAction)
|
||||
self.uiHelpMenu.addAction(self.uiDoctorAction)
|
||||
self.uiHelpMenu.addAction(self.uiExportDebugInformationAction)
|
||||
self.uiHelpMenu.addAction(self.uiShortcutsAction)
|
||||
self.uiHelpMenu.addAction(self.uiAboutQtAction)
|
||||
self.uiHelpMenu.addAction(self.uiAboutAction)
|
||||
self.uiViewMenu.addAction(self.uiActionFullscreen)
|
||||
@@ -604,9 +607,11 @@ class Ui_MainWindow(object):
|
||||
self.uiStartAllAction.setText(_translate("MainWindow", "Start/Resume all nodes"))
|
||||
self.uiStartAllAction.setToolTip(_translate("MainWindow", "Start/Resume all nodes"))
|
||||
self.uiStartAllAction.setStatusTip(_translate("MainWindow", "Start/Resume all devices"))
|
||||
self.uiStartAllAction.setShortcut(_translate("MainWindow", "Ctrl+B"))
|
||||
self.uiStopAllAction.setText(_translate("MainWindow", "Stop all nodes"))
|
||||
self.uiStopAllAction.setToolTip(_translate("MainWindow", "Stop all nodes"))
|
||||
self.uiStopAllAction.setStatusTip(_translate("MainWindow", "Stop all devices"))
|
||||
self.uiStopAllAction.setShortcut(_translate("MainWindow", "Ctrl+E"))
|
||||
self.uiConsoleAllAction.setText(_translate("MainWindow", "Console connect to all nodes"))
|
||||
self.uiConsoleAllAction.setToolTip(_translate("MainWindow", "Console connect to all nodes"))
|
||||
self.uiConsoleAllAction.setStatusTip(_translate("MainWindow", "Console to all devices"))
|
||||
@@ -635,6 +640,7 @@ class Ui_MainWindow(object):
|
||||
self.uiSuspendAllAction.setText(_translate("MainWindow", "Suspend all nodes"))
|
||||
self.uiSuspendAllAction.setToolTip(_translate("MainWindow", "Suspend all nodes"))
|
||||
self.uiSuspendAllAction.setStatusTip(_translate("MainWindow", "Suspend all devices"))
|
||||
self.uiSuspendAllAction.setShortcut(_translate("MainWindow", "Ctrl+J"))
|
||||
self.uiAddNoteAction.setText(_translate("MainWindow", "Add note"))
|
||||
self.uiAddNoteAction.setToolTip(_translate("MainWindow", "Add a note"))
|
||||
self.uiAddNoteAction.setStatusTip(_translate("MainWindow", "Add a note"))
|
||||
@@ -702,6 +708,7 @@ class Ui_MainWindow(object):
|
||||
self.uiAddLinkAction.setToolTip(_translate("MainWindow", "Add a link"))
|
||||
self.uiAddLinkAction.setStatusTip(_translate("MainWindow", "Add a link"))
|
||||
self.uiFitInViewAction.setText(_translate("MainWindow", "Fit in view"))
|
||||
self.uiFitInViewAction.setShortcut(_translate("MainWindow", "Ctrl+1"))
|
||||
self.uiActionFullscreen.setText(_translate("MainWindow", "Fullscreen"))
|
||||
self.uiActionFullscreen.setShortcut(_translate("MainWindow", "Ctrl+F"))
|
||||
self.uiSetupWizard.setText(_translate("MainWindow", "&Setup Wizard"))
|
||||
@@ -724,6 +731,7 @@ class Ui_MainWindow(object):
|
||||
self.uiResetDocksAction.setText(_translate("MainWindow", "Reset docks"))
|
||||
self.uiResetConsoleAllAction.setText(_translate("MainWindow", "Reset all console connections"))
|
||||
self.uiResetGUIStateAction.setText(_translate("MainWindow", "Reset GUI state"))
|
||||
self.uiShortcutsAction.setText(_translate("MainWindow", "&Shortcuts"))
|
||||
from ..compute_summary_view import ComputeSummaryView
|
||||
from ..console_view import ConsoleView
|
||||
from ..graphics_view import GraphicsView
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
|
||||
__version__ = "2.2.48"
|
||||
__version_info__ = (2, 2, 48, 0)
|
||||
__version__ = "2.2.50"
|
||||
__version_info__ = (2, 2, 50, 0)
|
||||
|
||||
if "dev" in __version__:
|
||||
try:
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
-rrequirements.txt
|
||||
|
||||
PyQt5==5.15.10
|
||||
PyQt5==5.15.11
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
jsonschema>=4.22.0,<4.23
|
||||
sentry-sdk==2.7.1,<2.8
|
||||
jsonschema>=4.23,<4.24
|
||||
sentry-sdk==2.12,<2.13 # optional dependency
|
||||
psutil==6.0.0
|
||||
distro>=1.9.0
|
||||
truststore>=0.9.1; python_version >= '3.10'
|
||||
|
||||
8
setup.py
8
setup.py
@@ -19,9 +19,9 @@ import sys
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools.command.test import test as TestCommand
|
||||
|
||||
# we only support Python 3 version >= 3.7
|
||||
if len(sys.argv) >= 2 and sys.argv[1] == "install" and sys.version_info < (3, 7):
|
||||
raise SystemExit("Python 3.7 or higher is required")
|
||||
# we only support Python 3 version >= 3.8
|
||||
if len(sys.argv) >= 2 and sys.argv[1] == "install" and sys.version_info < (3, 8):
|
||||
raise SystemExit("Python 3.8 or higher is required")
|
||||
|
||||
|
||||
class PyTest(TestCommand):
|
||||
@@ -79,7 +79,7 @@ setup(
|
||||
include_package_data=True,
|
||||
package_data={"gns3": ["configs/*.txt", "schemas/*.json"]},
|
||||
platforms="any",
|
||||
python_requires='>=3.7',
|
||||
python_requires='>=3.8',
|
||||
setup_requires=["setuptools>=17.1"],
|
||||
classifiers=[
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
|
||||
@@ -65,8 +65,8 @@
|
||||
{
|
||||
"filename": "empty100G.qcow2",
|
||||
"version": "100G",
|
||||
"checksum": "d08fdec95fffbda3f04e9a00db49295df73ae4a507396e442ba9e4ad5c14ce5a",
|
||||
"checksum_type": "sha256",
|
||||
"checksum": "1e6409a4523ada212dea2ebc50e50a65",
|
||||
"checksum_type": "md5",
|
||||
"filesize": 198656,
|
||||
"download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/",
|
||||
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty100G.qcow2/download"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-rrequirements.txt
|
||||
|
||||
PyQt5==5.15.10 # pyup: ignore
|
||||
PyQt5==5.15.11 # pyup: ignore
|
||||
pywin32==306 # pyup: ignore
|
||||
|
||||
Reference in New Issue
Block a user