First draft of VPCS module

This commit is contained in:
Joe Bowen
2014-05-06 12:45:12 -06:00
parent 35d16838cb
commit 4a37b4e39b
16 changed files with 2956 additions and 1 deletions

2
.gitignore vendored
View File

@@ -45,3 +45,5 @@ nosetests.xml
*_log.txt
*.log
# Gedit Temp Files
*~

View File

@@ -17,5 +17,6 @@
from gns3.modules.dynamips import Dynamips
from gns3.modules.iou import IOU
from gns3.modules.vpcs import VPCS
MODULES = [Dynamips, IOU]
MODULES = [Dynamips, IOU, VPCS]

View File

@@ -0,0 +1,450 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
VPCS module implementation.
"""
import socket
import base64
import os
from gns3.qt import QtCore, QtGui
from gns3.servers import Servers
from ..module import Module
from ..module_error import ModuleError
from .vpcs_device import VPCSDevice
from .settings import VPCS_SETTINGS, VPCS_SETTING_TYPES
import logging
log = logging.getLogger(__name__)
class VPCS(Module):
"""
VPCS module.
"""
def __init__(self):
Module.__init__(self)
self._settings = {}
self._nodes = []
self._vpcs_images = {}
self._servers = []
self._working_dir = ""
# load the settings
self._loadSettings()
self._loadVPCSImages()
def _loadSettings(self):
"""
Loads the settings from the persistent settings file.
"""
# load the settings
settings = QtCore.QSettings()
settings.beginGroup(self.__class__.__name__)
for name, value in VPCS_SETTINGS.items():
self._settings[name] = settings.value(name, value, type=VPCS_SETTING_TYPES[name])
settings.endGroup()
def _saveSettings(self):
"""
Saves the settings to the persistent settings file.
"""
# save the settings
settings = QtCore.QSettings()
settings.beginGroup(self.__class__.__name__)
for name, value in self._settings.items():
settings.setValue(name, value)
settings.endGroup()
def _loadVPCSImages(self):
"""
Load the VPCS images from the persistent settings file.
"""
# load the settings
settings = QtCore.QSettings()
settings.beginGroup("VPCSImages")
# load the VPCS images
size = settings.beginReadArray("vpcs_image")
for index in range(0, size):
settings.setArrayIndex(index)
path = settings.value("path", "")
image = settings.value("image", "")
startup_config = settings.value("startup_config", "")
ram = settings.value("ram", 256, type=int)
nvram = settings.value("nvram", 128, type=int)
server = settings.value("server", "local")
key = "{server}:{image}".format(server=server, image=image)
self._vpcs_images[key] = {"path": path,
"image": image,
"startup_config": startup_config,
"ram": ram,
"nvram": nvram,
"server": server}
settings.endArray()
settings.endGroup()
def _saveVPCSImages(self):
"""
Saves the VPCS images to the persistent settings file.
"""
# save the settings
settings = QtCore.QSettings()
settings.beginGroup("VPCSImages")
settings.remove("")
# save the VPCS images
settings.beginWriteArray("vpcs_image", len(self._vpcs_images))
index = 0
for ios_image in self._vpcs_images.values():
settings.setArrayIndex(index)
for name, value in ios_image.items():
settings.setValue(name, value)
index += 1
settings.endArray()
settings.endGroup()
def setProjectFilesDir(self, path):
"""
Sets the project files directory path this module.
:param path: path to the local project files directory
"""
self._working_dir = path
log.info("local working directory for VPCS module: {}".format(self._working_dir))
# update the server with the new working directory / project name
for server in self._servers:
if server.connected():
self._sendSettings(server)
def addServer(self, server):
"""
Adds a server to be used by this module.
:param server: WebSocketClient instance
"""
log.info("adding server {}:{} to VPCS module".format(server.host, server.port))
self._servers.append(server)
self._sendSettings(server)
def removeServer(self, server):
"""
Removes a server from being used by this module.
:param server: WebSocketClient instance
"""
log.info("removing server {}:{} from VPCS module".format(server.host, server.port))
self._servers.remove(server)
def servers(self):
"""
Returns all the servers used by this module.
:returns: list of WebSocketClient instances
"""
return self._servers
def addNode(self, node):
"""
Adds a node to this module.
:param node: Node instance
"""
self._nodes.append(node)
def removeNode(self, node):
"""
Removes a node from this module.
:param node: Node instance
"""
if node in self._nodes:
self._nodes.remove(node)
def vpcsImages(self):
"""
Returns VPCS images settings.
:returns: VPCS images settings (dictionary)
"""
return self._vpcs_images
def setVPCSImages(self, new_vpcs_images):
"""
Sets IOS images settings.
:param new_vpcs_images: IOS images settings (dictionary)
"""
self._vpcs_images = new_vpcs_images.copy()
self._saveVPCSImages()
def settings(self):
"""
Returns the module settings
:returns: module settings (dictionary)
"""
return self._settings
def _base64vpcsrc(self, vpcsrc_path):
"""
Get the content of the VPCSRC file base64 encoded.
:param config_path: path to the vpcsrc file.
:returns: base64 encoded string
"""
try:
with open(vpcsrc_path, "r") as f:
log.info("opening vpcsrc file: {}".format(vpcsrc_path))
config = f.read()
encoded = ("").join(base64.encodestring(config.encode("utf-8")).decode("utf-8").split())
return encoded
except OSError as e:
log.warn("could not base64 encode {}: {}".format(vpcsrc_path, e))
return ""
def setSettings(self, settings):
"""
Sets the module settings
:param settings: module settings (dictionary)
"""
params = {}
for name, value in settings.items():
if name in self._settings and self._settings[name] != value:
params[name] = value
if params:
if "vpcsrc" in params:
# encode the vpcsrc file in base64
params["vpcsrc"] = self._base64vpcsrc(params["vpcsrc"])
for server in self._servers:
# send the local working directory only if this is a local server
if server.isLocal():
params.update({"working_dir": self._working_dir})
else:
if "vpcsyap" in params:
del params["vpcsyap"] # do not send vpcsyap path to remote servers
project_name = os.path.basename(self._working_dir)
if project_name.endswith("-files"):
project_name = project_name[:-6]
params.update({"project_name": project_name})
server.send_notification("vpcs.settings", params)
self._settings.update(settings)
self._saveSettings()
def _sendSettings(self, server):
"""
Sends the module settings to the server.
:param server: WebSocketClient instance
"""
log.info("sending VPCS settings to server {}:{}".format(server.host, server.port))
params = self._settings.copy()
# encode the vpcsrc file in base64
params["vpcsrc"] = self._base64vpcsrc(params["vpcsrc"])
# send the local working directory only if this is a local server
if server.isLocal():
params.update({"working_dir": self._working_dir})
else:
if "vpcsyap" in params:
del params["vpcsyap"] # do not send vpcsyap path to remote servers
project_name = os.path.basename(self._working_dir)
if project_name.endswith("-files"):
project_name = project_name[:-6]
params.update({"project_name": project_name})
server.send_notification("vpcs.settings", params)
def allocateServer(self, node_class):
"""
Allocates a server.
:param node_class: Node object
:returns: allocated server (WebSocketClient instance)
"""
# allocate a server for the node
servers = Servers.instance()
if self._settings["use_local_server"]:
# use the local server
server = servers.localServer()
else:
# pick up a remote server (round-robin method)
server = next(iter(servers))
if not server:
raise ModuleError("No remote server is configured")
return server
def createNode(self, node_class, server):
"""
Creates a new node.
:param node_class: Node object
:param server: WebSocketClient instance
"""
log.info("creating node {}".format(node_class))
if not self._settings["vpcsrc"] or not os.path.isfile(self._settings["vpcsrc"]):
raise ModuleError("The path to VPCSRC must be configured")
if not server.connected():
try:
log.info("reconnecting to server {}:{}".format(server.host, server.port))
server.reconnect()
except OSError as e:
raise ModuleError("Could not connect to server {}:{}: {}".format(server.host,
server.port,
e))
if server not in self._servers:
self.addServer(server)
# create an instance of the node class
return node_class(self, server)
def setupNode(self, node):
"""
Setups a node.
:param node: Node instance
"""
log.info("configuring node {}".format(node))
settings = {}
selected_images = []
for image, info in self._vpcs_images.items():
if info["server"] == node.server().host or (node.server().isLocal() and info["server"] == "local"):
selected_images.append(image)
if not selected_images:
raise ModuleError("No VPCS image found for this device")
elif len(selected_images) > 1:
from gns3.main_window import MainWindow
mainwindow = MainWindow.instance()
(selection, ok) = QtGui.QInputDialog.getItem(mainwindow, "VPCS image", "Please choose an image", selected_images, 0, False)
if ok:
vpcsimage = selection
else:
raise ModuleError("Please select an VPCS image")
else:
vpcsimage = selected_images[0]
startup_config = self._vpcs_images[vpcsimage]["startup_config"]
vpcs_path = self._vpcs_images[vpcsimage]["path"]
if startup_config:
settings = {"startup_config": startup_config}
node.setup(vpcs_path, initial_settings=settings)
def reset(self):
"""
Resets the servers.
"""
log.info("VPCS module reset")
for server in self._servers:
if server.connected():
server.send_notification("vpcs.reset")
self._servers.clear()
def notification(self, destination, params):
"""
To received notifications from the server.
:param destination: JSON-RPC method
:param params: JSON-RPC params
"""
if "id" in params:
for node in self._nodes:
if node.id() == params["id"]:
message = "node {}: {}".format(node.name(), params["message"])
self.notification_signal.emit(message, params["details"])
node.stop()
@staticmethod
def getNodeClass(name):
"""
Returns the object with the corresponding name.
:param name: object name
"""
if name in globals():
return globals()[name]
return None
@staticmethod
def nodes():
"""
Returns all the node classes supported by this module.
:returns: list of classes
"""
return [VPCSDevice]
@staticmethod
def preferencePages():
"""
:returns: QWidget object list
"""
from .pages.vpcs_preferences_page import VPCSPreferencesPage
from .pages.vpcs_device_preferences_page import VPCSDevicePreferencesPage
return [VPCSPreferencesPage, VPCSDevicePreferencesPage]
@staticmethod
def instance():
"""
Singleton to return only on instance of VPCS module.
:returns: instance of VPCS
"""
if not hasattr(VPCS, "_instance"):
VPCS._instance = VPCS()
return VPCS._instance

View File

View File

@@ -0,0 +1,153 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Configuration page for IOU devices.
"""
import os
from gns3.qt import QtGui
from .. import IOU
from gns3.node_configurator import ConfigurationError
from ..ui.iou_device_configuration_page_ui import Ui_iouDeviceConfigPageWidget
class iouDeviceConfigurationPage(QtGui.QWidget, Ui_iouDeviceConfigPageWidget):
"""
QWidget configuration page for IOU devices.
"""
def __init__(self):
QtGui.QWidget.__init__(self)
self.setupUi(self)
self.uiStartupConfigToolButton.clicked.connect(self._startupConfigBrowserSlot)
def _startupConfigBrowserSlot(self):
"""
Slot to open a file browser and select a startup-config file.
"""
#TODO: current directory for startup-config + filter?
path = QtGui.QFileDialog.getOpenFileName(self, "Select a startup configuration", ".")
if not path:
return
if not os.access(path, os.R_OK):
QtGui.QMessageBox.critical(self, "Startup configuration", "Cannot read {}".format(path))
return
self.uiStartupConfigLineEdit.clear()
self.uiStartupConfigLineEdit.setText(path)
def loadSettings(self, settings, node, group=False):
"""
Loads the IOU device settings.
:param settings: the settings (dictionary)
:param node: Node instance
:param group: indicates the settings apply to a group of routers
"""
if not group:
self.uiNameLineEdit.setText(settings["name"])
self.uiConsolePortSpinBox.setValue(settings["console"])
# load the startup-config
self.uiStartupConfigLineEdit.setText(settings["startup_config"])
# load the available IOU images
iou_images = IOU.instance().iouImages()
for iou_image in iou_images.values():
#TODO: remote server aware
self.uiIOUImageComboBox.addItem(iou_image["image"], iou_image["path"])
index = self.uiIOUImageComboBox.findText(os.path.basename(settings["path"]))
if index != -1:
self.uiIOUImageComboBox.setCurrentIndex(index)
else:
self.uiNameLabel.hide()
self.uiNameLineEdit.hide()
self.uiIOUImageLabel.hide()
self.uiIOUImageComboBox.hide()
self.uiConsolePortLabel.hide()
self.uiConsolePortSpinBox.hide()
self.uiStartupConfigLabel.hide()
self.uiStartupConfigLineEdit.hide()
self.uiStartupConfigToolButton.hide()
# load the memories and disks settings
self.uiRamSpinBox.setValue(settings["ram"])
self.uiNvramSpinBox.setValue(settings["nvram"])
# load the number of adapters
self.uiEthernetAdaptersSpinBox.setValue(settings["ethernet_adapters"])
self.uiSerialAdaptersSpinBox.setValue(settings["serial_adapters"])
def saveSettings(self, settings, node, group=False):
"""
Saves the IOU device settings.
:param settings: the settings (dictionary)
:param node: Node instance
:param group: indicates the settings apply to a group of routers
"""
# these settings cannot be shared by nodes and updated
# in the node configurator.
if not group:
settings["name"] = self.uiNameLineEdit.text()
settings["console"] = self.uiConsolePortSpinBox.value()
startup_config = self.uiStartupConfigLineEdit.text()
if startup_config != settings["startup_config"]:
if os.access(startup_config, os.R_OK):
settings["startup_config"] = startup_config
else:
QtGui.QMessageBox.critical(self, "Startup-config", "Cannot read the startup-config file")
# save the IOU image path
index = self.uiIOUImageComboBox.currentIndex()
ios_path = self.uiIOUImageComboBox.itemData(index)
settings["path"] = ios_path
else:
del settings["name"]
del settings["console"]
# save the memories and disks settings
settings["ram"] = self.uiRamSpinBox.value()
settings["nvram"] = self.uiNvramSpinBox.value()
ethernet_adapters = self.uiEthernetAdaptersSpinBox.value()
serial_adapters = self.uiSerialAdaptersSpinBox.value()
if ethernet_adapters + serial_adapters > 16:
QtGui.QMessageBox.warning(self, node.name(), "The total number of adapters cannot exceed 16")
raise ConfigurationError()
node_ports = node.ports()
for node_port in node_ports:
if not node_port.isFree():
QtGui.QMessageBox.critical(self, node.name(), "Changing the number of adapters while links are connected isn't supported yet! Please delete all the links first.")
# if (node_port.linkType() == "Ethernet" and node_port.slotNumber() > ethernet_adapters) or \
# (node_port.linkType() == "Serial" and node_port.slotNumber() > serial_adapters) and not node_port.isFree():
# QtGui.QMessageBox.critical(self, node.name(), "A link is connected to port {} on adapter in slot {}, please remove it first".format(node_port.name(),
# node_port.slotNumber()))
raise ConfigurationError()
settings["ethernet_adapters"] = ethernet_adapters
settings["serial_adapters"] = serial_adapters

