IOU integration (to be polished).

Checks for valid IOS image (ELF header).
Generic module handling.
This commit is contained in:
grossmj
2014-03-11 16:44:37 -06:00
parent 6230a017bd
commit c5321dc95d
28 changed files with 2715 additions and 64 deletions

View File

@@ -1,4 +1,4 @@
-rrequirements.txt
pytest
ws4py

View File

@@ -26,7 +26,7 @@ from .items.node_item import NodeItem
from .node_configurator import NodeConfigurator
from .link import Link
from .node import Node
from .modules.dynamips import Dynamips
from .modules import MODULES
from .modules.module_error import ModuleError
from .settings import GRAPHICS_VIEW_SETTINGS, GRAPHICS_VIEW_SETTING_TYPES
from .topology import Topology
@@ -86,8 +86,10 @@ class GraphicsView(QtGui.QGraphicsView):
else:
self.scene().removeItem(item)
dynamips = Dynamips.instance()
dynamips.reset()
# reset the modules
for module in MODULES:
instance = module.instance()
instance.reset()
Node.reset()
Link.reset()
@@ -97,8 +99,9 @@ class GraphicsView(QtGui.QGraphicsView):
def setLocalBaseWorkingDirtoAllModules(self, path):
try:
dynamips = Dynamips.instance()
dynamips.setLocalBaseWorkingDir(path)
for module in MODULES:
instance = module.instance()
instance.setLocalBaseWorkingDir(path)
except ModuleError as e:
QtGui.QMessageBox.critical(self, "Local working directory", "{}".format(e))
@@ -748,12 +751,18 @@ class GraphicsView(QtGui.QGraphicsView):
:param pos: position of the drop event
"""
#TODO: node setup management with other modules
dynamips = Dynamips.instance()
try:
node = dynamips.createNode(node_class)
node_module = None
for module in MODULES:
instance = module.instance()
if node_class in instance.nodes():
node_module = instance
break
if not node_module:
raise ModuleError("Could not find any module for {}".format(node_class))
node = node_module.createNode(node_class)
node_item = NodeItem(node)
dynamips.setupNode(node)
node_module.setupNode(node)
except ModuleError as e:
QtGui.QMessageBox.critical(self, "Node creation", "{}".format(e))
return

View File

@@ -0,0 +1,21 @@
# -*- 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/>.
from gns3.modules.dynamips import Dynamips
from gns3.modules.iou import IOU
MODULES = [Dynamips, IOU]

View File

@@ -359,7 +359,7 @@ class Dynamips(Module):
if name in globals():
return globals()[name]
raise ModuleError("Dynamips module could not find object {}".format(name))
return None
@staticmethod
def nodes():

View File

@@ -185,6 +185,19 @@ class IOSRouterPreferencesPage(QtGui.QWidget, Ui_IOSRouterPreferencesPageWidget)
except UnicodeEncodeError:
QtGui.QMessageBox.warning(self, "IOS image", "The IOS image filename should contains only ascii (English) characters.")
try:
with open(path, "rb") as f:
# read the first 7 bytes of the file.
elf_header_start = f.read(7)
except EnvironmentError as e:
QtGui.QMessageBox.critical(self, "IOS 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
if elf_header_start != b'\x7fELF\x01\x02\x01':
QtGui.QMessageBox.critical(self, "IOS image", "Sorry, this is not a valid IOS image!")
return
self.uiIOSPathLineEdit.clear()
self.uiIOSPathLineEdit.setText(path)

View File

@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/modules/dynamips/ui/dynamips_preferences_page.ui'
#
# Created: Tue Feb 4 22:54:42 2014
# Created: Fri Mar 7 14:47:47 2014
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!

View File

@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/modules/dynamips/ui/router_configuration_page.ui'
#
# Created: Mon Feb 17 11:03:24 2014
# Created: Fri Mar 7 14:47:47 2014
# by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!

View File

@@ -0,0 +1,378 @@
# -*- 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/>.
"""
IOU module implementation.
"""
import socket
import base64
import os
from gns3.qt import QtCore
from gns3.servers import Servers
from ..module import Module
from ..module_error import ModuleError
from .iou_device import IOUDevice
from .settings import IOU_SETTINGS, IOU_SETTING_TYPES
import logging
log = logging.getLogger(__name__)
class IOU(Module):
"""
IOU module.
"""
def __init__(self):
Module.__init__(self)
self._settings = {}
self._iou_images = {}
self._servers = []
self._working_dir = ""
# load the settings
self._loadSettings()
self._loadIOUImages()
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 IOU_SETTINGS.items():
self._settings[name] = settings.value(name, value, type=IOU_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 _loadIOUImages(self):
"""
Load the IOU images from the persistent settings file.
"""
# load the settings
settings = QtCore.QSettings()
settings.beginGroup("IOUs")
# load the IOU images
size = settings.beginReadArray("iou_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._iou_images[key] = {"path": path,
"image": image,
"startup_config": startup_config,
"ram": ram,
"nvram": nvram,
"server": server}
settings.endArray()
settings.endGroup()
def _saveIOUImages(self):
"""
Saves the IOU images to the persistent settings file.
"""
# save the settings
settings = QtCore.QSettings()
settings.beginGroup("IOUs")
settings.remove("")
# save the IOU images
settings.beginWriteArray("iou_image", len(self._iou_images))
index = 0
for ios_image in self._iou_images.values():
settings.setArrayIndex(index)
for name, value in ios_image.items():
settings.setValue(name, value)
index += 1
settings.endArray()
settings.endGroup()
def setLocalBaseWorkingDir(self, path):
"""
Sets the local base working directory for this module.
:param path: path to the local working directory
"""
self._working_dir = os.path.join(path, "iou")
if not os.path.exists(self._working_dir):
try:
os.makedirs(self._working_dir)
except EnvironmentError as e:
raise ModuleError("{}".format(e))
log.info("local working directory for IOU module: {}".format(self._working_dir))
servers = Servers.instance()
server = servers.localServer()
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 IOU 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 IOU 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 iouImages(self):
"""
Returns IOU images settings.
:returns: IOU images settings (dictionary)
"""
return self._iou_images
def setIOUImages(self, new_iou_images):
"""
Sets IOS images settings.
:param new_iou_images: IOS images settings (dictionary)
"""
self._iou_images = new_iou_images.copy()
self._saveIOUImages()
def settings(self):
"""
Returns the module settings
:returns: module settings (dictionary)
"""
return self._settings
def _base64iourc(self, iourc_path):
"""
Get the content of the IOURC file base64 encoded.
:param config_path: path to the iourc file.
:returns: base64 encoded string
"""
try:
with open(iourc_path, "r") as f:
log.info("opening iourc file: {}".format(iourc_path))
config = f.read()
encoded = ("").join(base64.encodestring(config.encode("utf-8")).decode("utf-8").split())
return encoded
except EnvironmentError as e:
log.warn("could not base64 encode {}: {}".format(iourc_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 "iourc" in params:
# encode the iourc file in base64
params["iourc"] = self._base64iourc(params["iourc"])
for server in self._servers:
server.send_notification("iou.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 IOU settings to server {}:{}".format(server.host, server.port))
params = self._settings.copy()
# encode the iourc file in base64
params["iourc"] = self._base64iourc(params["iourc"])
# send the local working directory only if this is a local server
servers = Servers.instance()
if server == servers.localServer():
params.update({"working_dir": self._working_dir})
server.send_notification("iou.settings", params)
def createNode(self, node_class, server=None):
"""
Creates a new node.
:param node_class: Node object
:param server: optional WebSocketClient instance
"""
log.info("creating node {}".format(node_class))
if not self._settings["iourc"] or not os.path.exists(self._settings["iourc"]):
raise ModuleError("The path to IOURC must be configured")
# allocate a server for the node if none is given
servers = Servers.instance()
if self._settings["use_local_server"] and not server:
# use the local server
server = servers.localServer()
elif not server:
# pick up a remote server (round-robin method)
server = next(iter(servers))
if not server:
raise ModuleError("No remote server is configured")
if not server.connected():
try:
log.info("reconnecting to server {}:{}".format(server.host, server.port))
server.reconnect()
self._sendSettings(server)
except socket.error 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))
if not self._iou_images:
raise ModuleError("No IOU image found for this device")
settings = {}
#FIXME: for now use the fist available image
iouimage = list(self._iou_images.keys())[0]
startup_config = self._iou_images[iouimage]["startup_config"]
iou_path = self._iou_images[iouimage]["path"]
if startup_config:
settings = {"startup_config": startup_config}
node.setup(iou_path, initial_settings=settings)
def reset(self):
"""
Resets the servers.
"""
log.info("IOU module reset")
for server in self._servers:
if server.connected():
server.send_notification("iou.reset")
@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 [IOUDevice]
@staticmethod
def preferencePages():
"""
:returns: QWidget object list
"""
from .pages.iou_preferences_page import IOUPreferencesPage
from .pages.iou_device_preferences_page import IOUDevicePreferencesPage
return [IOUPreferencesPage, IOUDevicePreferencesPage]
@staticmethod
def instance():
"""
Singleton to return only on instance of IOU module.
:returns: instance of IOU
"""
if not hasattr(IOU, "_instance"):
IOU._instance = IOU()
return IOU._instance

View File

@@ -0,0 +1,551 @@
# -*- 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/>.
"""
IOU 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 IOUDevice(Node):
"""
IOU device.
:param module: parent module for this node
:param server: GNS3 server instance
"""
def __init__(self, module, server):
Node.__init__(self, server)
log.info("IOU instance is being created")
self._iou_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, iou_path, name=None, initial_settings={}):
"""
Setups this IOU device.
:param name: optional name
"""
params = {"path": iou_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("iou.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.error_signal.emit(self.name(), result["code"], result["message"])
return
self._iou_id = result["id"]
# 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("IOU 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)
else:
self.setInitialized(True)
log.info("IOU instance {} has been created".format(self.name()))
self.created_signal.emit(self.id())
def delete(self):
"""
Deletes this IOU instance.
"""
log.debug("IOU device {} is being deleted".format(self.name()))
# first delete all the links attached to this node
self.delete_links_signal.emit()
if self._iou_id:
self._server.send_message("iou.delete", {"id": self._iou_id}, self._deleteCallback)
else:
self.delete_signal.emit()
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.error_signal.emit(self.name(), result["code"], result["message"])
else:
log.info("{} has been deleted".format(self.name()))
self.delete_signal.emit()
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 EnvironmentError as e:
log.warn("could not base64 encode {}: {}".format(config_path, e))
return ""
def update(self, new_settings):
"""
Updates the settings for this IOU device.
:param new_settings: settings dictionary
"""
params = {"id": self._iou_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.exists(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("iou.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.error_signal.emit(self.name(), 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("IOU device {} has been created".format(self.name()))
self.created_signal.emit(self.id())
self._inital_settings = None
elif updated:
log.info("IOU device {} has been updated".format(self.name()))
self.updated_signal.emit()
def start(self):
"""
Starts this IOU instance.
"""
log.debug("{} is starting".format(self.name()))
self._server.send_message("iou.start", {"id": self._iou_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.error_signal.emit(self.name(), 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 IOU instance.
"""
log.debug("{} is stopping".format(self.name()))
self._server.send_message("iou.stop", {"id": self._iou_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.error_signal.emit(self.name(), 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 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("iou.allocate_udp_port", {"id": self._iou_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.error_signal.emit(self.name(), result["code"], result["message"])
else:
port_id = result["port_id"]
lhost = result["lhost"]
lport = result["lport"]
log.debug("{} has allocated UDP port {} for host {}".format(self.name(), port_id, lport, lhost))
self.allocate_udp_nio_signal.emit(self.id(), port_id, lport, lhost)
def addNIO(self, port, nio):
"""
Adds a new NIO on the specified port for this IOU instance.
:param port: Port instance
:param nio: NIO instance
"""
nio_type = str(nio)
params = {"id": self._iou_id,
"nio": nio_type,
"slot": port.slotNumber(),
"port": port.portNumber(),
"port_id": port.id()}
self.addNIOInfo(nio, params)
log.debug("{} is adding an {}: {}".format(self.name(), nio_type, params))
self._server.send_message("iou.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.error_signal.emit(self.name(), result["code"], result["message"])
else:
self.nio_signal.emit(self.id(), result["port_id"])
def deleteNIO(self, port):
"""
Deletes an NIO from the specified port on this IOU instance
:param port: Port instance
"""
params = {"id": self._iou_id,
"port": port.portNumber(),
"slot": port.slotNumber()}
log.debug("{} is deleting an NIO: {}".format(self.name(), params))
self._server.send_message("iou.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.error_signal.emit(self.name(), result["code"], result["message"])
return
log.debug("{} has deleted a NIO: {}".format(self.name(), result))
def info(self):
"""
Returns information about this IOU device.
:returns: formated string
"""
return ""
def dump(self):
"""
Returns a representation of this IOU 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 IOU 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("iou device {} is loading".format(name))
self.setup(path, name, settings)
def _updatePortSettings(self):
"""
Updates port settings when loading a topology.
"""
# 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._inital_settings = None
self._loading = False
def name(self):
"""
Returns the name of this IOU device.
:returns: name (string)
"""
return self._settings["name"]
def settings(self):
"""
Returns all this IOU device settings.
:returns: settings dictionary
"""
return self._settings
def ports(self):
"""
Returns all the ports for this IOU device.
:returns: list of Port instances
"""
return self._ports
def console(self):
"""
Returns the console port for this IOU 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.iou_device_configuration_page import iouDeviceConfigurationPage
return iouDeviceConfigurationPage
@staticmethod
def defaultSymbol():
"""
Returns the default symbol path for this node.
:returns: symbol path (or resource).
"""
return ":/symbols/router.normal.svg"
@staticmethod
def hoverSymbol():
"""
Returns the symbol to use when this node is hovered.
:returns: symbol path (or resource).
"""
return ":/symbols/router.selected.svg"
@staticmethod
def symbolName():
return "IOU device"
def __str__(self):
return "IOU device"

View File

View File

@@ -0,0 +1,109 @@
# -*- 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 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)
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"])
else:
self.uiNameLabel.hide()
self.uiNameLineEdit.hide()
self.uiConsolePortLabel.hide()
self.uiConsolePortSpinBox.hide()
# load the IOU image name without the full path
self.uiIOUImageTextLabel.setText(os.path.basename(settings["path"]))
# load the startup-config
self.uiStartupConfigTextLabel.setText(settings["startup_config"])
# 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()
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,207 @@
# -*- 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 .. 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)
key = "{server}:{image}".format(server="local", 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)
key = "{server}:{image}".format(server="local", 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, "local")
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, "local")
self.uiIOUImagesTreeWidget.setCurrentItem(item)
self._iou_images[key] = {"path": path,
"image": image,
"startup_config": startup_config,
"ram": ram,
"nvram": nvram,
"server": "local"}
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)
key = "{server}:{image}".format(server="local", 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 EnvironmentError 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, "local")
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,108 @@
# -*- 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 sys
from gns3.qt import 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)
# connect signals
self.uiRestoreDefaultsPushButton.clicked.connect(self._restoreDefaultsSlot)
self.uiUseLocalServercheckBox.stateChanged.connect(self._useLocalServerSlot)
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:
# IOU is only available on Linux
if not sys.platform.startswith("linux"):
QtGui.QMessageBox.critical(self, "IOU", "Sorry, local server is only supported on Linux")
return
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.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 loadPreferences(self):
"""
Loads IOU preferences.
"""
iou_settings = IOU.instance().settings()
self._populateWidgets(iou_settings)
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))
def savePreferences(self):
"""
Saves IOU preferences.
"""
new_settings = {}
new_settings["iourc"] = self.uiIOURCPathLineEdit.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,44 @@
# -*- 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": "",
"console_start_port_range": 4001,
"console_end_port_range": 4512,
"udp_start_port_range": 30001,
"udp_end_port_range": 40001,
"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,
"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,190 @@
<?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="1" column="0">
<widget class="QLabel" name="uiIOUImageLabel">
<property name="text">
<string>IOU image:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="uiStartupConfigLabel">
<property name="text">
<string>Startup-config:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="uiConsolePortLabel">
<property name="text">
<string>Console port:</string>
</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="5" column="0">
<widget class="QLabel" name="uiNvramLabel">
<property name="text">
<string>NVRAM size:</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="3">
<widget class="QLabel" name="uiEthernetAdaptersLabel">
<property name="text">
<string>Ethernet adapters:</string>
</property>
</widget>
</item>
<item row="6" column="3">
<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" colspan="2">
<widget class="QLabel" name="uiSerialAdaptersLabel">
<property name="text">
<string>Serial adapters:</string>
</property>
</widget>
</item>
<item row="7" column="3">
<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="3">
<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>
<item row="5" column="3">
<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="4" column="3">
<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="3" column="3">
<widget class="QSpinBox" name="uiConsolePortSpinBox">
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLabel" name="uiStartupConfigTextLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="uiIOUImageTextLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="uiNameLineEdit"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,131 @@
# -*- 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: Sat Mar 8 18:19:32 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.uiIOUImageLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiIOUImageLabel.setObjectName(_fromUtf8("uiIOUImageLabel"))
self.gridLayout.addWidget(self.uiIOUImageLabel, 1, 0, 1, 1)
self.uiStartupConfigLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiStartupConfigLabel.setObjectName(_fromUtf8("uiStartupConfigLabel"))
self.gridLayout.addWidget(self.uiStartupConfigLabel, 2, 0, 1, 1)
self.uiConsolePortLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiConsolePortLabel.setObjectName(_fromUtf8("uiConsolePortLabel"))
self.gridLayout.addWidget(self.uiConsolePortLabel, 3, 0, 1, 1)
self.uiRamLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiRamLabel.setObjectName(_fromUtf8("uiRamLabel"))
self.gridLayout.addWidget(self.uiRamLabel, 4, 0, 1, 1)
self.uiNvramLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiNvramLabel.setObjectName(_fromUtf8("uiNvramLabel"))
self.gridLayout.addWidget(self.uiNvramLabel, 5, 0, 1, 1)
self.uiEthernetAdaptersLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiEthernetAdaptersLabel.setObjectName(_fromUtf8("uiEthernetAdaptersLabel"))
self.gridLayout.addWidget(self.uiEthernetAdaptersLabel, 6, 0, 1, 3)
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, 3, 1, 1)
self.uiSerialAdaptersLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiSerialAdaptersLabel.setObjectName(_fromUtf8("uiSerialAdaptersLabel"))
self.gridLayout.addWidget(self.uiSerialAdaptersLabel, 7, 0, 1, 2)
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, 3, 1, 1)
spacerItem = QtGui.QSpacerItem(263, 212, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem, 8, 3, 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, 3, 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, 3, 1, 1)
self.uiConsolePortSpinBox = QtGui.QSpinBox(iouDeviceConfigPageWidget)
self.uiConsolePortSpinBox.setMaximum(65535)
self.uiConsolePortSpinBox.setObjectName(_fromUtf8("uiConsolePortSpinBox"))
self.gridLayout.addWidget(self.uiConsolePortSpinBox, 3, 3, 1, 1)
self.uiStartupConfigTextLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiStartupConfigTextLabel.setText(_fromUtf8(""))
self.uiStartupConfigTextLabel.setObjectName(_fromUtf8("uiStartupConfigTextLabel"))
self.gridLayout.addWidget(self.uiStartupConfigTextLabel, 2, 3, 1, 1)
self.uiIOUImageTextLabel = QtGui.QLabel(iouDeviceConfigPageWidget)
self.uiIOUImageTextLabel.setText(_fromUtf8(""))
self.uiIOUImageTextLabel.setObjectName(_fromUtf8("uiIOUImageTextLabel"))
self.gridLayout.addWidget(self.uiIOUImageTextLabel, 1, 3, 1, 1)
self.uiNameLineEdit = QtGui.QLineEdit(iouDeviceConfigPageWidget)
self.uiNameLineEdit.setObjectName(_fromUtf8("uiNameLineEdit"))
self.gridLayout.addWidget(self.uiNameLineEdit, 0, 3, 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.uiConsolePortLabel.setText(_translate("iouDeviceConfigPageWidget", "Console port:", None))
self.uiRamLabel.setText(_translate("iouDeviceConfigPageWidget", "RAM size:", None))
self.uiNvramLabel.setText(_translate("iouDeviceConfigPageWidget", "NVRAM size:", None))
self.uiEthernetAdaptersLabel.setText(_translate("iouDeviceConfigPageWidget", "Ethernet adapters:", None))
self.uiSerialAdaptersLabel.setText(_translate("iouDeviceConfigPageWidget", "Serial adapters:", None))
self.uiNvramSpinBox.setSuffix(_translate("iouDeviceConfigPageWidget", " KiB", None))
self.uiRamSpinBox.setSuffix(_translate("iouDeviceConfigPageWidget", " MiB", 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>IOS routers</string>
</property>
</column>
<column>
<property name="text">
<string>IOS 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: Sun Mar 9 14:21:50 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", "IOS routers", None))
self.treeWidget_2.headerItem().setText(1, _translate("IOUDevicePreferencesPageWidget", "IOS 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,296 @@
<?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="0" column="0">
<widget class="QLabel" name="uiIOURCPathLabel">
<property name="text">
<string>Path to IOURC:</string>
</property>
</widget>
</item>
<item row="1" 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="2" 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="2" 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="3" 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>
</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</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>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</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"> UDP</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>40001</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,158 @@
# -*- 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: Fri Mar 7 15:10:32 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.uiIOURCPathLabel = QtGui.QLabel(self.uiGeneralSettingsTabWidget)
self.uiIOURCPathLabel.setObjectName(_fromUtf8("uiIOURCPathLabel"))
self.gridLayout.addWidget(self.uiIOURCPathLabel, 0, 0, 1, 1)
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, 1, 0, 1, 2)
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, 2, 0, 1, 1)
spacerItem = QtGui.QSpacerItem(164, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 2, 1, 1, 1)
spacerItem1 = QtGui.QSpacerItem(390, 193, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem1, 3, 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.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
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(" UDP"))
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", 40001)
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.uiIOURCPathLabel.setText(_translate("IOUPreferencesPageWidget", "Path to IOURC:", None))
self.uiIOURCPathToolButton.setText(_translate("IOUPreferencesPageWidget", "...", None))
self.uiTestSettingsPushButton.setText(_translate("IOUPreferencesPageWidget", "Test settings", None))
self.uiRestoreDefaultsPushButton.setText(_translate("IOUPreferencesPageWidget", "Restore defaults", None))
self.uiTabWidget.setTabText(self.uiTabWidget.indexOf(self.uiGeneralSettingsTabWidget), _translate("IOUPreferencesPageWidget", "General settings", None))
self.uiUseLocalServercheckBox.setText(_translate("IOUPreferencesPageWidget", "Use the local server", 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

@@ -21,7 +21,7 @@ Nodes view that list all the available nodes to be dragged and dropped on the QG
import pickle
from .qt import QtCore, QtGui
from .modules.dynamips import Dynamips
from .modules import MODULES
class NodesView(QtGui.QTreeWidget):
@@ -38,13 +38,13 @@ class NodesView(QtGui.QTreeWidget):
# enables the possibility to drag items.
self.setDragEnabled(True)
# FIXME: generic creation of the node list
for node in Dynamips.nodes():
item = QtGui.QTreeWidgetItem(self)
item.setIcon(0, QtGui.QIcon(node.defaultSymbol()))
item.setText(0, node.symbolName())
# add the node class in the item data
item.setData(0, QtCore.Qt.UserRole, node)
for module in MODULES:
for node in module.nodes():
item = QtGui.QTreeWidgetItem(self)
item.setIcon(0, QtGui.QIcon(node.defaultSymbol()))
item.setText(0, node.symbolName())
# add the node class in the item data
item.setData(0, QtCore.Qt.UserRole, node)
def mouseMoveEvent(self, event):
"""

View File

@@ -151,25 +151,26 @@ class ServerPreferencesPage(QtGui.QWidget, Ui_ServerPreferencesPageWidget):
local_server_port = self.uiLocalServerPortSpinBox.value()
local_server_path = self.uiLocalServerPathLineEdit.text()
if not os.path.exists(local_server_path):
QtGui.QMessageBox.critical(self, "Local server", "The path to {} doesn't exists.".format(local_server_path))
else:
server = servers.localServer()
if servers.localServerPath() != local_server_path or server.host != local_server_host or server.port != local_server_port:
# local server settings have changed, let's stop the current local server.
if server.connected():
server.close_connection()
servers.stopLocalServer(wait=True)
#TODO: ASK if the user wants to start local server
if servers.startLocalServer(local_server_path, local_server_host, local_server_port):
thread = WaitForConnectionThread(local_server_host, local_server_port)
dialog = ProgressDialog(thread, "Local server", "Connecting...", "Cancel", busy=True, parent=self)
dialog.show()
dialog.exec_()
else:
QtGui.QMessageBox.critical(self, "Local server", "Could not start the local server process: {}".format(local_server_path))
if local_server_path:
if not os.path.exists(local_server_path):
QtGui.QMessageBox.critical(self, "Local server", "The path to {} doesn't exists.".format(local_server_path))
else:
server = servers.localServer()
if servers.localServerPath() != local_server_path or server.host != local_server_host or server.port != local_server_port:
# local server settings have changed, let's stop the current local server.
if server.connected():
server.close_connection()
servers.stopLocalServer(wait=True)
#TODO: ASK if the user wants to start local server
if servers.startLocalServer(local_server_path, local_server_host, local_server_port):
thread = WaitForConnectionThread(local_server_host, local_server_port)
dialog = ProgressDialog(thread, "Local server", "Connecting...", "Cancel", busy=True, parent=self)
dialog.show()
dialog.exec_()
else:
QtGui.QMessageBox.critical(self, "Local server", "Could not start the local server process: {}".format(local_server_path))
# save the remote server preferences
servers.setLocalServer(local_server_path, local_server_host, local_server_port)
# save the remote server preferences
servers.setLocalServer(local_server_path, local_server_host, local_server_port)
servers.updateRemoteServers(self._remote_servers)
servers.save()

View File

@@ -23,7 +23,7 @@ from .qt import QtCore, QtGui
from .ui.preferences_dialog_ui import Ui_PreferencesDialog
from .pages.server_preferences_page import ServerPreferencesPage
from .pages.general_preferences_page import GeneralPreferencesPage
from .modules.dynamips import Dynamips
from .modules import MODULES
class PreferencesDialog(QtGui.QDialog, Ui_PreferencesDialog):
@@ -69,16 +69,16 @@ class PreferencesDialog(QtGui.QDialog, Ui_PreferencesDialog):
self.uiStackedWidget.addWidget(servers_page)
self._items.append(item)
# load Dynamips pages
#TODO: generic way to go thru all modules
for cls in Dynamips.preferencePages():
preferences_page = cls()
preferences_page.loadPreferences()
name = preferences_page.windowTitle()
item = QtGui.QListWidgetItem(name, self.uiListWidget)
item.setData(QtCore.Qt.UserRole, preferences_page)
self.uiStackedWidget.addWidget(preferences_page)
self._items.append(item)
# load module preference pages
for module in MODULES:
for cls in module.preferencePages():
preferences_page = cls()
preferences_page.loadPreferences()
name = preferences_page.windowTitle()
item = QtGui.QListWidgetItem(name, self.uiListWidget)
item.setData(QtCore.Qt.UserRole, preferences_page)
self.uiStackedWidget.addWidget(preferences_page)
self._items.append(item)
def _showPreferencesPageSlot(self, current, previous):
"""

View File

@@ -21,9 +21,9 @@ Handles the saving and loading of a topology.
"""
#import networkx as nx
from .qt import QtGui, QtCore
from .qt import QtCore
from .items.node_item import NodeItem
from .modules.dynamips import Dynamips
from .modules import MODULES
from .modules.module_error import ModuleError
from .utils.message_box import MessageBox
from .version import __version__
@@ -243,16 +243,19 @@ class Topology(object):
log.debug("loading node with ID {}".format(topology_node["id"]))
#TODO: node setup management with other modules
# create the node
try:
node_class = Dynamips.getNodeClass(topology_node["type"])
dynamips = Dynamips.instance()
node = dynamips.createNode(node_class)
node_module = None
for module in MODULES:
instance = module.instance()
node_class = module.getNodeClass(topology_node["type"])
if node_class:
node_module = instance
break
if not node_module:
raise ModuleError("Could not find any module for {}".format(topology_node["type"]))
node = node_module.createNode(node_class)
except ModuleError as e:
node_errors.append(str(e))
#QtGui.QMessageBox.critical(main_window, "Node creation", "{}".format(e))
continue
node.setId(topology_node["id"])

View File

@@ -21,7 +21,7 @@ Based on the ws4py websocket client.
"""
import json
import jsonrpc
from . import jsonrpc
from ws4py.client import WebSocketBaseClient
from .qt import QtCore

View File

@@ -0,0 +1 @@
ws4py

View File

@@ -63,11 +63,8 @@ setup(
'Natural Language :: English',
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
],
)