def _editVPCSSlot(self): """ Edits a VPCS node template. """ item = self.uiVPCSTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) vpcs_node = self._vpcs_nodes[key] dialog = ConfigurationDialog(vpcs_node["name"], vpcs_node, VPCSNodeConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon(vpcs_node["symbol"], qpartial(self._setItemIcon, item)) if vpcs_node["name"] != item.text(0): new_key = "{server}:{name}".format(server=vpcs_node["server"], name=vpcs_node["name"]) if new_key in self._vpcs_nodes: QtWidgets.QMessageBox.critical(self, "VPCS node", "VPCS node name {} already exists for server {}".format(vpcs_node["name"], vpcs_node["server"])) vpcs_node["name"] = item.text(0) return self._vpcs_nodes[new_key] = self._vpcs_nodes[key] del self._vpcs_nodes[key] item.setText(0, vpcs_node["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(vpcs_node)
def done(self, result): """ This dialog is closed. :param result: ignored """ Controller.instance().setDisplayError(True) settings = self.parentWidget().settings() if result: reply = QtWidgets.QMessageBox.question( self, "Wizard", "Do you want to run the wizard again when starting GNS3?", QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.Yes: settings["hide_setup_wizard"] = False elif reply == QtWidgets.QMessageBox.No: settings["hide_setup_wizard"] = True else: local_server_settings = LocalServer.instance().localServerSettings( ) if local_server_settings["host"] is None: local_server_settings["host"] = DEFAULT_LOCAL_SERVER_HOST LocalServer.instance().updateLocalServerSettings( local_server_settings) settings["hide_setup_wizard"] = self.uiShowCheckBox.isChecked() self.parentWidget().setSettings(settings) super().done(result)
def loadPreferences(self): """ Loads the VirtualBox VM preferences. """ self._virtualbox_vms = {} templates = TemplateManager.instance().templates() for template_id, template in templates.items(): if template.template_type( ) == "virtualbox" and not template.builtin(): vmname = template.settings()["vmname"] server = template.compute_id() #TODO: use template id for the key key = "{server}:{vmname}".format(server=server, vmname=vmname) self._virtualbox_vms[key] = copy.deepcopy(template.settings()) self._items.clear() for key, vbox_vm in self._virtualbox_vms.items(): item = QtWidgets.QTreeWidgetItem(self.uiVirtualBoxVMsTreeWidget) item.setText(0, vbox_vm["name"]) Controller.instance().getSymbolIcon( vbox_vm["symbol"], qpartial(self._setItemIcon, item)) item.setData(0, QtCore.Qt.UserRole, key) self._items.append(item) if self._items: self.uiVirtualBoxVMsTreeWidget.setCurrentItem(self._items[0]) self.uiVirtualBoxVMsTreeWidget.sortByColumn( 0, QtCore.Qt.AscendingOrder) self.uiVirtualBoxVMsTreeWidget.setMaximumWidth( self.uiVirtualBoxVMsTreeWidget.sizeHintForColumn(0) + 10)
def __init__(self, parent): super().__init__(parent) self.setupUi(self) self.adjustSize() self._gns3_vm_settings = { "enable": True, "headless": False, "when_exit": "stop", "engine": "vmware", "vcpus": 1, "ram": 2048, "vmname": "GNS3 VM", "port": 80 } self.setWizardStyle(QtWidgets.QWizard.ModernStyle) if sys.platform.startswith("darwin"): # we want to see the cancel button on OSX self.setOptions(QtWidgets.QWizard.NoDefaultButton) self.uiLocalServerToolButton.clicked.connect(self._localServerBrowserSlot) self.uiGNS3VMDownloadLinkUrlLabel.setText("") self.uiRefreshPushButton.clicked.connect(self._refreshVMListSlot) self.uiVmwareRadioButton.clicked.connect(self._listVMwareVMsSlot) self.uiVirtualBoxRadioButton.clicked.connect(self._listVirtualBoxVMsSlot) settings = parent.settings() self.uiShowCheckBox.setChecked(settings["hide_setup_wizard"]) # by default all radio buttons are unchecked self.uiVmwareRadioButton.setAutoExclusive(False) self.uiVirtualBoxRadioButton.setAutoExclusive(False) self.uiVmwareRadioButton.setChecked(False) self.uiVirtualBoxRadioButton.setChecked(False) # Mandatory fields self.uiLocalServerWizardPage.registerField("path*", self.uiLocalServerPathLineEdit) # load all available addresses for address in QtNetwork.QNetworkInterface.allAddresses(): if address.protocol() in [QtNetwork.QAbstractSocket.IPv4Protocol, QtNetwork.QAbstractSocket.IPv6Protocol]: address_string = address.toString() if address_string.startswith("169.254") or address_string.startswith("fe80"): # ignore link-local addresses, could not use https://doc.qt.io/qt-5/qhostaddress.html#isLinkLocal # because it was introduced in Qt 5.11 continue self.uiLocalServerHostComboBox.addItem(address_string, address_string) self.uiLocalServerHostComboBox.addItem("localhost", "localhost") # local host self.uiLocalServerHostComboBox.addItem("::", "::") # all IPv6 addresses self.uiLocalServerHostComboBox.addItem("0.0.0.0", "0.0.0.0") # all IPv4 addresses if sys.platform.startswith("linux"): self.uiLocalRadioButton.setChecked(True) self.uiLocalLabel.setText("Dependencies like Dynamips and Qemu must be manually installed") Controller.instance().connected_signal.connect(self._refreshLocalServerStatusSlot) Controller.instance().connection_failed_signal.connect(self._refreshLocalServerStatusSlot)
def _iouDeviceEditSlot(self): """ Edits an IOU device. """ item = self.uiIOUDevicesTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) iou_device = self._iou_devices[key] dialog = ConfigurationDialog(iou_device["name"], iou_device, iouDeviceConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon( iou_device["symbol"], qpartial(self._setItemIcon, item)) if iou_device["name"] != item.text(0): new_key = "{server}:{name}".format( server=iou_device["server"], name=iou_device["name"]) if new_key in self._iou_devices: QtWidgets.QMessageBox.critical( self, "IOU device", "IOU device name {} already exists for server {}". format(iou_device["name"], iou_device["server"])) iou_device["name"] = item.text(0) return self._iou_devices[new_key] = self._iou_devices[key] del self._iou_devices[key] item.setText(0, iou_device["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(dialog.settings)
def _getSettingsCallback(self, result, error=False, **kwargs): if sip_is_deleted(self.uiRamSpinBox) or sip_is_deleted(self): return if error: if "message" in result: log.error( "Error while getting the GNS3 VM settings : {}".format( result["message"])) return self._old_settings = copy.copy(result) self._settings = result self.uiAllocatevCPUsRAMCheckBox.setChecked( self._settings["allocate_vcpus_ram"]) self.uiRamSpinBox.setValue(self._settings["ram"]) self.uiCpuSpinBox.setValue(self._settings["vcpus"]) self.uiPortSpinBox.setValue(self._settings.get("port", 3080)) self.uiEnableVMCheckBox.setChecked(self._settings["enable"]) if self._settings["when_exit"] == "keep": self.uiWhenExitKeepRadioButton.setChecked(True) elif self._settings["when_exit"] == "suspend": self.uiWhenExitSuspendRadioButton.setChecked(True) else: self.uiWhenExitStopRadioButton.setChecked(True) self.uiHeadlessCheckBox.setChecked(self._settings["headless"]) Controller.instance().get("/gns3vm/engines", self._listEnginesCallback)
def _qemuVMEditSlot(self): """ Edits a QEMU VM. """ item = self.uiQemuVMsTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) qemu_vm = self._qemu_vms[key] dialog = ConfigurationDialog(qemu_vm["name"], qemu_vm, QemuVMConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon( qemu_vm["symbol"], qpartial(self._setItemIcon, item)) if qemu_vm["name"] != item.text(0): new_key = "{server}:{name}".format( server=qemu_vm["compute_id"], name=qemu_vm["name"]) if new_key in self._qemu_vms: QtWidgets.QMessageBox.critical( self, "QEMU VM", "QEMU VM name {} already exists for server {}". format(qemu_vm["name"], qemu_vm["compute_id"])) qemu_vm["name"] = item.text(0) return self._qemu_vms[new_key] = self._qemu_vms[key] del self._qemu_vms[key] item.setText(0, qemu_vm["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(qemu_vm)
def _iouDeviceEditSlot(self): """ Edits an IOU device. """ item = self.uiIOUDevicesTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) iou_device = self._iou_devices[key] dialog = ConfigurationDialog(iou_device["name"], iou_device, iouDeviceConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon(iou_device["symbol"], qpartial(self._setItemIcon, item)) if iou_device["name"] != item.text(0): new_key = "{server}:{name}".format(server=iou_device["compute_id"], name=iou_device["name"]) if new_key in self._iou_devices: QtWidgets.QMessageBox.critical(self, "IOU device", "IOU device name {} already exists for server {}".format(iou_device["name"], iou_device["compute_id"])) iou_device["name"] = item.text(0) return self._iou_devices[new_key] = self._iou_devices[key] del self._iou_devices[key] item.setText(0, iou_device["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(dialog.settings)
def _iouDeviceCopySlot(self): """ Copies an IOU device. """ item = self.uiIOUDevicesTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) copied_iou_device_settings = copy.deepcopy(self._iou_devices[key]) new_name, ok = QtWidgets.QInputDialog.getText(self, "Copy IOU template", "Template name:", QtWidgets.QLineEdit.Normal, "Copy of {}".format(copied_iou_device_settings["name"])) if ok: key = "{server}:{name}".format(server=copied_iou_device_settings["compute_id"], name=new_name) if key in self._iou_devices: QtWidgets.QMessageBox.critical(self, "IOU template", "IOU template name {} already exists".format(new_name)) return self._iou_devices[key] = IOU_DEVICE_SETTINGS.copy() self._iou_devices[key].update(copied_iou_device_settings) self._iou_devices[key]["name"] = new_name self._iou_devices[key].pop("template_id", None) item = QtWidgets.QTreeWidgetItem(self.uiIOUDevicesTreeWidget) item.setText(0, self._iou_devices[key]["name"]) Controller.instance().getSymbolIcon(self._iou_devices[key]["symbol"], qpartial(self._setItemIcon, item)) item.setData(0, QtCore.Qt.UserRole, key) self._items.append(item) self.uiIOUDevicesTreeWidget.setCurrentItem(item)
def savePreferences(self): """ Saves the preferences on controller. """ if not self._old_settings: return if self.uiWhenExitKeepRadioButton.isChecked(): when_exit = "keep" elif self.uiWhenExitSuspendRadioButton.isChecked(): when_exit = "suspend" else: when_exit = "stop" settings = { "enable": self.uiEnableVMCheckBox.isChecked(), "vmname": self.uiVMListComboBox.currentData(), "headless": self.uiHeadlessCheckBox.isChecked(), "when_exit": when_exit, "engine": self.uiGNS3VMEngineComboBox.currentData(), "ram": self.uiRamSpinBox.value(), "vcpus": self.uiCpuSpinBox.value(), "port": self.uiPortSpinBox.value() } if self._old_settings != settings: Controller.instance().put("/gns3vm", self._saveSettingsCallback, settings, timeout=60 * 5) self._old_settings = copy.copy(settings)
def _startListenNotifications(self): if not Controller.instance().connected(): 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"): 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) else: path = "/projects/{project_id}/notifications/ws".format( project_id=self._id) self._notification_stream = Controller.instance().connectWebSocket( path) self._notification_stream.textMessageReceived.connect( self._websocket_event_received) self._notification_stream.error.connect(self._websocket_error)
def _editCloudNodeSlot(self): """ Edits a cloud node template. """ item = self.uiCloudNodesTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) cloud_node = self._cloud_nodes[key] dialog = ConfigurationDialog(cloud_node["name"], cloud_node, CloudConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon( cloud_node["symbol"], qpartial(self._setItemIcon, item)) if cloud_node["name"] != item.text(0): new_key = "{server}:{name}".format( server=cloud_node["server"], name=cloud_node["name"]) if new_key in self._cloud_nodes: QtWidgets.QMessageBox.critical( self, "Cloud node", "Cloud node name {} already exists for server {}". format(cloud_node["name"], cloud_node["server"])) cloud_node["name"] = item.text(0) return self._cloud_nodes[new_key] = self._cloud_nodes[key] del self._cloud_nodes[key] item.setText(0, cloud_node["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(cloud_node)
def _editEthernetHubSlot(self): """ Edits an Ethernet hub template. """ item = self.uiEthernetHubsTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) ethernet_hub = self._ethernet_hubs[key] dialog = ConfigurationDialog(ethernet_hub["name"], ethernet_hub, EthernetHubConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon( ethernet_hub["symbol"], qpartial(self._setItemIcon, item)) if ethernet_hub["name"] != item.text(0): new_key = "{server}:{name}".format( server=ethernet_hub["server"], name=ethernet_hub["name"]) if new_key in self._ethernet_hubs: QtWidgets.QMessageBox.critical( self, "Ethernet hub", "Ethernet hub name {} already exists for server {}" .format(ethernet_hub["name"], ethernet_hub["server"])) ethernet_hub["name"] = item.text(0) return self._ethernet_hubs[new_key] = self._ethernet_hubs[key] del self._ethernet_hubs[key] item.setText(0, ethernet_hub["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(ethernet_hub)
def loadPreferences(self): """ Loads the Docker VM preferences. """ docker_module = Docker.instance() self._docker_containers = copy.deepcopy(docker_module.VMs()) self._items.clear() for key, docker_image in self._docker_containers.items(): item = QtWidgets.QTreeWidgetItem(self.uiDockerVMsTreeWidget) item.setText(0, docker_image["name"]) Controller.instance().getSymbolIcon( docker_image["symbol"], qpartial(self._setItemIcon, item)) item.setData(0, QtCore.Qt.UserRole, key) self._items.append(item) if self._items: self.uiDockerVMsTreeWidget.setCurrentItem(self._items[0]) self.uiDockerVMsTreeWidget.sortByColumn(0, QtCore.Qt.AscendingOrder) self.uiDockerVMsTreeWidget.setMaximumWidth( self.uiDockerVMsTreeWidget.sizeHintForColumn(0) + 10)
def loadPreferences(self): """ Loads the IOU devices preferences. """ self._iou_devices = {} templates = TemplateManager.instance().templates() for template_id, template in templates.items(): if template.template_type() == "iou" and not template.builtin(): name = template.name() server = template.compute_id() #TODO: use template id for the key key = "{server}:{name}".format(server=server, name=name) self._iou_devices[key] = copy.deepcopy(template.settings()) self._items.clear() for key, iou_device in self._iou_devices.items(): item = QtWidgets.QTreeWidgetItem(self.uiIOUDevicesTreeWidget) item.setText(0, iou_device["name"]) Controller.instance().getSymbolIcon(iou_device["symbol"], qpartial(self._setItemIcon, item)) item.setData(0, QtCore.Qt.UserRole, key) self._items.append(item) if self._items: self.uiIOUDevicesTreeWidget.setCurrentItem(self._items[0]) self.uiIOUDevicesTreeWidget.sortByColumn(0, QtCore.Qt.AscendingOrder) self.uiIOUDevicesTreeWidget.setMaximumWidth(self.uiIOUDevicesTreeWidget.sizeHintForColumn(0) + 10)
def _editVPCSSlot(self): """ Edits a VPCS node. """ item = self.uiVPCSTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) vpcs_node = self._vpcs_nodes[key] dialog = ConfigurationDialog(vpcs_node["name"], vpcs_node, VPCSNodeConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon(vpcs_node["symbol"], qpartial(self._setItemIcon, item)) if vpcs_node["name"] != item.text(0): new_key = "{server}:{name}".format(server=vpcs_node["compute_id"], name=vpcs_node["name"]) if new_key in self._vpcs_nodes: QtWidgets.QMessageBox.critical(self, "VPCS node", "VPCS node name {} already exists for server {}".format(vpcs_node["name"], vpcs_node["compute_id"])) vpcs_node["name"] = item.text(0) return self._vpcs_nodes[new_key] = self._vpcs_nodes[key] del self._vpcs_nodes[key] item.setText(0, vpcs_node["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(vpcs_node)
def _qemuVMNewSlot(self): """ Creates a new VM. """ wizard = QemuVMWizard(self._qemu_vms, parent=self) wizard.show() if wizard.exec_(): new_vm_settings = wizard.getSettings() key = "{server}:{name}".format( server=new_vm_settings["compute_id"], name=new_vm_settings["name"]) if key in self._qemu_vms: QtWidgets.QMessageBox.critical( self, "New QEMU VM", "VM name {} already exists".format( new_vm_settings["name"])) return self._qemu_vms[key] = QEMU_VM_SETTINGS.copy() self._qemu_vms[key].update(new_vm_settings) item = QtWidgets.QTreeWidgetItem(self.uiQemuVMsTreeWidget) item.setText(0, self._qemu_vms[key]["name"]) Controller.instance().getSymbolIcon( self._qemu_vms[key]["symbol"], qpartial(self._setItemIcon, item)) item.setData(0, QtCore.Qt.UserRole, key) self._items.append(item) self.uiQemuVMsTreeWidget.setCurrentItem(item)
def _dockerImageEditSlot(self): """ Edits a Docker image. """ item = self.uiDockerVMsTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) docker_container = self._docker_containers[key] dialog = ConfigurationDialog(docker_container["name"], docker_container, DockerVMConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon(docker_container["symbol"], qpartial(self._setItemIcon, item)) if docker_container["name"] != item.text(0): new_key = "{server}:{name}".format(server=docker_container["compute_id"], name=docker_container["name"]) if new_key in self._docker_containers: QtWidgets.QMessageBox.critical(self, "Docker container", "Docker container name {} already exists for server {}".format(docker_container["name"], docker_container["compute_id"])) docker_container["name"] = item.text(0) return self._docker_containers[new_key] = self._docker_containers[key] del self._docker_containers[key] item.setText(0, docker_container["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(docker_container)
def _iouDeviceCopySlot(self): """ Copies an IOU device. """ item = self.uiIOUDevicesTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) copied_iou_device_settings = copy.deepcopy(self._iou_devices[key]) new_name, ok = QtWidgets.QInputDialog.getText( self, "Copy IOU template", "Template name:", QtWidgets.QLineEdit.Normal, "Copy of {}".format(copied_iou_device_settings["name"])) if ok: key = "{server}:{name}".format( server=copied_iou_device_settings["compute_id"], name=new_name) if key in self._iou_devices: QtWidgets.QMessageBox.critical( self, "IOU template", "IOU template name {} already exists".format(new_name)) return self._iou_devices[key] = IOU_DEVICE_SETTINGS.copy() self._iou_devices[key].update(copied_iou_device_settings) self._iou_devices[key]["name"] = new_name self._iou_devices[key].pop("template_id", None) item = QtWidgets.QTreeWidgetItem(self.uiIOUDevicesTreeWidget) item.setText(0, self._iou_devices[key]["name"]) Controller.instance().getSymbolIcon( self._iou_devices[key]["symbol"], qpartial(self._setItemIcon, item)) item.setData(0, QtCore.Qt.UserRole, key) self._items.append(item) self.uiIOUDevicesTreeWidget.setCurrentItem(item)
def updateLocalServerSettings(self, new_settings): """ Update the local server settings. Keep the key not in new_settings """ old_settings = copy.copy(self._settings) if not self._settings: self._settings = new_settings else: self._settings.update(new_settings) self._port = self._settings["port"] LocalServerConfig.instance().saveSettings("Server", self._settings) # Settings have changed we need to restart the server if old_settings != self._settings: if self._settings["auto_start"]: # We restart the local server only if we really need. Auth can be hot change settings_require_restart = ('host', 'port', 'path') need_restart = False for s in settings_require_restart: if old_settings.get(s) != self._settings.get(s): need_restart = True if need_restart: self.stopLocalServer(wait=True) self.localServerAutoStartIfRequire() # If the controller is remote: else: self.stopLocalServer(wait=True) if self._settings.get("host") is None: self._http_client = None else: self._http_client = HTTPClient(self._settings) Controller.instance().setHttpClient(self._http_client)
def _editCloudNodeSlot(self): """ Edits a cloud node. """ item = self.uiCloudNodesTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) cloud_node = self._cloud_nodes[key] dialog = ConfigurationDialog(cloud_node["name"], cloud_node, CloudConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon(cloud_node["symbol"], qpartial(self._setItemIcon, item)) if cloud_node["name"] != item.text(0): new_key = "{server}:{name}".format(server=cloud_node["compute_id"], name=cloud_node["name"]) if new_key in self._cloud_nodes: QtWidgets.QMessageBox.critical(self, "Cloud node", "Cloud node name {} already exists for server {}".format(cloud_node["name"], cloud_node["compute_id"])) cloud_node["name"] = item.text(0) return self._cloud_nodes[new_key] = self._cloud_nodes[key] del self._cloud_nodes[key] item.setText(0, cloud_node["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(cloud_node)
def loadPreferences(self): """ Loads the ethernet hub preferences. """ self._ethernet_hubs = {} templates = TemplateManager.instance().templates() for template_id, template in templates.items(): if template.template_type( ) == "ethernet_hub" and not template.builtin(): name = template.name() server = template.compute_id() #TODO: use template id for the key key = "{server}:{name}".format(server=server, name=name) self._ethernet_hubs[key] = copy.deepcopy(template.settings()) self._items.clear() for key, ethernet_hub in self._ethernet_hubs.items(): item = QtWidgets.QTreeWidgetItem(self.uiEthernetHubsTreeWidget) item.setText(0, ethernet_hub["name"]) Controller.instance().getSymbolIcon( ethernet_hub["symbol"], qpartial(self._setItemIcon, item)) item.setData(0, QtCore.Qt.UserRole, key) self._items.append(item) if self._items: self.uiEthernetHubsTreeWidget.setCurrentItem(self._items[0]) self.uiEthernetHubsTreeWidget.sortByColumn( 0, QtCore.Qt.AscendingOrder) self.uiEthernetHubsTreeWidget.setMaximumWidth( self.uiEthernetHubsTreeWidget.sizeHintForColumn(0) + 20)
def updateLocalServerSettings(self, new_settings): """ Update the local server settings. Keep the key not in new_settings """ old_settings = copy.copy(self._settings) if not self._settings: self._settings = new_settings else: self._settings.update(new_settings) self._port = self._settings["port"] LocalServerConfig.instance().saveSettings("Server", self._settings) # Settings have changed we need to restart the server if old_settings != self._settings: if self._settings["auto_start"]: # We restart the local server only if we really need. Auth can be hot change settings_require_restart = ('host', 'port', 'path') need_restart = False for s in settings_require_restart: if old_settings.get(s) != self._settings.get(s): need_restart = True if need_restart: self.stopLocalServer(wait=True) self.localServerAutoStartIfRequired() # If the controller is remote: else: self.stopLocalServer(wait=True) if self._settings.get("host") is None: self._http_client = None else: self._http_client = HTTPClient(self._settings) Controller.instance().setHttpClient(self._http_client)
def _downloadAppliancesSlot(self): """ Request server to update appliances from online registry. """ ApplianceManager.instance().refresh(update=True) Controller.instance().clearStaticCache()
def _uploadImageToRemoteServer(self, path, server, node_type): """ Upload image to remote server :param path: File path on computer :param server: The server where the images should be located :param node_type: Image node_type :returns path: Final path """ if node_type == 'QEMU': upload_endpoint = '/qemu/images' elif node_type == 'IOU': upload_endpoint = '/iou/images' elif node_type == 'DYNAMIPS': upload_endpoint = '/dynamips/images' else: raise Exception('Invalid node type') filename = self._getRelativeImagePath(path, node_type).replace("\\", "/") Controller.instance().postCompute( '{}/{}'.format(upload_endpoint, filename), server, None, body=pathlib.Path(path), progressText="Uploading {}".format(filename), timeout=None) return filename
def savePreferences(self): """ Saves the preferences on controller. """ if not self._old_settings: return if self.uiWhenExitKeepRadioButton.isChecked(): when_exit = "keep" elif self.uiWhenExitSuspendRadioButton.isChecked(): when_exit = "suspend" else: when_exit = "stop" settings = { "enable": self.uiEnableVMCheckBox.isChecked(), "vmname": self.uiVMListComboBox.currentData(), "headless": self.uiHeadlessCheckBox.isChecked(), "when_exit": when_exit, "engine": self.uiGNS3VMEngineComboBox.currentData(), "ram": self.uiRamSpinBox.value(), "vcpus": self.uiCpuSpinBox.value() } if self._old_settings != settings: Controller.instance().put("/gns3vm", self._saveSettingsCallback, settings, timeout=60 * 5) self._old_settings = copy.copy(settings)
def _editEthernetHubSlot(self): """ Edits an Ethernet hub. """ item = self.uiEthernetHubsTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) ethernet_hub = self._ethernet_hubs[key] dialog = ConfigurationDialog(ethernet_hub["name"], ethernet_hub, EthernetHubConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon(ethernet_hub["symbol"], qpartial(self._setItemIcon, item)) if ethernet_hub["name"] != item.text(0): new_key = "{server}:{name}".format(server=ethernet_hub["compute_id"], name=ethernet_hub["name"]) if new_key in self._ethernet_hubs: QtWidgets.QMessageBox.critical(self, "Ethernet hub", "Ethernet hub name {} already exists for server {}".format(ethernet_hub["name"], ethernet_hub["compute_id"])) ethernet_hub["name"] = item.text(0) return self._ethernet_hubs[new_key] = self._ethernet_hubs[key] del self._ethernet_hubs[key] item.setText(0, ethernet_hub["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(ethernet_hub)
def _qemuVMEditSlot(self): """ Edits a QEMU VM. """ item = self.uiQemuVMsTreeWidget.currentItem() if item: key = item.data(0, QtCore.Qt.UserRole) qemu_vm = self._qemu_vms[key] dialog = ConfigurationDialog(qemu_vm["name"], qemu_vm, QemuVMConfigurationPage(), parent=self) dialog.show() if dialog.exec_(): # update the icon Controller.instance().getSymbolIcon(qemu_vm["symbol"], qpartial(self._setItemIcon, item)) if qemu_vm["name"] != item.text(0): new_key = "{server}:{name}".format(server=qemu_vm["server"], name=qemu_vm["name"]) if new_key in self._qemu_vms: QtWidgets.QMessageBox.critical(self, "QEMU VM", "QEMU VM name {} already exists for server {}".format(qemu_vm["name"], qemu_vm["server"])) qemu_vm["name"] = item.text(0) return self._qemu_vms[new_key] = self._qemu_vms[key] del self._qemu_vms[key] item.setText(0, qemu_vm["name"]) item.setData(0, QtCore.Qt.UserRole, new_key) self._refreshInfo(qemu_vm)
def __init__(self, parent): super().__init__(parent) self.setupUi(self) self._gns3_vm_settings = { "enable": True, "headless": False, "when_exit": "stop", "engine": "vmware", "vcpus": 1, "ram": 2048, "vmname": "GNS3 VM" } self.setWizardStyle(QtWidgets.QWizard.ModernStyle) if sys.platform.startswith("darwin"): # we want to see the cancel button on OSX self.setOptions(QtWidgets.QWizard.NoDefaultButton) self.uiLocalServerToolButton.clicked.connect(self._localServerBrowserSlot) self.uiGNS3VMDownloadLinkUrlLabel.setText("") self.uiRefreshPushButton.clicked.connect(self._refreshVMListSlot) self.uiVmwareRadioButton.clicked.connect(self._listVMwareVMsSlot) self.uiVirtualBoxRadioButton.clicked.connect(self._listVirtualBoxVMsSlot) self.uiVMwareBannerButton.clicked.connect(self._VMwareBannerButtonClickedSlot) settings = parent.settings() self.uiShowCheckBox.setChecked(settings["hide_setup_wizard"]) # by default all radio buttons are unchecked self.uiVmwareRadioButton.setAutoExclusive(False) self.uiVirtualBoxRadioButton.setAutoExclusive(False) self.uiVmwareRadioButton.setChecked(False) self.uiVirtualBoxRadioButton.setChecked(False) # Mandatory fields self.uiLocalServerWizardPage.registerField("path*", self.uiLocalServerPathLineEdit) # load all available addresses for address in QtNetwork.QNetworkInterface.allAddresses(): if address.protocol() in [QtNetwork.QAbstractSocket.IPv4Protocol, QtNetwork.QAbstractSocket.IPv6Protocol]: address_string = address.toString() if address_string.startswith("169.254") or address_string.startswith("fe80"): # ignore link-local addresses continue self.uiLocalServerHostComboBox.addItem(address_string, address_string) if sys.platform.startswith("darwin"): self.uiVMwareBannerButton.setIcon(QtGui.QIcon(":/images/vmware_fusion_banner.png")) else: self.uiVMwareBannerButton.setIcon(QtGui.QIcon(":/images/vmware_workstation_banner.png")) if sys.platform.startswith("linux"): self.uiLocalRadioButton.setChecked(True) self.uiLocalLabel.setText("Dependencies like Dynamips and Qemu must be manually installed") Controller.instance().connected_signal.connect(self._refreshLocalServerStatusSlot) Controller.instance().connection_failed_signal.connect(self._refreshLocalServerStatusSlot)
def reload_all_nodes(self): """Reload all nodes belonging to this project""" # Don't do anything if the project doesn't exist on the server if self._id is None: return Controller.instance().post("/projects/{project_id}/nodes/reload".format(project_id=self._id), None, body={}, timeout=None)
def load(self, path=None): if not path: path = self.path() if path: body = {"path": path} Controller.instance().post("/projects/load", self._projectOpenCallback, body=body, timeout=None) else: self.post("/open", self._projectOpenCallback, timeout=None)
def loadImagesList(self, endpoint): """ Fill the list box with available Images" :param endpoint: server endpoint with the list of Images """ Controller.instance().getCompute(endpoint, self._compute_id, self._getImagesFromServerCallback)
def create(self): """ Create the project on the remote server. """ body = {"name": self._name, "path": self.filesDir()} Controller.instance().post("/projects", self._projectCreatedCallback, body=body)
def duplicate(self, name=None, path=None, callback=None): """ Duplicate a project """ Controller.instance().post("/projects/{project_id}/duplicate".format(project_id=self._id), qpartial(self._duplicateCallback, callback), body={"name": name, "path": path}, progressText="Duplicating project '{}'...".format(name), timeout=None)
def getQemuImgBinariesFromServer(self, compute_id, callback): """ Gets the QEMU-img binaries list from a server. :param server: server to send the request to :param callback: callback for the reply from the server """ Controller.instance().getCompute("/qemu/img-binaries", compute_id, callback)
def _refreshVMListSlot(self): """ Refresh the list of VM available in VMware or VirtualBox. """ if self.uiVmwareRadioButton.isChecked(): Controller.instance().get("/gns3vm/engines/vmware/vms", self._getVMsFromServerCallback, progressText="Retrieving VMware VM list from server...") elif self.uiVirtualBoxRadioButton.isChecked(): Controller.instance().get("/gns3vm/engines/virtualbox/vms", self._getVMsFromServerCallback, progressText="Retrieving VirtualBox VM list from server...")
def _loadSettings(self): """ Loads the settings from the persistent settings file. """ self._settings = LocalConfig.instance().loadSectionSettings(self.__class__.__name__, QEMU_SETTINGS) # migrate VM settings to the controller (templates are managed on server side starting with version 2.0) Controller.instance().connected_signal.connect(self._migrateOldVMs)
def create(self): """ Create the project on the remote server. """ body = { "name": self._name, "path": self.filesDir() } Controller.instance().post("/projects", self._projectCreatedCallback, body=body)
def __init__(self, parent=None): super().__init__() self.setupUi(self) self._engines = [] self._old_settings = None self._initialized = False self.uiRefreshPushButton.clicked.connect(self._refreshVMSlot) self.uiGNS3VMEngineComboBox.currentIndexChanged.connect(self._engineChangedSlot) Controller.instance().connected_signal.connect(self.loadPreferences)
def getQemuCapabilitiesFromServer(self, compute_id, callback): """ Gets the capabilities of Qemu at a server. :param server: server to send the request to :param callback: callback for the reply from the server """ Controller.instance().getCompute("/qemu/capabilities", compute_id, callback)
def updateDiskImage(self, compute_id, callback, options): """ Update a disk image on the remote server :param server: server to send the request to :param callback: callback for the reply from the server :param options: Options for the image update """ Controller.instance().putCompute("/qemu/img", compute_id, callback, body=options)
def getDockerImagesFromServer(self, compute_id, callback): """ Gets the Docker images list from a server. :param server: server to send the request to :param callback: callback for the reply from the server """ Controller.instance().getCompute("/docker/images", compute_id, callback)
def destroy(self): """ Delete the project from all servers """ self.project_about_to_close_signal.emit() Controller.instance().delete( "/projects/{project_id}".format(project_id=self._id), self._projectClosedCallback, body={}, progressText="Delete the project")
def initializePage(self, page_id): super().initializePage(page_id) if self.page(page_id) == self.uiVirtualBoxWizardPage: self.uiVMListComboBox.clear() Controller.instance().getCompute( "/virtualbox/vms", self._compute_id, self._getVirtualBoxVMsFromServerCallback, progressText="Listing VirtualBox VMs...")
def __init__(self): super().__init__() self.setupUi(self) self._old_settings = None # connect signals self.uiIOURCPathToolButton.clicked.connect(self._iourcPathBrowserSlot) self.uiRestoreDefaultsPushButton.clicked.connect(self._restoreDefaultsSlot) Controller.instance().connected_signal.connect(self.loadPreferences)
def __init__(self, parent=None): super().__init__() self.setupUi(self) self._engines = [] self._old_settings = None self._initialized = False self.uiRefreshPushButton.clicked.connect(self._refreshVMSlot) self.uiGNS3VMEngineComboBox.currentIndexChanged.connect( self._engineChangedSlot) Controller.instance().connected_signal.connect(self.loadPreferences)
def _refreshLocalServerStatusSlot(self): """ Refresh the local server status page """ if Controller.instance().connected(): self.uiLocalServerStatusLabel.setText("Connection to local server successful") Controller.instance().get("/gns3vm", self._getSettingsCallback) elif Controller.instance().connecting(): self.uiLocalServerStatusLabel.setText("Please wait connection to the GNS3 server") else: local_server_settings = LocalServer.instance().localServerSettings() self.uiLocalServerStatusLabel.setText("Connection to local server failed.\n* Make sure GNS3 is allowed in your firewall.\n* Go back and try to change the server port\n* Please check with a browser if you can connect to {protocol}://{host}:{port}.\n* Try to run {path} in a terminal to see if you have an error if the above does not work.".format(protocol=local_server_settings["protocol"], host=local_server_settings["host"], port=local_server_settings["port"], path=local_server_settings["path"]))
def _loadSettings(self): """ Loads the settings from the server settings file. """ self._settings = LocalConfig.instance().loadSectionSettings(self.__class__.__name__, VBOX_SETTINGS) if not os.path.exists(self._settings["vboxmanage_path"]): self._settings["vboxmanage_path"] = self._findVBoxManage(self) # migrate VM settings to the controller (templates are managed on server side starting with version 2.0) Controller.instance().connected_signal.connect(self._migrateOldVMs)
def getQemuBinariesFromServer(self, compute_id, callback, archs=None): """ Gets the QEMU binaries list from a server. :param compute_id: server to send the request to :param callback: callback for the reply from the server :param archs: A list of architectures. Only binaries matching the specified architectures are returned. """ request_body = None if archs is not None: request_body = {"archs": archs} Controller.instance().getCompute("/qemu/binaries", compute_id, callback, body=request_body)
def _loadSettings(self): """ Loads the settings from the server settings file. """ local_config = LocalConfig.instance() self._settings = local_config.loadSectionSettings(self.__class__.__name__, VMWARE_SETTINGS) if not os.path.exists(self._settings["vmrun_path"]): self._settings["vmrun_path"] = self.findVmrun() self._settings["host_type"] = self._determineHostType() # migrate VM settings to the controller (templates are managed on server side starting with version 2.0) Controller.instance().connected_signal.connect(self._migrateOldVMs)
def close(self, local_server_shutdown=False): """Close project""" if self._closed or self._closing: return self._closing = True if self._id: self.project_about_to_close_signal.emit() Controller.instance().post("/projects/{project_id}/close".format(project_id=self._id), self._projectClosedCallback, body={}, progressText="Close the project") else: # The project is not initialized when we close it self._closed = True self.project_about_to_close_signal.emit() self.project_closed_signal.emit()
def create(self): """ Create the project on the remote server. """ body = { "name": self._name, "path": self.filesDir(), "grid_size": self._grid_size, "drawing_grid_size": self._drawing_grid_size, "show_grid": self._show_grid_on_new_project, "snap_to_grid": self._snap_to_grid_on_new_project, "show_interface_labels": self._show_interface_labels_on_new_project } Controller.instance().post("/projects", self._projectCreatedCallback, body=body)