View File

@@ -0,0 +1,220 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Configuration page for IOU image & device preferences.
"""
import os
import sys
from gns3.qt import QtGui
from gns3.servers import Servers
from .. import IOU
from ..ui.iou_device_preferences_page_ui import Ui_IOUDevicePreferencesPageWidget
class IOUDevicePreferencesPage(QtGui.QWidget, Ui_IOUDevicePreferencesPageWidget):
"""
QWidget preference page for IOU image & device preferences.
"""
def __init__(self):
QtGui.QWidget.__init__(self)
self.setupUi(self)
self._iou_images = {}
self.uiSaveIOUImagePushButton.clicked.connect(self._iouImageSaveSlot)
self.uiDeleteIOUImagePushButton.clicked.connect(self._iouImageDeleteSlot)
self.uiIOUImagesTreeWidget.itemClicked.connect(self._iouImageClickedSlot)
self.uiIOUImagesTreeWidget.itemSelectionChanged.connect(self._iouImageChangedSlot)
self.uiIOUPathToolButton.clicked.connect(self._iouImageBrowserSlot)
self.uiStartupConfigToolButton.clicked.connect(self._startupConfigBrowserSlot)
self.uiIOUImageTestSettingsPushButton.clicked.connect(self._testSettingsSlot)
def _iouImageClickedSlot(self, item, column):
"""
Loads a selected IOU image from the tree widget.
:param item: selected QTreeWidgetItem instance
:param column: ignored
"""
image = item.text(0)
server = item.text(1)
key = "{server}:{image}".format(server=server, image=image)
iou_image = self._iou_images[key]
self.uiIOUPathLineEdit.setText(iou_image["path"])
self.uiStartupConfigLineEdit.setText(iou_image["startup_config"])
self.uiRAMSpinBox.setValue(iou_image["ram"])
self.uiNVRAMSpinBox.setValue(iou_image["nvram"])
def _iouImageChangedSlot(self):
"""
Enables the use of the delete button.
"""
item = self.uiIOUImagesTreeWidget.currentItem()
if item:
self.uiDeleteIOUImagePushButton.setEnabled(True)
else:
self.uiDeleteIOUImagePushButton.setEnabled(False)
def _iouImageSaveSlot(self):
"""
Adds/Saves an IOU image.
"""
path = self.uiIOUPathLineEdit.text()
startup_config = self.uiStartupConfigLineEdit.text()
nvram = self.uiNVRAMSpinBox.value()
ram = self.uiRAMSpinBox.value()
# basename doesn't work on Unix with Windows paths
if not sys.platform.startswith('win') and len(path) > 2 and path[1] == ":":
import ntpath
image = ntpath.basename(path)
else:
image = os.path.basename(path)
#TODO: mutiple remote server
if IOU.instance().settings()["use_local_server"]:
server = "local"
else:
server = next(iter(Servers.instance()))
if not server:
QtGui.QMessageBox.critical(self, "IOU image", "No remote server available!")
return
server = server.host
key = "{server}:{image}".format(server=server, image=image)
item = self.uiIOUImagesTreeWidget.currentItem()
if key in self._iou_images and item and item.text(0) == image:
item.setText(0, image)
item.setText(1, server)
elif key in self._iou_images:
return
else:
# add a new entry in the tree widget
item = QtGui.QTreeWidgetItem(self.uiIOUImagesTreeWidget)
item.setText(0, image)
item.setText(1, server)
self.uiIOUImagesTreeWidget.setCurrentItem(item)
self._iou_images[key] = {"path": path,
"image": image,
"startup_config": startup_config,
"ram": ram,
"nvram": nvram,
"server": server}
self.uiIOUImagesTreeWidget.resizeColumnToContents(0)
self.uiIOUImagesTreeWidget.resizeColumnToContents(1)
def _iouImageDeleteSlot(self):
"""
Deletes an IOU image.
"""
item = self.uiIOUImagesTreeWidget.currentItem()
if item:
image = item.text(0)
server = item.text(1)
key = "{server}:{image}".format(server=server, image=image)
del self._iou_images[key]
self.uiIOUImagesTreeWidget.takeTopLevelItem(self.uiIOUImagesTreeWidget.indexOfTopLevelItem(item))
def _iouImageBrowserSlot(self):
"""
Slot to open a file browser and select an IOU image.
"""
#TODO: current directory for IOU image + filter?
path = QtGui.QFileDialog.getOpenFileName(self, "Select an IOU image", ".", "IOU image (*.bin *.image)")
if not path:
return
if not os.access(path, os.R_OK):
QtGui.QMessageBox.critical(self, "IOU image", "Cannot read {}".format(path))
return
try:
with open(path, "rb") as f:
# read the first 7 bytes of the file.
elf_header_start = f.read(7)
except OSError as e:
QtGui.QMessageBox.critical(self, "IOU image", "Cannot read ELF magic number: {}".format(e))
return
# file must start with the ELF magic number, be 32-bit, little endian and have an ELF version of 1
# normal IOS image are big endian!
if elf_header_start != b'\x7fELF\x01\x01\x01':
QtGui.QMessageBox.critical(self, "IOU image", "Sorry, this is not a valid IOU image!")
return
self.uiIOUPathLineEdit.clear()
self.uiIOUPathLineEdit.setText(path)
self.uiRAMSpinBox.setValue(256)
self.uiNVRAMSpinBox.setValue(128)
def _startupConfigBrowserSlot(self):
"""
Slot to open a file browser and select a startup-config file.
"""
#TODO: current directory for startup-config + filter?
path = QtGui.QFileDialog.getOpenFileName(self, "Select a startup configuration", ".")
if not path:
return
if not os.access(path, os.R_OK):
QtGui.QMessageBox.critical(self, "Startup configuration", "Cannot read {}".format(path))
return
self.uiStartupConfigLineEdit.clear()
self.uiStartupConfigLineEdit.setText(path)
def _testSettingsSlot(self):
QtGui.QMessageBox.critical(self, "Test settings", "Sorry, not yet implemented!")
def loadPreferences(self):
"""
Loads the IOU image & device preferences.
"""
self._iou_images.clear()
self.uiIOUImagesTreeWidget.clear()
iou_images = IOU.instance().iouImages()
for iou_image in iou_images.values():
item = QtGui.QTreeWidgetItem(self.uiIOUImagesTreeWidget)
item.setText(0, iou_image["image"])
item.setText(1, iou_image["server"])
self.uiIOUImagesTreeWidget.resizeColumnToContents(0)
self.uiIOUImagesTreeWidget.resizeColumnToContents(1)
self._iou_images.update(iou_images)
def savePreferences(self):
"""
Saves the IOU image & device preferences.
"""
IOU.instance().setIOUImages(self._iou_images)

View File

@@ -0,0 +1,204 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Configuration page for IOU preferences.
"""
import os
import sys
from gns3.qt import QtCore, QtGui
from gns3.servers import Servers
from .. import IOU
from ..ui.iou_preferences_page_ui import Ui_IOUPreferencesPageWidget
from ..settings import IOU_SETTINGS
class IOUPreferencesPage(QtGui.QWidget, Ui_IOUPreferencesPageWidget):
"""
QWidget preference page for IOU.
"""
def __init__(self):
QtGui.QWidget.__init__(self)
self.setupUi(self)
if not sys.platform.startswith("linux"):
self.uiIouyapPathLineEdit.setEnabled(False)
self.uiIouyapPathToolButton.setEnabled(False)
self.uiUseLocalServercheckBox.setEnabled(False)
# connect signals
self.uiIOURCPathToolButton.clicked.connect(self._iourcPathBrowserSlot)
self.uiIouyapPathToolButton.clicked.connect(self._iouyapPathBrowserSlot)
self.uiRestoreDefaultsPushButton.clicked.connect(self._restoreDefaultsSlot)
self.uiUseLocalServercheckBox.stateChanged.connect(self._useLocalServerSlot)
self.uiTestSettingsPushButton.clicked.connect(self._testSettingsSlot)
def _iourcPathBrowserSlot(self):
"""
Slot to open a file browser and select an iourc file
"""
path = QtGui.QFileDialog.getOpenFileName(self, "Select the IOURC file", ".")
if not path:
return
if not os.access(path, os.R_OK):
QtGui.QMessageBox.critical(self, "IOURC file", "{} cannot be read".format(os.path.basename(path)))
return
self.uiIOURCPathLineEdit.setText(os.path.normpath(path))
def _iouyapPathBrowserSlot(self):
"""
Slot to open a file browser and select iouyap.
"""
path = QtGui.QFileDialog.getOpenFileName(self, "Select iouyap", ".")
if not path:
return
if not os.access(path, os.X_OK):
QtGui.QMessageBox.critical(self, "iouyap", "{} is not an executable".format(os.path.basename(path)))
return
self.uiIouyapPathLineEdit.setText(os.path.normpath(path))
def _testSettingsSlot(self):
QtGui.QMessageBox.critical(self, "Test settings", "Sorry, not yet implemented!")
return
servers = Servers.instance()
if self.uiUseLocalServercheckBox.isChecked():
server = servers.localServer()
else:
QtGui.QMessageBox.critical(self, "Test settings", "Sorry, not yet implemented!")
try:
if not server.connected():
server.reconnect()
except OSError as e:
QtGui.QMessageBox.critical(self, "Local server", "Could not connect to the local server {host} on port {port}: {error}".format(host=server.host,
port=server.port,
error=e))
self._progress_dialog = QtGui.QProgressDialog("Testing settings...", "Cancel", 0, 0, parent=self)
self._progress_dialog.setWindowModality(QtCore.Qt.WindowModal)
self._progress_dialog.setWindowTitle("Settings")
self._progress_dialog.show()
iou_module = IOU.instance()
if server not in iou_module.servers():
server_added = True
iou_module.addServer(server)
self.savePreferences()
if server_added:
iou_module.removeServer(server)
server.send_message("iou.test_settings", None, self._testSettingsCallback)
def _testSettingsCallback(self, result, error=False):
if self._progress_dialog.wasCanceled():
print("Was canceled")
return
self._progress_dialog.accept()
if error:
pass
#log.error("error while allocating an UDP port for {}: {}".format(self.name(), result["message"]))
print("Report received")
print(result)
def _restoreDefaultsSlot(self):
"""
Slot to populate the page widgets with the default settings.
"""
self._populateWidgets(IOU_SETTINGS)
def _useLocalServerSlot(self, state):
"""
Slot to enable or not the QTreeWidget for remote servers.
"""
if state:
self.uiRemoteServersTreeWidget.setEnabled(False)
else:
self.uiRemoteServersTreeWidget.setEnabled(True)
def _populateWidgets(self, settings):
"""
Populates the widgets with the settings.
:param settings: IOU settings
"""
self.uiIOURCPathLineEdit.setText(settings["iourc"])
self.uiIouyapPathLineEdit.setText(settings["iouyap"])
self.uiUseLocalServercheckBox.setChecked(settings["use_local_server"])
self.uiConsoleStartPortSpinBox.setValue(settings["console_start_port_range"])
self.uiConsoleEndPortSpinBox.setValue(settings["console_end_port_range"])
self.uiUDPStartPortSpinBox.setValue(settings["udp_start_port_range"])
self.uiUDPEndPortSpinBox.setValue(settings["udp_end_port_range"])
def _updateRemoteServersSlot(self):
"""
Adds/Updates the available remote servers.
"""
servers = Servers.instance()
self.uiRemoteServersTreeWidget.clear()
for server in servers.remoteServers().values():
host = server.host
port = server.port
item = QtGui.QTreeWidgetItem(self.uiRemoteServersTreeWidget)
item.setText(0, host)
item.setText(1, str(port))
self.uiRemoteServersTreeWidget.resizeColumnToContents(0)
def loadPreferences(self):
"""
Loads IOU preferences.
"""
iou_settings = IOU.instance().settings()
self._populateWidgets(iou_settings)
servers = Servers.instance()
servers.updated_signal.connect(self._updateRemoteServersSlot)
self._updateRemoteServersSlot()
def savePreferences(self):
"""
Saves IOU preferences.
"""
new_settings = {}
new_settings["iourc"] = self.uiIOURCPathLineEdit.text()
new_settings["iouyap"] = self.uiIouyapPathLineEdit.text()
new_settings["use_local_server"] = self.uiUseLocalServercheckBox.isChecked()
new_settings["console_start_port_range"] = self.uiConsoleStartPortSpinBox.value()
new_settings["console_end_port_range"] = self.uiConsoleEndPortSpinBox.value()
new_settings["udp_start_port_range"] = self.uiUDPStartPortSpinBox.value()
new_settings["udp_end_port_range"] = self.uiUDPEndPortSpinBox.value()
IOU.instance().setSettings(new_settings)

View File

@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
"""
Default IOU settings.
"""
IOU_SETTINGS = {
"iourc": "",
"iouyap": "",
"console_start_port_range": 4001,
"console_end_port_range": 4512,
"udp_start_port_range": 30001,
"udp_end_port_range": 40000,
"use_local_server": True,
}
# IOU is only available on Linux
if not sys.platform.startswith("linux"):
IOU_SETTINGS["use_local_server"] = False
IOU_SETTING_TYPES = {
"iourc": str,
"iouyap": str,
"console_start_port_range": int,
"console_end_port_range": int,
"udp_start_port_range": int,
"udp_end_port_range": int,
"use_local_server": bool,
}

View File

View File

@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>iouDeviceConfigPageWidget</class>
<widget class="QWidget" name="iouDeviceConfigPageWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>403</width>
<height>461</height>
</rect>
</property>
<property name="windowTitle">
<string>IOU device configuration</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="uiNameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="uiNameLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="uiIOUImageLabel">
<property name="text">
<string>IOU image:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="uiIOUImageComboBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="uiStartupConfigLabel">
<property name="text">
<string>Startup-config:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLineEdit" name="uiStartupConfigLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="uiStartupConfigToolButton">
<property name="text">
<string>...</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextOnly</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="uiConsolePortLabel">
<property name="text">
<string>Console port:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="uiConsolePortSpinBox">
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="uiRamLabel">
<property name="text">
<string>RAM size:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="uiRamSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> MiB</string>
</property>
<property name="maximum">
<number>4096</number>
</property>
<property name="singleStep">
<number>4</number>
</property>
<property name="value">
<number>128</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="uiNvramLabel">
<property name="text">
<string>NVRAM size:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="uiNvramSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> KiB</string>
</property>
<property name="maximum">
<number>4096</number>
</property>
<property name="singleStep">
<number>4</number>
</property>
<property name="value">
<number>128</number>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="uiEthernetAdaptersLabel">
<property name="text">
<string>Ethernet adapters:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="uiEthernetAdaptersSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>16</number>
</property>
<property name="singleStep">
<number>2</number>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="uiSerialAdaptersLabel">
<property name="text">
<string>Serial adapters:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSpinBox" name="uiSerialAdaptersSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>16</number>
</property>
<property name="singleStep">
<number>2</number>
</property>
</widget>
</item>
<item row="8" column="1">
<spacer name="spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>263</width>
<height>212</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,137 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/modules/iou/ui/iou_device_configuration_page.ui'
#
# Created: Fri Mar 21 10:37:58 2014
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_iouDeviceConfigPageWidget(object):
def setupUi(self, iouDeviceConfigPageWidget):
iouDeviceConfigPageWidget.setObjectName(_fromUtf8("iouDeviceConfigPageWidget"))
iouDeviceConfigPageWidget.resize(403, 461)
self.gridLayout = QtGui.QGridLayout(iouDeviceConfigPageWidget)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.uiNameLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiNameLabel.setObjectName(_fromUtf8("uiNameLabel"))
self.gridLayout.addWidget(self.uiNameLabel, 0, 0, 1, 1)
self.uiNameLineEdit = QtGui.QLineEdit(iouDeviceConfigPageWidget)
self.uiNameLineEdit.setObjectName(_fromUtf8("uiNameLineEdit"))
self.gridLayout.addWidget(self.uiNameLineEdit, 0, 1, 1, 1)
self.uiIOUImageLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiIOUImageLabel.setObjectName(_fromUtf8("uiIOUImageLabel"))
self.gridLayout.addWidget(self.uiIOUImageLabel, 1, 0, 1, 1)
self.uiIOUImageComboBox = QtGui.QComboBox(iouDeviceConfigPageWidget)
self.uiIOUImageComboBox.setObjectName(_fromUtf8("uiIOUImageComboBox"))
self.gridLayout.addWidget(self.uiIOUImageComboBox, 1, 1, 1, 1)
self.uiStartupConfigLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiStartupConfigLabel.setObjectName(_fromUtf8("uiStartupConfigLabel"))
self.gridLayout.addWidget(self.uiStartupConfigLabel, 2, 0, 1, 1)
self.horizontalLayout_4 = QtGui.QHBoxLayout()
self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4"))
self.uiStartupConfigLineEdit = QtGui.QLineEdit(iouDeviceConfigPageWidget)
self.uiStartupConfigLineEdit.setObjectName(_fromUtf8("uiStartupConfigLineEdit"))
self.horizontalLayout_4.addWidget(self.uiStartupConfigLineEdit)
self.uiStartupConfigToolButton = QtGui.QToolButton(iouDeviceConfigPageWidget)
self.uiStartupConfigToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.uiStartupConfigToolButton.setObjectName(_fromUtf8("uiStartupConfigToolButton"))
self.horizontalLayout_4.addWidget(self.uiStartupConfigToolButton)
self.gridLayout.addLayout(self.horizontalLayout_4, 2, 1, 1, 1)
self.uiConsolePortLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiConsolePortLabel.setObjectName(_fromUtf8("uiConsolePortLabel"))
self.gridLayout.addWidget(self.uiConsolePortLabel, 3, 0, 1, 1)
self.uiConsolePortSpinBox = QtGui.QSpinBox(iouDeviceConfigPageWidget)
self.uiConsolePortSpinBox.setMaximum(65535)
self.uiConsolePortSpinBox.setObjectName(_fromUtf8("uiConsolePortSpinBox"))
self.gridLayout.addWidget(self.uiConsolePortSpinBox, 3, 1, 1, 1)
self.uiRamLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiRamLabel.setObjectName(_fromUtf8("uiRamLabel"))
self.gridLayout.addWidget(self.uiRamLabel, 4, 0, 1, 1)
self.uiRamSpinBox = QtGui.QSpinBox(iouDeviceConfigPageWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.uiRamSpinBox.sizePolicy().hasHeightForWidth())
self.uiRamSpinBox.setSizePolicy(sizePolicy)
self.uiRamSpinBox.setMaximum(4096)
self.uiRamSpinBox.setSingleStep(4)
self.uiRamSpinBox.setProperty("value", 128)
self.uiRamSpinBox.setObjectName(_fromUtf8("uiRamSpinBox"))
self.gridLayout.addWidget(self.uiRamSpinBox, 4, 1, 1, 1)
self.uiNvramLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiNvramLabel.setObjectName(_fromUtf8("uiNvramLabel"))
self.gridLayout.addWidget(self.uiNvramLabel, 5, 0, 1, 1)
self.uiNvramSpinBox = QtGui.QSpinBox(iouDeviceConfigPageWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.uiNvramSpinBox.sizePolicy().hasHeightForWidth())
self.uiNvramSpinBox.setSizePolicy(sizePolicy)
self.uiNvramSpinBox.setMaximum(4096)
self.uiNvramSpinBox.setSingleStep(4)
self.uiNvramSpinBox.setProperty("value", 128)
self.uiNvramSpinBox.setObjectName(_fromUtf8("uiNvramSpinBox"))
self.gridLayout.addWidget(self.uiNvramSpinBox, 5, 1, 1, 1)
self.uiEthernetAdaptersLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiEthernetAdaptersLabel.setObjectName(_fromUtf8("uiEthernetAdaptersLabel"))
self.gridLayout.addWidget(self.uiEthernetAdaptersLabel, 6, 0, 1, 1)
self.uiEthernetAdaptersSpinBox = QtGui.QSpinBox(iouDeviceConfigPageWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.uiEthernetAdaptersSpinBox.sizePolicy().hasHeightForWidth())
self.uiEthernetAdaptersSpinBox.setSizePolicy(sizePolicy)
self.uiEthernetAdaptersSpinBox.setMaximum(16)
self.uiEthernetAdaptersSpinBox.setSingleStep(2)
self.uiEthernetAdaptersSpinBox.setObjectName(_fromUtf8("uiEthernetAdaptersSpinBox"))
self.gridLayout.addWidget(self.uiEthernetAdaptersSpinBox, 6, 1, 1, 1)
self.uiSerialAdaptersLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiSerialAdaptersLabel.setObjectName(_fromUtf8("uiSerialAdaptersLabel"))
self.gridLayout.addWidget(self.uiSerialAdaptersLabel, 7, 0, 1, 1)
self.uiSerialAdaptersSpinBox = QtGui.QSpinBox(iouDeviceConfigPageWidget)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.uiSerialAdaptersSpinBox.sizePolicy().hasHeightForWidth())
self.uiSerialAdaptersSpinBox.setSizePolicy(sizePolicy)
self.uiSerialAdaptersSpinBox.setMaximum(16)
self.uiSerialAdaptersSpinBox.setSingleStep(2)
self.uiSerialAdaptersSpinBox.setObjectName(_fromUtf8("uiSerialAdaptersSpinBox"))
self.gridLayout.addWidget(self.uiSerialAdaptersSpinBox, 7, 1, 1, 1)
spacerItem = QtGui.QSpacerItem(263, 212, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem, 8, 1, 1, 1)
self.retranslateUi(iouDeviceConfigPageWidget)
QtCore.QMetaObject.connectSlotsByName(iouDeviceConfigPageWidget)
def retranslateUi(self, iouDeviceConfigPageWidget):
iouDeviceConfigPageWidget.setWindowTitle(_translate("iouDeviceConfigPageWidget", "IOU device configuration", None))
self.uiNameLabel.setText(_translate("iouDeviceConfigPageWidget", "Name:", None))
self.uiIOUImageLabel.setText(_translate("iouDeviceConfigPageWidget", "IOU image:", None))
self.uiStartupConfigLabel.setText(_translate("iouDeviceConfigPageWidget", "Startup-config:", None))
self.uiStartupConfigToolButton.setText(_translate("iouDeviceConfigPageWidget", "...", None))
self.uiConsolePortLabel.setText(_translate("iouDeviceConfigPageWidget", "Console port:", None))
self.uiRamLabel.setText(_translate("iouDeviceConfigPageWidget", "RAM size:", None))
self.uiRamSpinBox.setSuffix(_translate("iouDeviceConfigPageWidget", " MiB", None))
self.uiNvramLabel.setText(_translate("iouDeviceConfigPageWidget", "NVRAM size:", None))
self.uiNvramSpinBox.setSuffix(_translate("iouDeviceConfigPageWidget", " KiB", None))
self.uiEthernetAdaptersLabel.setText(_translate("iouDeviceConfigPageWidget", "Ethernet adapters:", None))
self.uiSerialAdaptersLabel.setText(_translate("iouDeviceConfigPageWidget", "Serial adapters:", None))

View File

@@ -0,0 +1,275 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>IOUDevicePreferencesPageWidget</class>
<widget class="QWidget" name="IOUDevicePreferencesPageWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>404</width>
<height>487</height>
</rect>
</property>
<property name="windowTitle">
<string>IOU devices</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QTabWidget" name="uiTabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="uiIOUDeviceTabWidget">
<attribute name="title">
<string>IOU images</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QPushButton" name="uiIOUImageTestSettingsPushButton">
<property name="text">
<string>Test settings</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="uiSaveIOUImagePushButton">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="uiDeleteIOUImagePushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>76</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="uiIOUPathLabel">
<property name="text">
<string>IOU path:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="uiIOUPathLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="uiIOUPathToolButton">
<property name="text">
<string>...</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextOnly</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="uiStartupConfigLabel">
<property name="text">
<string>Startup-config:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLineEdit" name="uiStartupConfigLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="uiStartupConfigToolButton">
<property name="text">
<string>...</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextOnly</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="uiNVRAMLabel">
<property name="text">
<string>NVRAM:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="uiNVRAMSpinBox">
<property name="suffix">
<string> KB</string>
</property>
<property name="minimum">
<number>16</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>128</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="uiRAMLabel">
<property name="text">
<string>RAM:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="uiRAMSpinBox">
<property name="suffix">
<string> MB</string>
</property>
<property name="minimum">
<number>16</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>256</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QTreeWidget" name="uiIOUImagesTreeWidget">
<column>
<property name="text">
<string>File</string>
</property>
</column>
<column>
<property name="text">
<string>Server</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="uiIOSRoutersTabWidget">
<property name="enabled">
<bool>false</bool>
</property>
<attribute name="title">
<string>IOU devices</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" rowspan="2">
<widget class="QTreeWidget" name="treeWidget_2">
<column>
<property name="text">
<string>IOU device</string>
</property>
</column>
<column>
<property name="text">
<string>IOU file</string>
</property>
</column>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>New</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_4">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_5">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>354</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
<designerdata>
<property name="gridDeltaX">
<number>10</number>
</property>
<property name="gridDeltaY">
<number>10</number>
</property>
<property name="gridSnapX">
<bool>true</bool>
</property>
<property name="gridSnapY">
<bool>true</bool>
</property>
<property name="gridVisible">
<bool>true</bool>
</property>
</designerdata>
</ui>

View File

@@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/modules/iou/ui/iou_device_preferences_page.ui'
#
# Created: Sat Apr 12 14:54:36 2014
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_IOUDevicePreferencesPageWidget(object):
def setupUi(self, IOUDevicePreferencesPageWidget):
IOUDevicePreferencesPageWidget.setObjectName(_fromUtf8("IOUDevicePreferencesPageWidget"))
IOUDevicePreferencesPageWidget.resize(404, 487)
self.vboxlayout = QtGui.QVBoxLayout(IOUDevicePreferencesPageWidget)
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
self.uiTabWidget = QtGui.QTabWidget(IOUDevicePreferencesPageWidget)
self.uiTabWidget.setEnabled(True)
self.uiTabWidget.setObjectName(_fromUtf8("uiTabWidget"))
self.uiIOUDeviceTabWidget = QtGui.QWidget()
self.uiIOUDeviceTabWidget.setObjectName(_fromUtf8("uiIOUDeviceTabWidget"))
self.gridLayout_3 = QtGui.QGridLayout(self.uiIOUDeviceTabWidget)
self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
self.horizontalLayout_5 = QtGui.QHBoxLayout()
self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5"))
self.uiIOUImageTestSettingsPushButton = QtGui.QPushButton(self.uiIOUDeviceTabWidget)
self.uiIOUImageTestSettingsPushButton.setObjectName(_fromUtf8("uiIOUImageTestSettingsPushButton"))
self.horizontalLayout_5.addWidget(self.uiIOUImageTestSettingsPushButton)
self.uiSaveIOUImagePushButton = QtGui.QPushButton(self.uiIOUDeviceTabWidget)
self.uiSaveIOUImagePushButton.setObjectName(_fromUtf8("uiSaveIOUImagePushButton"))
self.horizontalLayout_5.addWidget(self.uiSaveIOUImagePushButton)
self.uiDeleteIOUImagePushButton = QtGui.QPushButton(self.uiIOUDeviceTabWidget)
self.uiDeleteIOUImagePushButton.setEnabled(False)
self.uiDeleteIOUImagePushButton.setObjectName(_fromUtf8("uiDeleteIOUImagePushButton"))
self.horizontalLayout_5.addWidget(self.uiDeleteIOUImagePushButton)
self.gridLayout_3.addLayout(self.horizontalLayout_5, 2, 0, 1, 1)
spacerItem = QtGui.QSpacerItem(76, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem, 2, 1, 1, 1)
self.groupBox = QtGui.QGroupBox(self.uiIOUDeviceTabWidget)
self.groupBox.setObjectName(_fromUtf8("groupBox"))
self.gridLayout_2 = QtGui.QGridLayout(self.groupBox)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.uiIOUPathLabel = QtGui.QLabel(self.groupBox)
self.uiIOUPathLabel.setObjectName(_fromUtf8("uiIOUPathLabel"))
self.gridLayout_2.addWidget(self.uiIOUPathLabel, 0, 0, 1, 1)
self.horizontalLayout_3 = QtGui.QHBoxLayout()
self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
self.uiIOUPathLineEdit = QtGui.QLineEdit(self.groupBox)
self.uiIOUPathLineEdit.setObjectName(_fromUtf8("uiIOUPathLineEdit"))
self.horizontalLayout_3.addWidget(self.uiIOUPathLineEdit)
self.uiIOUPathToolButton = QtGui.QToolButton(self.groupBox)
self.uiIOUPathToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.uiIOUPathToolButton.setObjectName(_fromUtf8("uiIOUPathToolButton"))
self.horizontalLayout_3.addWidget(self.uiIOUPathToolButton)
self.gridLayout_2.addLayout(self.horizontalLayout_3, 0, 1, 1, 1)
self.uiStartupConfigLabel = QtGui.QLabel(self.groupBox)
self.uiStartupConfigLabel.setObjectName(_fromUtf8("uiStartupConfigLabel"))
self.gridLayout_2.addWidget(self.uiStartupConfigLabel, 1, 0, 1, 1)
self.horizontalLayout_4 = QtGui.QHBoxLayout()
self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4"))
self.uiStartupConfigLineEdit = QtGui.QLineEdit(self.groupBox)
self.uiStartupConfigLineEdit.setObjectName(_fromUtf8("uiStartupConfigLineEdit"))
self.horizontalLayout_4.addWidget(self.uiStartupConfigLineEdit)
self.uiStartupConfigToolButton = QtGui.QToolButton(self.groupBox)
self.uiStartupConfigToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.uiStartupConfigToolButton.setObjectName(_fromUtf8("uiStartupConfigToolButton"))
self.horizontalLayout_4.addWidget(self.uiStartupConfigToolButton)
self.gridLayout_2.addLayout(self.horizontalLayout_4, 1, 1, 1, 1)
self.uiNVRAMLabel = QtGui.QLabel(self.groupBox)
self.uiNVRAMLabel.setObjectName(_fromUtf8("uiNVRAMLabel"))
self.gridLayout_2.addWidget(self.uiNVRAMLabel, 2, 0, 1, 1)
self.uiNVRAMSpinBox = QtGui.QSpinBox(self.groupBox)
self.uiNVRAMSpinBox.setMinimum(16)
self.uiNVRAMSpinBox.setMaximum(65535)
self.uiNVRAMSpinBox.setProperty("value", 128)
self.uiNVRAMSpinBox.setObjectName(_fromUtf8("uiNVRAMSpinBox"))
self.gridLayout_2.addWidget(self.uiNVRAMSpinBox, 2, 1, 1, 1)
self.uiRAMLabel = QtGui.QLabel(self.groupBox)
self.uiRAMLabel.setObjectName(_fromUtf8("uiRAMLabel"))
self.gridLayout_2.addWidget(self.uiRAMLabel, 3, 0, 1, 1)
self.uiRAMSpinBox = QtGui.QSpinBox(self.groupBox)
self.uiRAMSpinBox.setMinimum(16)
self.uiRAMSpinBox.setMaximum(65535)
self.uiRAMSpinBox.setProperty("value", 256)
self.uiRAMSpinBox.setObjectName(_fromUtf8("uiRAMSpinBox"))
self.gridLayout_2.addWidget(self.uiRAMSpinBox, 3, 1, 1, 1)
self.gridLayout_3.addWidget(self.groupBox, 1, 0, 1, 2)
self.uiIOUImagesTreeWidget = QtGui.QTreeWidget(self.uiIOUDeviceTabWidget)
self.uiIOUImagesTreeWidget.setObjectName(_fromUtf8("uiIOUImagesTreeWidget"))
self.gridLayout_3.addWidget(self.uiIOUImagesTreeWidget, 0, 0, 1, 2)
self.uiTabWidget.addTab(self.uiIOUDeviceTabWidget, _fromUtf8(""))
self.uiIOSRoutersTabWidget = QtGui.QWidget()
self.uiIOSRoutersTabWidget.setEnabled(False)
self.uiIOSRoutersTabWidget.setObjectName(_fromUtf8("uiIOSRoutersTabWidget"))
self.gridLayout = QtGui.QGridLayout(self.uiIOSRoutersTabWidget)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.treeWidget_2 = QtGui.QTreeWidget(self.uiIOSRoutersTabWidget)
self.treeWidget_2.setObjectName(_fromUtf8("treeWidget_2"))
self.gridLayout.addWidget(self.treeWidget_2, 0, 0, 2, 1)
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.pushButton_3 = QtGui.QPushButton(self.uiIOSRoutersTabWidget)
self.pushButton_3.setObjectName(_fromUtf8("pushButton_3"))
self.verticalLayout.addWidget(self.pushButton_3)
self.pushButton_4 = QtGui.QPushButton(self.uiIOSRoutersTabWidget)
self.pushButton_4.setObjectName(_fromUtf8("pushButton_4"))
self.verticalLayout.addWidget(self.pushButton_4)
self.pushButton_5 = QtGui.QPushButton(self.uiIOSRoutersTabWidget)
self.pushButton_5.setObjectName(_fromUtf8("pushButton_5"))
self.verticalLayout.addWidget(self.pushButton_5)
self.gridLayout.addLayout(self.verticalLayout, 0, 1, 1, 1)
spacerItem1 = QtGui.QSpacerItem(20, 354, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem1, 1, 1, 1, 1)
self.uiTabWidget.addTab(self.uiIOSRoutersTabWidget, _fromUtf8(""))
self.vboxlayout.addWidget(self.uiTabWidget)
self.retranslateUi(IOUDevicePreferencesPageWidget)
self.uiTabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(IOUDevicePreferencesPageWidget)
def retranslateUi(self, IOUDevicePreferencesPageWidget):
IOUDevicePreferencesPageWidget.setWindowTitle(_translate("IOUDevicePreferencesPageWidget", "IOU devices", None))
self.uiIOUImageTestSettingsPushButton.setText(_translate("IOUDevicePreferencesPageWidget", "Test settings", None))
self.uiSaveIOUImagePushButton.setText(_translate("IOUDevicePreferencesPageWidget", "Save", None))
self.uiDeleteIOUImagePushButton.setText(_translate("IOUDevicePreferencesPageWidget", "Delete", None))
self.groupBox.setTitle(_translate("IOUDevicePreferencesPageWidget", "Settings", None))
self.uiIOUPathLabel.setText(_translate("IOUDevicePreferencesPageWidget", "IOU path:", None))
self.uiIOUPathToolButton.setText(_translate("IOUDevicePreferencesPageWidget", "...", None))
self.uiStartupConfigLabel.setText(_translate("IOUDevicePreferencesPageWidget", "Startup-config:", None))
self.uiStartupConfigToolButton.setText(_translate("IOUDevicePreferencesPageWidget", "...", None))
self.uiNVRAMLabel.setText(_translate("IOUDevicePreferencesPageWidget", "NVRAM:", None))
self.uiNVRAMSpinBox.setSuffix(_translate("IOUDevicePreferencesPageWidget", " KB", None))
self.uiRAMLabel.setText(_translate("IOUDevicePreferencesPageWidget", "RAM:", None))
self.uiRAMSpinBox.setSuffix(_translate("IOUDevicePreferencesPageWidget", " MB", None))
self.uiIOUImagesTreeWidget.headerItem().setText(0, _translate("IOUDevicePreferencesPageWidget", "File", None))
self.uiIOUImagesTreeWidget.headerItem().setText(1, _translate("IOUDevicePreferencesPageWidget", "Server", None))
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiIOUDeviceTabWidget), _translate("IOUDevicePreferencesPageWidget", "IOU images", None))
self.treeWidget_2.headerItem().setText(0, _translate("IOUDevicePreferencesPageWidget", "IOU device", None))
self.treeWidget_2.headerItem().setText(1, _translate("IOUDevicePreferencesPageWidget", "IOU file", None))
self.pushButton_3.setText(_translate("IOUDevicePreferencesPageWidget", "New", None))
self.pushButton_4.setText(_translate("IOUDevicePreferencesPageWidget", "Edit", None))
self.pushButton_5.setText(_translate("IOUDevicePreferencesPageWidget", "Delete", None))
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiIOSRoutersTabWidget), _translate("IOUDevicePreferencesPageWidget", "IOU devices", None))

View File

@@ -0,0 +1,317 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>IOUPreferencesPageWidget</class>
<widget class="QWidget" name="IOUPreferencesPageWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>432</width>
<height>508</height>
</rect>
</property>
<property name="windowTitle">
<string>IOS on UNIX</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QTabWidget" name="uiTabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="uiGeneralSettingsTabWidget">
<attribute name="title">
<string>General settings</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLineEdit" name="uiIOURCPathLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="uiIOURCPathToolButton">
<property name="text">
<string>...</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextOnly</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>164</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="uiTestSettingsPushButton">
<property name="text">
<string>Test settings</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="uiRestoreDefaultsPushButton">
<property name="text">
<string>Restore defaults</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="uiIouyapPathLabel">
<property name="text">
<string>Path to iouyap (local Linux server only):</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="uiIOURCPathLabel">
<property name="text">
<string>Path to IOURC (pushed to the server):</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<spacer name="spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>390</width>
<height>193</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLineEdit" name="uiIouyapPathLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="uiIouyapPathToolButton">
<property name="text">
<string>...</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextOnly</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="uiServerSettingsTabWidget">
<attribute name="title">
<string>Server settings</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QCheckBox" name="uiUseLocalServercheckBox">
<property name="text">
<string>Use the local server (Linux only)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="uiRemoteServersGroupBox">
<property name="title">
<string>Remote servers</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QTreeWidget" name="uiRemoteServersTreeWidget">
<property name="enabled">
<bool>false</bool>
</property>
<column>
<property name="text">
<string>Host</string>
</property>
</column>
<column>
<property name="text">
<string>Port</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Advanced settings</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="uiConsolePortRangeGroupBox">
<property name="title">
<string>Console port range</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="uiConsoleStartPortSpinBox">
<property name="suffix">
<string notr="true"> TCP</string>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>4001</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="uiConsolePortRangeLabel">
<property name="text">
<string>to</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="uiConsoleEndPortSpinBox">
<property name="suffix">
<string notr="true"> TCP</string>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>4500</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="uiUDPPortRangeGroupBox">
<property name="title">
<string>UDP tunneling port range</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QSpinBox" name="uiUDPStartPortSpinBox">
<property name="suffix">
<string notr="true"> UDP</string>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>30001</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="uiUDPPortRangeLabel">
<property name="text">
<string>to</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="uiUDPEndPortSpinBox">
<property name="suffix">
<string notr="true"> UDP</string>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>40000</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>147</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>304</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
<designerdata>
<property name="gridDeltaX">
<number>10</number>
</property>
<property name="gridDeltaY">
<number>10</number>
</property>
<property name="gridSnapX">
<bool>true</bool>
</property>
<property name="gridSnapY">
<bool>true</bool>
</property>
<property name="gridVisible">
<bool>true</bool>
</property>
</designerdata>
</ui>

View File

@@ -0,0 +1,172 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/modules/iou/ui/iou_preferences_page.ui'
#
# Created: Wed Apr 30 16:43:13 2014
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_IOUPreferencesPageWidget(object):
def setupUi(self, IOUPreferencesPageWidget):
IOUPreferencesPageWidget.setObjectName(_fromUtf8("IOUPreferencesPageWidget"))
IOUPreferencesPageWidget.resize(432, 508)
self.vboxlayout = QtGui.QVBoxLayout(IOUPreferencesPageWidget)
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
self.uiTabWidget = QtGui.QTabWidget(IOUPreferencesPageWidget)
self.uiTabWidget.setObjectName(_fromUtf8("uiTabWidget"))
self.uiGeneralSettingsTabWidget = QtGui.QWidget()
self.uiGeneralSettingsTabWidget.setObjectName(_fromUtf8("uiGeneralSettingsTabWidget"))
self.gridLayout = QtGui.QGridLayout(self.uiGeneralSettingsTabWidget)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.horizontalLayout_5 = QtGui.QHBoxLayout()
self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5"))
self.uiIOURCPathLineEdit = QtGui.QLineEdit(self.uiGeneralSettingsTabWidget)
self.uiIOURCPathLineEdit.setObjectName(_fromUtf8("uiIOURCPathLineEdit"))
self.horizontalLayout_5.addWidget(self.uiIOURCPathLineEdit)
self.uiIOURCPathToolButton = QtGui.QToolButton(self.uiGeneralSettingsTabWidget)
self.uiIOURCPathToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.uiIOURCPathToolButton.setObjectName(_fromUtf8("uiIOURCPathToolButton"))
self.horizontalLayout_5.addWidget(self.uiIOURCPathToolButton)
self.gridLayout.addLayout(self.horizontalLayout_5, 3, 0, 1, 2)
spacerItem = QtGui.QSpacerItem(164, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 6, 1, 1, 1)
self.horizontalLayout_2 = QtGui.QHBoxLayout()
self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
self.uiTestSettingsPushButton = QtGui.QPushButton(self.uiGeneralSettingsTabWidget)
self.uiTestSettingsPushButton.setObjectName(_fromUtf8("uiTestSettingsPushButton"))
self.horizontalLayout_2.addWidget(self.uiTestSettingsPushButton)
self.uiRestoreDefaultsPushButton = QtGui.QPushButton(self.uiGeneralSettingsTabWidget)
self.uiRestoreDefaultsPushButton.setObjectName(_fromUtf8("uiRestoreDefaultsPushButton"))
self.horizontalLayout_2.addWidget(self.uiRestoreDefaultsPushButton)
self.gridLayout.addLayout(self.horizontalLayout_2, 6, 0, 1, 1)
self.uiIouyapPathLabel = QtGui.QLabel(self.uiGeneralSettingsTabWidget)
self.uiIouyapPathLabel.setObjectName(_fromUtf8("uiIouyapPathLabel"))
self.gridLayout.addWidget(self.uiIouyapPathLabel, 4, 0, 1, 1)
self.uiIOURCPathLabel = QtGui.QLabel(self.uiGeneralSettingsTabWidget)
self.uiIOURCPathLabel.setObjectName(_fromUtf8("uiIOURCPathLabel"))
self.gridLayout.addWidget(self.uiIOURCPathLabel, 2, 0, 1, 1)
spacerItem1 = QtGui.QSpacerItem(390, 193, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem1, 7, 0, 1, 2)
self.horizontalLayout_6 = QtGui.QHBoxLayout()
self.horizontalLayout_6.setObjectName(_fromUtf8("horizontalLayout_6"))
self.uiIouyapPathLineEdit = QtGui.QLineEdit(self.uiGeneralSettingsTabWidget)
self.uiIouyapPathLineEdit.setObjectName(_fromUtf8("uiIouyapPathLineEdit"))
self.horizontalLayout_6.addWidget(self.uiIouyapPathLineEdit)
self.uiIouyapPathToolButton = QtGui.QToolButton(self.uiGeneralSettingsTabWidget)
self.uiIouyapPathToolButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.uiIouyapPathToolButton.setObjectName(_fromUtf8("uiIouyapPathToolButton"))
self.horizontalLayout_6.addWidget(self.uiIouyapPathToolButton)
self.gridLayout.addLayout(self.horizontalLayout_6, 5, 0, 1, 2)
self.uiTabWidget.addTab(self.uiGeneralSettingsTabWidget, _fromUtf8(""))
self.uiServerSettingsTabWidget = QtGui.QWidget()
self.uiServerSettingsTabWidget.setObjectName(_fromUtf8("uiServerSettingsTabWidget"))
self.gridLayout_2 = QtGui.QGridLayout(self.uiServerSettingsTabWidget)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.uiUseLocalServercheckBox = QtGui.QCheckBox(self.uiServerSettingsTabWidget)
self.uiUseLocalServercheckBox.setChecked(True)
self.uiUseLocalServercheckBox.setObjectName(_fromUtf8("uiUseLocalServercheckBox"))
self.gridLayout_2.addWidget(self.uiUseLocalServercheckBox, 0, 0, 1, 1)
self.uiRemoteServersGroupBox = QtGui.QGroupBox(self.uiServerSettingsTabWidget)
self.uiRemoteServersGroupBox.setObjectName(_fromUtf8("uiRemoteServersGroupBox"))
self.horizontalLayout_3 = QtGui.QHBoxLayout(self.uiRemoteServersGroupBox)
self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
self.uiRemoteServersTreeWidget = QtGui.QTreeWidget(self.uiRemoteServersGroupBox)
self.uiRemoteServersTreeWidget.setEnabled(False)
self.uiRemoteServersTreeWidget.setObjectName(_fromUtf8("uiRemoteServersTreeWidget"))
self.horizontalLayout_3.addWidget(self.uiRemoteServersTreeWidget)
self.gridLayout_2.addWidget(self.uiRemoteServersGroupBox, 1, 0, 1, 1)
self.uiTabWidget.addTab(self.uiServerSettingsTabWidget, _fromUtf8(""))
self.tab = QtGui.QWidget()
self.tab.setObjectName(_fromUtf8("tab"))
self.verticalLayout = QtGui.QVBoxLayout(self.tab)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.uiConsolePortRangeGroupBox = QtGui.QGroupBox(self.tab)
self.uiConsolePortRangeGroupBox.setObjectName(_fromUtf8("uiConsolePortRangeGroupBox"))
self.horizontalLayout = QtGui.QHBoxLayout(self.uiConsolePortRangeGroupBox)
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.uiConsoleStartPortSpinBox = QtGui.QSpinBox(self.uiConsolePortRangeGroupBox)
self.uiConsoleStartPortSpinBox.setSuffix(_fromUtf8(" TCP"))
self.uiConsoleStartPortSpinBox.setMaximum(65535)
self.uiConsoleStartPortSpinBox.setProperty("value", 4001)
self.uiConsoleStartPortSpinBox.setObjectName(_fromUtf8("uiConsoleStartPortSpinBox"))
self.horizontalLayout.addWidget(self.uiConsoleStartPortSpinBox)
self.uiConsolePortRangeLabel = QtGui.QLabel(self.uiConsolePortRangeGroupBox)
self.uiConsolePortRangeLabel.setObjectName(_fromUtf8("uiConsolePortRangeLabel"))
self.horizontalLayout.addWidget(self.uiConsolePortRangeLabel)
self.uiConsoleEndPortSpinBox = QtGui.QSpinBox(self.uiConsolePortRangeGroupBox)
self.uiConsoleEndPortSpinBox.setSuffix(_fromUtf8(" TCP"))
self.uiConsoleEndPortSpinBox.setMaximum(65535)
self.uiConsoleEndPortSpinBox.setProperty("value", 4500)
self.uiConsoleEndPortSpinBox.setObjectName(_fromUtf8("uiConsoleEndPortSpinBox"))
self.horizontalLayout.addWidget(self.uiConsoleEndPortSpinBox)
spacerItem2 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem2)
self.verticalLayout.addWidget(self.uiConsolePortRangeGroupBox)
self.uiUDPPortRangeGroupBox = QtGui.QGroupBox(self.tab)
self.uiUDPPortRangeGroupBox.setObjectName(_fromUtf8("uiUDPPortRangeGroupBox"))
self.horizontalLayout_4 = QtGui.QHBoxLayout(self.uiUDPPortRangeGroupBox)
self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4"))
self.uiUDPStartPortSpinBox = QtGui.QSpinBox(self.uiUDPPortRangeGroupBox)
self.uiUDPStartPortSpinBox.setSuffix(_fromUtf8(" UDP"))
self.uiUDPStartPortSpinBox.setMaximum(65535)
self.uiUDPStartPortSpinBox.setProperty("value", 30001)
self.uiUDPStartPortSpinBox.setObjectName(_fromUtf8("uiUDPStartPortSpinBox"))
self.horizontalLayout_4.addWidget(self.uiUDPStartPortSpinBox)
self.uiUDPPortRangeLabel = QtGui.QLabel(self.uiUDPPortRangeGroupBox)
self.uiUDPPortRangeLabel.setObjectName(_fromUtf8("uiUDPPortRangeLabel"))
self.horizontalLayout_4.addWidget(self.uiUDPPortRangeLabel)
self.uiUDPEndPortSpinBox = QtGui.QSpinBox(self.uiUDPPortRangeGroupBox)
self.uiUDPEndPortSpinBox.setSuffix(_fromUtf8(" UDP"))
self.uiUDPEndPortSpinBox.setMaximum(65535)
self.uiUDPEndPortSpinBox.setProperty("value", 40000)
self.uiUDPEndPortSpinBox.setObjectName(_fromUtf8("uiUDPEndPortSpinBox"))
self.horizontalLayout_4.addWidget(self.uiUDPEndPortSpinBox)
spacerItem3 = QtGui.QSpacerItem(147, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout_4.addItem(spacerItem3)
self.verticalLayout.addWidget(self.uiUDPPortRangeGroupBox)
spacerItem4 = QtGui.QSpacerItem(20, 304, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem4)
self.uiTabWidget.addTab(self.tab, _fromUtf8(""))
self.vboxlayout.addWidget(self.uiTabWidget)
self.retranslateUi(IOUPreferencesPageWidget)
self.uiTabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(IOUPreferencesPageWidget)
def retranslateUi(self, IOUPreferencesPageWidget):
IOUPreferencesPageWidget.setWindowTitle(_translate("IOUPreferencesPageWidget", "IOS on UNIX", None))
self.uiIOURCPathToolButton.setText(_translate("IOUPreferencesPageWidget", "...", None))
self.uiTestSettingsPushButton.setText(_translate("IOUPreferencesPageWidget", "Test settings", None))
self.uiRestoreDefaultsPushButton.setText(_translate("IOUPreferencesPageWidget", "Restore defaults", None))
self.uiIouyapPathLabel.setText(_translate("IOUPreferencesPageWidget", "Path to iouyap (local Linux server only):", None))
self.uiIOURCPathLabel.setText(_translate("IOUPreferencesPageWidget", "Path to IOURC (pushed to the server):", None))
self.uiIouyapPathToolButton.setText(_translate("IOUPreferencesPageWidget", "...", None))
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiGeneralSettingsTabWidget), _translate("IOUPreferencesPageWidget", "General settings", None))
self.uiUseLocalServercheckBox.setText(_translate("IOUPreferencesPageWidget", "Use the local server (Linux only)", None))
self.uiRemoteServersGroupBox.setTitle(_translate("IOUPreferencesPageWidget", "Remote servers", None))
self.uiRemoteServersTreeWidget.headerItem().setText(0, _translate("IOUPreferencesPageWidget", "Host", None))
self.uiRemoteServersTreeWidget.headerItem().setText(1, _translate("IOUPreferencesPageWidget", "Port", None))
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiServerSettingsTabWidget), _translate("IOUPreferencesPageWidget", "Server settings", None))
self.uiConsolePortRangeGroupBox.setTitle(_translate("IOUPreferencesPageWidget", "Console port range", None))
self.uiConsolePortRangeLabel.setText(_translate("IOUPreferencesPageWidget", "to", None))
self.uiUDPPortRangeGroupBox.setTitle(_translate("IOUPreferencesPageWidget", "UDP tunneling port range", None))
self.uiUDPPortRangeLabel.setText(_translate("IOUPreferencesPageWidget", "to", None))
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.tab), _translate("IOUPreferencesPageWidget", "Advanced settings", None))

View File

@@ -0,0 +1,623 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
VPCS device implementation.
"""
import os
import base64
from gns3.node import Node
from gns3.ports.port import Port
from gns3.ports.ethernet_port import EthernetPort
from gns3.ports.serial_port import SerialPort
import logging
log = logging.getLogger(__name__)
class VPCSDevice(Node):
"""
VPCS device.
:param module: parent module for this node
:param server: GNS3 server instance
"""
def __init__(self, module, server):
Node.__init__(self, server)
log.info("VPCS instance is being created")
self._vpcs_id = None
self._defaults = {}
self._inital_settings = None
self._loading = False
self._module = module
self._ports = []
self._settings = {"name": "",
"path": "",
"startup_config": "",
"ram": 256,
"nvram": 128,
"ethernet_adapters": 2,
"serial_adapters": 2,
"console": None}
#self._occupied_slots = []
self._addAdapters(2, 2)
# save the default settings
self._defaults = self._settings.copy()
def _addAdapters(self, nb_ethernet_adapters, nb_serial_adapters):
"""
Adds ports based on what adapter is inserted in which slot.
:param adapter: adapter name
:param slot_number: slot number (integer)
"""
nb_adapters = nb_ethernet_adapters + nb_serial_adapters
for slot_number in range(0, nb_adapters):
# if slot_number in self._occupied_slots:
# continue
for port_number in range(0, 4):
if slot_number < nb_ethernet_adapters:
port = EthernetPort
else:
port = SerialPort
port_name = port.longNameType() + str(slot_number) + "/" + str(port_number)
new_port = port(port_name)
new_port.setPortNumber(port_number)
new_port.setSlotNumber(slot_number)
#self._occupied_slots.append(slot_number)
self._ports.append(new_port)
log.debug("port {} has been added".format(port_name))
def _removeAdapters(self, nb_ethernet_adapters, nb_serial_adapters):
"""
Removes ports when an adapter is removed from a slot.
:param slot_number: slot number (integer)
"""
for port in self._ports.copy():
if (port.slotNumber() >= nb_ethernet_adapters and port.linkType() == "Ethernet") or \
(port.slotNumber() >= nb_serial_adapters and port.linkType() == "Serial"):
#self._occupied_slots.remove(port.slotNumber())
self._ports.remove(port)
log.info("port {} has been removed".format(port.name()))
def setup(self, vpcs_path, name=None, initial_settings={}):
"""
Setups this VPCS device.
:param name: optional name
"""
params = {"path": vpcs_path}
if name:
params["name"] = self._settings["name"] = name
# other initial settings will be applied when the router has been created
if initial_settings:
self._inital_settings = initial_settings
self._server.send_message("vpcs.create", params, self._setupCallback)
def _setupCallback(self, result, error=False):
"""
Callback for setup.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
log.error("error while setting up {}: {}".format(self.name(), result["message"]))
self.server_error_signal.emit(self.id(), result["code"], result["message"])
return
self._vpcs_id = result["id"]
if not self._vpcs_id:
self.error_signal.emit(self.id(), "returned ID from server is null")
return
# update the settings using the defaults sent by the server
for name, value in result.items():
if name in self._settings and self._settings[name] != value:
log.info("VPCS instance setting up and updating {} from '{}' to '{}'".format(name, self._settings[name], value))
self._settings[name] = value
# update the node with setup initial settings if any
if self._inital_settings:
self.update(self._inital_settings)
elif self._loading:
self.updated_signal.emit()
else:
self.setInitialized(True)
log.info("VPCS instance {} has been created".format(self.name()))
self.created_signal.emit(self.id())
self._module.addNode(self)
def delete(self):
"""
Deletes this VPCS instance.
"""
log.debug("VPCS device {} is being deleted".format(self.name()))
# first delete all the links attached to this node
self.delete_links_signal.emit()
if self._vpcs_id:
self._server.send_message("vpcs.delete", {"id": self._vpcs_id}, self._deleteCallback)
else:
self.deleted_signal.emit()
self._module.removeNode(self)
def _deleteCallback(self, result, error=False):
"""
Callback for delete.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
log.error("error while deleting {}: {}".format(self.name(), result["message"]))
self.server_error_signal.emit(self.id(), result["code"], result["message"])
log.info("{} has been deleted".format(self.name()))
self.deleted_signal.emit()
self._module.removeNode(self)
def _base64Config(self, config_path):
"""
Get the base64 encoded config from a file.
:param config_path: path to the configuration file.
:returns: base64 encoded string
"""
try:
with open(config_path, "r") as f:
log.info("opening configuration file: {}".format(config_path))
config = f.read()
config = '!\n' + config.replace('\r', "")
encoded = ("").join(base64.encodestring(config.encode("utf-8")).decode("utf-8").split())
return encoded
except OSError as e:
log.warn("could not base64 encode {}: {}".format(config_path, e))
return ""
def update(self, new_settings):
"""
Updates the settings for this VPCS device.
:param new_settings: settings dictionary
"""
params = {"id": self._vpcs_id}
for name, value in new_settings.items():
if name in self._settings and self._settings[name] != value:
params[name] = value
if "startup_config" in new_settings and self._settings["startup_config"] != new_settings["startup_config"] \
and os.path.isfile(new_settings["startup_config"]):
params["startup_config_base64"] = self._base64Config(new_settings["startup_config"])
log.debug("{} is updating settings: {}".format(self.name(), params))
self._server.send_message("vpcs.update", params, self._updateCallback)
def _updateCallback(self, result, error=False):
"""
Callback for update.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
log.error("error while deleting {}: {}".format(self.name(), result["message"]))
self.server_error_signal.emit(self.id(), result["code"], result["message"])
return
updated = False
nb_adapters_changed = False
for name, value in result.items():
if name in self._settings and self._settings[name] != value:
log.info("{}: updating {} from '{}' to '{}'".format(self.name(), name, self._settings[name], value))
updated = True
if (name == "ethernet_adapters" or name == "serial_adapters"):
nb_adapters_changed = True
self._settings[name] = value
if nb_adapters_changed:
log.debug("number of adapters has changed: Ethernet={} Serial={}".format(self._settings["ethernet_adapters"], self._settings["serial_adapters"]))
#TODO: dynamically add/remove adapters
self._ports.clear()
self._addAdapters(self._settings["ethernet_adapters"], self._settings["serial_adapters"])
if self._inital_settings and not self._loading:
self.setInitialized(True)
log.info("VPCS device {} has been created".format(self.name()))
self.created_signal.emit(self.id())
self._module.addNode(self)
self._inital_settings = None
elif updated or self._loading:
log.info("VPCS device {} has been updated".format(self.name()))
self.updated_signal.emit()
def start(self):
"""
Starts this VPCS instance.
"""
log.debug("{} is starting".format(self.name()))
self._server.send_message("vpcs.start", {"id": self._vpcs_id}, self._startCallback)
def _startCallback(self, result, error=False):
"""
Callback for start.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
log.error("error while starting {}: {}".format(self.name(), result["message"]))
self.server_error_signal.emit(self.id(), result["code"], result["message"])
else:
log.info("{} has started".format(self.name()))
self.setStatus(Node.started)
for port in self._ports:
# set ports as started
port.setStatus(Port.started)
self.started_signal.emit()
def stop(self):
"""
Stops this VPCS instance.
"""
log.debug("{} is stopping".format(self.name()))
self._server.send_message("vpcs.stop", {"id": self._vpcs_id}, self._stopCallback)
def _stopCallback(self, result, error=False):
"""
Callback for stop.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
log.error("error while stopping {}: {}".format(self.name(), result["message"]))
self.server_error_signal.emit(self.id(), result["code"], result["message"])
else:
log.info("{} has stopped".format(self.name()))
self.setStatus(Node.stopped)
for port in self._ports:
# set ports as stopped
port.setStatus(Port.stopped)
self.stopped_signal.emit()
def reload(self):
"""
Reloads this VPCS instance.
"""
log.debug("{} is being reloaded".format(self.name()))
self._server.send_message("vpcs.reload", {"id": self._vpcs_id}, self._reloadCallback)
def _reloadCallback(self, result, error=False):
"""
Callback for reload.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
log.error("error while suspending {}: {}".format(self.name(), result["message"]))
self.server_error_signal.emit(self.id(), result["code"], result["message"])
else:
log.info("{} has reloaded".format(self.name()))
def allocateUDPPort(self, port_id):
"""
Requests an UDP port allocation.
:param port_id: port identifier
"""
log.debug("{} is requesting an UDP port allocation".format(self.name()))
self._server.send_message("vpcs.allocate_udp_port", {"id": self._vpcs_id, "port_id": port_id}, self._allocateUDPPortCallback)
def _allocateUDPPortCallback(self, result, error=False):
"""
Callback for allocateUDPPort.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
log.error("error while allocating an UDP port for {}: {}".format(self.name(), result["message"]))
self.server_error_signal.emit(self.id(), result["code"], result["message"])
else:
port_id = result["port_id"]
lport = result["lport"]
log.debug("{} has allocated UDP port {}".format(self.name(), port_id, lport))
self.allocate_udp_nio_signal.emit(self.id(), port_id, lport)
def addNIO(self, port, nio):
"""
Adds a new NIO on the specified port for this VPCS instance.
:param port: Port instance
:param nio: NIO instance
"""
params = {"id": self._vpcs_id,
"slot": port.slotNumber(),
"port": port.portNumber(),
"port_id": port.id()}
params["nio"] = self.getNIOInfo(nio)
log.debug("{} is adding an {}: {}".format(self.name(), nio, params))
self._server.send_message("vpcs.add_nio", params, self._addNIOCallback)
def _addNIOCallback(self, result, error=False):
"""
Callback for addNIO.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
log.error("error while adding an UDP NIO for {}: {}".format(self.name(), result["message"]))
self.server_error_signal.emit(self.id(), result["code"], result["message"])
self.nio_cancel_signal.emit(self.id())
else:
self.nio_signal.emit(self.id(), result["port_id"])
def deleteNIO(self, port):
"""
Deletes an NIO from the specified port on this VPCS instance
:param port: Port instance
"""
params = {"id": self._vpcs_id,
"port": port.portNumber(),
"slot": port.slotNumber()}
log.debug("{} is deleting an NIO: {}".format(self.name(), params))
self._server.send_message("vpcs.delete_nio", params, self._deleteNIOCallback)
def _deleteNIOCallback(self, result, error=False):
"""
Callback for deleteNIO.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
log.error("error while deleting NIO {}: {}".format(self.name(), result["message"]))
self.server_error_signal.emit(self.id(), result["code"], result["message"])
return
log.debug("{} has deleted a NIO: {}".format(self.name(), result))
def info(self):
"""
Returns information about this VPCS device.
:returns: formated string
"""
if self.status() == Node.started:
state = "started"
else:
state = "stopped"
info = """Device {name} is {state}
Node ID is {id}, server's VPCS device ID is {vpcs_id}
Hardware is Cisco VPCS generic device with {ram} MB RAM and {nvram} KB NVRAM
Device's server runs on {host}:{port}, console is on port {console}
Image is {image_name}
{nb_ethernet} Ethernet adapters and {nb_serial} serial adapters installed
""".format(name=self.name(),
id=self.id(),
vpcs_id=self._vpcs_id,
state=state,
ram=self._settings["ram"],
nvram=self._settings["nvram"],
host=self._server.host,
port=self._server.port,
console=self._settings["console"],
image_name=os.path.basename(self._settings["path"]),
nb_ethernet=self._settings["ethernet_adapters"],
nb_serial=self._settings["serial_adapters"])
port_info = ""
for port in self._ports:
if port.isFree():
port_info += " {port_name} is empty\n".format(port_name=port.name())
else:
port_info += " {port_name} {port_description}\n".format(port_name=port.name(),
port_description=port.description())
return info + port_info
def dump(self):
"""
Returns a representation of this VPCS device.
(to be saved in a topology file).
:returns: representation of the node (dictionary)
"""
router = {"id": self.id(),
"type": self.__class__.__name__,
"description": str(self),
"properties": {},
"server_id": self._server.id()}
# add the properties
for name, value in self._settings.items():
if name in self._defaults and self._defaults[name] != value:
router["properties"][name] = value
# add the ports
if self._ports:
ports = router["ports"] = []
for port in self._ports:
ports.append(port.dump())
#TODO: handle the image path
# router["properties"]["image"]
return router
def load(self, node_info):
"""
Loads an VPCS device representation
(from a topology file).
:param node_info: representation of the node (dictionary)
"""
self.node_info = node_info
settings = node_info["properties"]
name = settings.pop("name")
path = settings.pop("path")
self.updated_signal.connect(self._updatePortSettings)
# block the created signal, it will be triggered when loading is completely done
self._loading = True
log.info("vpcs device {} is loading".format(name))
self.setup(path, name, settings)
def _updatePortSettings(self):
"""
Updates port settings when loading a topology.
"""
self.updated_signal.disconnect(self._updatePortSettings)
# update the port with the correct names and IDs
if "ports" in self.node_info:
ports = self.node_info["ports"]
for topology_port in ports:
for port in self._ports:
if topology_port["port_number"] == port.portNumber() and topology_port["slot_number"] == port.slotNumber():
port.setName(topology_port["name"])
port.setId(topology_port["id"])
# now we can set the node has initialized and trigger the signal
self.setInitialized(True)
log.info("router {} has been loaded".format(self.name()))
self.created_signal.emit(self.id())
self._module.addNode(self)
self._inital_settings = None
self._loading = False
def name(self):
"""
Returns the name of this VPCS device.
:returns: name (string)
"""
return self._settings["name"]
def settings(self):
"""
Returns all this VPCS device settings.
:returns: settings dictionary
"""
return self._settings
def ports(self):
"""
Returns all the ports for this VPCS device.
:returns: list of Port instances
"""
return self._ports
def console(self):
"""
Returns the console port for this VPCS device.
:returns: port (integer)
"""
return self._settings["console"]
def configPage(self):
"""
Returns the configuration page widget to be used by the node configurator.
:returns: QWidget object
"""
from .pages.vpcs_device_configuration_page import vpcsDeviceConfigurationPage
return vpcsDeviceConfigurationPage
@staticmethod
def defaultSymbol():
"""
Returns the default symbol path for this node.
:returns: symbol path (or resource).
"""
return ":/symbols/multilayer_switch.normal.svg"
@staticmethod
def hoverSymbol():
"""
Returns the symbol to use when this node is hovered.
:returns: symbol path (or resource).
"""
return ":/symbols/multilayer_switch.selected.svg"
@staticmethod
def symbolName():
return "VPCS device"
@staticmethod
def categories():
"""
Returns the node categories the node is part of (used by the device panel).
:returns: list of node category (integer)
"""
return [Node.routers, Node.switches]
def __str__(self):
return "VPCS device"