Support for binding addresses when loading a topology stable-0.8.2
authorJeremy
Thu Jun 28 21:36:05 2012 -0600 (11 months ago)
branchstable-0.8.2
changeset 12650fa1bdf2b415
parent 1264 92bcf5ce64c2
child 1266 368e7e046648
Support for binding addresses when loading a topology
GNS3 identifiers can be used as hostnames for Vbox nodes.
Track opened consoles in order to close them when deleting a node (as an option).
IPv6 support (with correct functions).
gns3.pyw
qemuwrapper/qemuwrapper.py
src/GNS3/Application.py
src/GNS3/Config/Defaults.py
src/GNS3/Console.py
src/GNS3/Dynagen/dynagen_vbox_lib.py
src/GNS3/Dynagen/dynamips_lib.py
src/GNS3/Dynagen/portTracker_lib.py
src/GNS3/Dynagen/qemu_lib.py
src/GNS3/DynagenSub.py
src/GNS3/HypervisorManager.py
src/GNS3/MACTableDialog.py
src/GNS3/Node/AbstractNode.py
src/GNS3/Node/AnyEmuDevice.py
src/GNS3/Node/AnyVBoxEmuDevice.py
src/GNS3/Node/IOSRouter.py
src/GNS3/QemuManager.py
src/GNS3/Scene.py
src/GNS3/Telnet.py
src/GNS3/Topology.py
src/GNS3/Ui/ConfigurationPages/Form_PreferencesVirtualBox.py
src/GNS3/Ui/ConfigurationPages/Form_PreferencesVirtualBox.ui
src/GNS3/Ui/ConfigurationPages/Page_PreferencesDynamips.py
src/GNS3/Ui/ConfigurationPages/Page_PreferencesVirtualBox.py
src/GNS3/VBoxManager.py
     1.1 --- a/gns3.pyw	Mon Jun 18 17:28:03 2012 -0600
     1.2 +++ b/gns3.pyw	Thu Jun 28 21:36:05 2012 -0600
     1.3 @@ -43,9 +43,8 @@
     1.4  if QtCore.PYQT_VERSION < 0x040500:
     1.5      raise RuntimeError, "Need PyQt v4.5 or higher, but got v%s" % QtCore.PYQT_VERSION_STR
     1.6  
     1.7 -if sys.version_info < (2, 5):
     1.8 -    #FIXME: need to check that, I think this is 2.6 at least
     1.9 -    raise RuntimeError, "Need Python 2.5 or higher"
    1.10 +if sys.version_info < (2, 6):
    1.11 +    raise RuntimeError, "Python 2.6 or higher is required"
    1.12  
    1.13  def exceptionHook(type, value, tb):
    1.14  
     2.1 --- a/qemuwrapper/qemuwrapper.py	Mon Jun 18 17:28:03 2012 -0600
     2.2 +++ b/qemuwrapper/qemuwrapper.py	Thu Jun 28 21:36:05 2012 -0600
     2.3 @@ -83,7 +83,10 @@
     2.4  __author__ = 'Thomas Pani and Jeremy Grossmann'
     2.5  __version__ = '0.8.3'
     2.6  
     2.7 -QEMU_PATH = "qemu-system-i386"
     2.8 +if platform.system() == 'Windows':
     2.9 +    QEMU_PATH = "qemu" # we still use Qemu 0.11.0 on Windows
    2.10 +else:
    2.11 +    QEMU_PATH = "qemu-system-i386"
    2.12  QEMU_IMG_PATH = "qemu-img"
    2.13  PORT = 10525
    2.14  IP = ""
    2.15 @@ -157,7 +160,7 @@
    2.16          command = self._build_command()
    2.17  
    2.18          qemu_cmd = " ".join(command)
    2.19 -        print "Command =>", qemu_cmd
    2.20 +        print "Starting Qemu =>", qemu_cmd
    2.21          try:
    2.22              if platform.system() == 'Windows':
    2.23                  shell = False
    2.24 @@ -175,7 +178,13 @@
    2.25          # give us some time to wait for Qemu to start
    2.26          time.sleep(1)
    2.27  
    2.28 -        print "    pid:", self.process.pid
    2.29 +        # check if Qemu has exited (not to say crashed!)
    2.30 +        self.process.poll()
    2.31 +        if self.process.returncode != None:
    2.32 +            print >> sys.stderr, "Qemu has exited with return code %i" % self.process.returncode
    2.33 +            return False
    2.34 +
    2.35 +        print "Qemu has successfully started with pid %i" % self.process.pid
    2.36  
    2.37          if platform.system() == 'Windows':
    2.38              print "Setting priority class to BELOW_NORMAL"
     3.1 --- a/src/GNS3/Application.py	Mon Jun 18 17:28:03 2012 -0600
     3.2 +++ b/src/GNS3/Application.py	Thu Jun 28 21:36:05 2012 -0600
     3.3 @@ -410,6 +410,7 @@
     3.4          else:
     3.5              confo.memory_limit = int(ConfDB().get("Dynamips/hypervisor_memory_usage_limit", 1024))
     3.6          confo.udp_incrementation = int(ConfDB().get("Dynamips/hypervisor_udp_incrementation", 100))
     3.7 +        confo.detected_version = ConfDB().get('Dynamips/detected_version', unicode(''))
     3.8          confo.import_use_HypervisorManager = ConfDB().value("Dynamips/hypervisor_manager_import", QVariant(True)).toBool()
     3.9          confo.HypervisorManager_binding = ConfDB().get('Dynamips/hypervisor_manager_binding', unicode('127.0.0.1'))
    3.10          confo.allocateHypervisorPerIOS = ConfDB().value("Dynamips/allocate_hypervisor_per_IOS", QVariant(True)).toBool()
    3.11 @@ -663,6 +664,7 @@
    3.12          c.set('Dynamips/dynamips_jitsharing', confo.jitsharing)
    3.13          c.set('Dynamips/dynamips_mmap', confo.mmap)
    3.14          c.set('Dynamips/hypervisor_memory_usage_limit', confo.memory_limit)
    3.15 +        c.set('Dynamips/detected_version', confo.detected_version)
    3.16          c.set('Dynamips/hypervisor_udp_incrementation', confo.udp_incrementation)
    3.17          c.set('Dynamips/hypervisor_manager_import', confo.import_use_HypervisorManager)
    3.18          c.set('Dynamips/allocate_hypervisor_per_IOS', confo.allocateHypervisorPerIOS)
     4.1 --- a/src/GNS3/Config/Defaults.py	Mon Jun 18 17:28:03 2012 -0600
     4.2 +++ b/src/GNS3/Config/Defaults.py	Thu Jun 28 21:36:05 2012 -0600
     4.3 @@ -474,6 +474,7 @@
     4.4      'mmap': True,
     4.5      'memory_limit': 512,
     4.6      'udp_incrementation': 100,
     4.7 +    'detected_version': '',
     4.8      'import_use_HypervisorManager': True,
     4.9      'allocateHypervisorPerIOS': True,
    4.10      'HypervisorManager_binding': u'localhost',
    4.11 @@ -493,6 +494,7 @@
    4.12      'mmap': bool,
    4.13      'memory_limit': int,
    4.14      'udp_incrementation': int,
    4.15 +    'detected_version': unicode,
    4.16      'import_use_HypervisorManager': bool,
    4.17      'allocateHypervisorPerIOS': bool,
    4.18      'HypervisorManager_binding': unicode,
     5.1 --- a/src/GNS3/Console.py	Mon Jun 18 17:28:03 2012 -0600
     5.2 +++ b/src/GNS3/Console.py	Thu Jun 28 21:36:05 2012 -0600
     5.3 @@ -196,9 +196,9 @@
     5.4                      globals.GApp.mainWindow.treeWidget_TopologySummary.changeNodeStatus(node.hostname, 'running')
     5.5          except lib.DynamipsError, msg:
     5.6              QtGui.QMessageBox.critical(self, translate("Console", "%s: Dynamips error") % node.hostname,  unicode(msg))
     5.7 -        except lib.DynamipsWarning,  msg:
     5.8 +        except lib.DynamipsWarning, msg:
     5.9              QtGui.QMessageBox.warning(self, translate("Console", "%s: Dynamips warning") % node.hostname,  unicode(msg))
    5.10 -        except (lib.DynamipsErrorHandled,  socket.error):
    5.11 +        except (lib.DynamipsErrorHandled, socket.error):
    5.12              QtGui.QMessageBox.critical(self, translate("Console", "%s: Dynamips error") % node.hostname, translate("Console", "Connection lost"))
    5.13  
    5.14      def do_stop(self, args):
     6.1 --- a/src/GNS3/Dynagen/dynagen_vbox_lib.py	Mon Jun 18 17:28:03 2012 -0600
     6.2 +++ b/src/GNS3/Dynagen/dynagen_vbox_lib.py	Thu Jun 28 21:36:05 2012 -0600
     6.3 @@ -58,9 +58,9 @@
     6.4  msg = "WELCOME to dynagen_vbox_lib.py"
     6.5  debugmsg(2, msg)
     6.6  
     6.7 -from socket import socket, AF_INET, AF_INET6, SOCK_STREAM
     6.8  from dynamips_lib import NIO_udp, send, dowarning, debug, DynamipsError, validate_connect, Bridge, DynamipsVerError, get_reverse_udp_nio, Router, FRSW, ATMSW, ETHSW, DynamipsWarning
     6.9  import random
    6.10 +import socket
    6.11  
    6.12  #version = "0.11.0.111211"
    6.13  (MAJOR, MINOR, SUB) = (0, 8, 2)
    6.14 @@ -121,17 +121,11 @@
    6.15          self.host = name
    6.16  
    6.17          #connect to VBox Wrapper
    6.18 -        if name.__contains__(':'):
    6.19 -            # IPv6 address support
    6.20 -            self.s = socket(AF_INET6, SOCK_STREAM)
    6.21 -        else:
    6.22 -            self.s = socket(AF_INET, SOCK_STREAM)
    6.23 -        self.s.setblocking(0)
    6.24 -        self.s.settimeout(300)
    6.25 +        timeout = 60.0
    6.26          self._type = 'vboxwrapper'
    6.27          if not NOSEND:
    6.28              try:
    6.29 -                self.s.connect((self.host, self.port))
    6.30 +                self.s = socket.create_connection((self.host, self.port), timeout)
    6.31              except:
    6.32                  raise DynamipsError, '101-Could not connect to vboxwrapper at %s:%i' % (self.host, self.port)
    6.33          #version checking
     7.1 --- a/src/GNS3/Dynagen/dynamips_lib.py	Mon Jun 18 17:28:03 2012 -0600
     7.2 +++ b/src/GNS3/Dynagen/dynamips_lib.py	Thu Jun 28 21:36:05 2012 -0600
     7.3 @@ -25,13 +25,13 @@
     7.4  #This file is a client, that connects to 'dynamips' server.
     7.5  #This is part of Dynagen-GNS3.
     7.6  
     7.7 -from socket import socket, AF_INET, AF_INET6, SOCK_STREAM
     7.8  import portTracker_lib as tracker
     7.9  import sys
    7.10  import os
    7.11  import re
    7.12  import copy
    7.13  import time
    7.14 +import socket
    7.15  
    7.16  #version = "0.11.0.101003"
    7.17  # Minimum version of dynamips required. Currently 0.2.8-RC1 (due to change to
    7.18 @@ -248,19 +248,12 @@
    7.19                   default is 3 seconds
    7.20      """
    7.21  
    7.22 -    def __init__(self, host, port=7200, timeout=500):
    7.23 -        if host.__contains__(':'):
    7.24 -            # IPv6 address support
    7.25 -            self.s = socket(AF_INET6, SOCK_STREAM)
    7.26 -        else:
    7.27 -            self.s = socket(AF_INET, SOCK_STREAM)
    7.28 -        self.s.setblocking(0)
    7.29 -        self.s.settimeout(timeout)
    7.30 +    def __init__(self, host, port=7200, timeout=60.0):
    7.31          self.configchange = False
    7.32          self.__type = 'dynamips'
    7.33          if not NOSEND:
    7.34              try:
    7.35 -                self.s.connect((host, port))
    7.36 +                self.s = socket.create_connection((host, port), timeout)
    7.37              except:
    7.38                  raise DynamipsError, 'Could not connect to server'
    7.39          self.__devices = []
    7.40 @@ -4517,7 +4510,7 @@
    7.41              except KeyError:
    7.42                  return None
    7.43              except AttributeError, e:
    7.44 -                raise DynamipsError, 'nothing connected to port %s, it does not exist' % (port1)
    7.45 +                raise DynamipsError, 'nothing connected to port %s, it does not exist' % (port)
    7.46  
    7.47          if isinstance(nio, NIO):
    7.48              # Set the NETIO for this port
     8.1 --- a/src/GNS3/Dynagen/portTracker_lib.py	Mon Jun 18 17:28:03 2012 -0600
     8.2 +++ b/src/GNS3/Dynagen/portTracker_lib.py	Thu Jun 28 21:36:05 2012 -0600
     8.3 @@ -80,9 +80,7 @@
     8.4                          s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
     8.5                      else:
     8.6                          s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     8.7 -                    #FIXME: for now bind on 0.0.0.0 (default for dynamips. A bug inside Dynamips prevent us to bind it to a specific address!)
     8.8 -                    #s.bind((host, port))
     8.9 -                    s.bind(('0.0.0.0', port))
    8.10 +                    s.bind((host, port))
    8.11                  except socket.error, e:
    8.12                      # Not available
    8.13                      if (max_port != 0):
     9.1 --- a/src/GNS3/Dynagen/qemu_lib.py	Mon Jun 18 17:28:03 2012 -0600
     9.2 +++ b/src/GNS3/Dynagen/qemu_lib.py	Thu Jun 28 21:36:05 2012 -0600
     9.3 @@ -59,10 +59,10 @@
     9.4  msg = "WELCOME to qemu_lib.py"
     9.5  debugmsg(2, msg)
     9.6  
     9.7 -from socket import socket, AF_INET, AF_INET6, SOCK_STREAM
     9.8  from dynamips_lib import NIO_udp, send, dowarning, debug, DynamipsError, validate_connect, Bridge, DynamipsVerError, get_reverse_udp_nio, Router, FRSW, ATMSW, ETHSW, DynamipsWarning
     9.9  import random
    9.10  import hashlib
    9.11 +import socket
    9.12  
    9.13  #version = "0.11.0.091411"
    9.14  (MAJOR, MINOR, SUB, RCVER) = (0, 2, 1, .1)
    9.15 @@ -123,17 +123,11 @@
    9.16          self.host = name
    9.17  
    9.18          #connect to Qemu Wrapper
    9.19 -        if name.__contains__(':'):
    9.20 -            # IPv6 address support
    9.21 -            self.s = socket(AF_INET6, SOCK_STREAM)
    9.22 -        else:
    9.23 -            self.s = socket(AF_INET, SOCK_STREAM)
    9.24 -        self.s.setblocking(0)
    9.25 -        self.s.settimeout(300)
    9.26 +        timeout = 60.0
    9.27          self._type = 'qemuwrapper'
    9.28          if not NOSEND:
    9.29              try:
    9.30 -                self.s.connect((self.host, self.port))
    9.31 +                self.s = socket.create_connection((self.host, self.port), timeout)
    9.32              except:
    9.33                  raise DynamipsError, 'Could not connect to qemuwrapper at %s:%i' % (self.host, self.port)
    9.34          #version checking
    9.35 @@ -174,7 +168,6 @@
    9.36  
    9.37      def close(self):
    9.38          """ Close the connection to the Qemuwrapper (but leave it running)"""
    9.39 -        debugmsg(2, "Qemu::close(%s, %s)" % (unicode(name), str(port)))
    9.40  
    9.41          self.s.close()
    9.42  
    10.1 --- a/src/GNS3/DynagenSub.py	Mon Jun 18 17:28:03 2012 -0600
    10.2 +++ b/src/GNS3/DynagenSub.py	Thu Jun 28 21:36:05 2012 -0600
    10.3 @@ -26,7 +26,7 @@
    10.4  import GNS3.Globals as globals
    10.5  from GNS3.Dynagen.dynagen import Dynagen, DEVICETUPLE
    10.6  from GNS3.Utils import translate, debug, getWindowsInterfaces
    10.7 -from PyQt4 import QtCore, QtGui
    10.8 +from PyQt4 import QtCore, QtGui, QtNetwork
    10.9  
   10.10  def debugmsg(level, message):
   10.11      if debuglevel == 0:
   10.12 @@ -43,6 +43,8 @@
   10.13          Dynagen.__init__(self)
   10.14          self.gns3_data = None
   10.15          self.rpcap_mapping = {}
   10.16 +        self.local_addresses = map(lambda addr: unicode(addr.toString()), QtNetwork.QNetworkInterface.allAddresses())
   10.17 +        self.local_addresses += ['0.0.0.0', '127.0.0.1', 'localhost', '::1', '0:0:0:0:0:0:0:1', QtNetwork.QHostInfo.localHostName()]
   10.18  
   10.19      def check_replace_GUID_NIO(self, filename):
   10.20          """ Check and replace non-existing GUID (network interface ID) on Windows
   10.21 @@ -173,11 +175,10 @@
   10.22                  if ':' in host:
   10.23                      # unpack the server and port
   10.24                      # controlPort is ignored
   10.25 -                    #(host, controlPort) = host.split(':')  # What if we provide IPv6 ???
   10.26                      controlPort = host.split(':')[-1]
   10.27                      host = self.getHost(host)
   10.28 -                if emulator == 'qemu' and (host == globals.GApp.systconf['qemu'].QemuManager_binding or host == 'localhost') and globals.GApp.systconf['qemu'].enable_QemuManager:
   10.29 -                    globals.GApp.QemuManager.startQemu(int(controlPort))
   10.30 +                if emulator == 'qemu' and globals.GApp.systconf['qemu'].enable_QemuManager and globals.GApp.systconf['vbox'].import_use_QemuManager and host in self.local_addresses:
   10.31 +                    globals.GApp.QemuManager.startQemu(int(controlPort), host)
   10.32                      debugmsg(2, "DynagenSub::open_config(), entered QemuManager")
   10.33  
   10.34                      # Check if this is a relative working directory path and convert to an absolute path if necessary
   10.35 @@ -294,9 +295,9 @@
   10.36                                  print translate("DynagenSub", "Local PIX image %s cannot be found, use image %s instead") \
   10.37                                  % (unicode(device['image']), image_name)
   10.38                                  device['image'] = image_name
   10.39 -                elif emulator == 'vbox' and (host == globals.GApp.systconf['vbox'].VBoxManager_binding or host == 'localhost') and globals.GApp.systconf['vbox'].enable_VBoxManager:
   10.40 +                elif emulator == 'vbox' and globals.GApp.systconf['vbox'].enable_VBoxManager and globals.GApp.systconf['vbox'].import_use_VBoxManager and host in self.local_addresses:
   10.41                      debugmsg(2, "DynagenSub::open_config(), entered VBoxManager")
   10.42 -                    globals.GApp.VBoxManager.startVBox(int(controlPort))
   10.43 +                    globals.GApp.VBoxManager.startVBox(int(controlPort), host)
   10.44  
   10.45                      # Check if this is a relative working directory path and convert to an absolute path if necessary
   10.46                      if server['workingdir']:
   10.47 @@ -327,8 +328,8 @@
   10.48                      controlPort = '7200'
   10.49  
   10.50                  # need to start local hypervisors
   10.51 -                if (server.host == globals.GApp.systconf['dynamips'].HypervisorManager_binding or server.host == 'localhost') and \
   10.52 -                    globals.GApp.HypervisorManager and globals.GApp.systconf['dynamips'].import_use_HypervisorManager:
   10.53 +
   10.54 +                if globals.GApp.HypervisorManager and globals.GApp.systconf['dynamips'].import_use_HypervisorManager and server.host in self.local_addresses:
   10.55                      debugmsg(2, "DynagenSub::open_config(), entered Dynamips HypervisorManager")
   10.56  
   10.57                      # update server.host and server.name to match with Hypervisor Manager Binding configuration,
   10.58 @@ -339,17 +340,16 @@
   10.59  #                        server.name = server.host + ':' + controlPort
   10.60  
   10.61                      debug("Start hypervisor on port: " + str(controlPort))
   10.62 -                    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   10.63 -                    s.setblocking(0)
   10.64 -                    s.settimeout(300)
   10.65 +
   10.66                      try:
   10.67 -                        s.connect(('localhost', int(controlPort)))
   10.68 +                        s = socket.create_connection((server.host, int(controlPort)), 60.0)
   10.69                          s.close()
   10.70                          print "Warning: a process is already running on port %i, please consider closing it or killing it as this may negatively impact your topology" % int(controlPort)
   10.71                      except:
   10.72 -                        s.close()
   10.73 -                    hypervisor = globals.GApp.HypervisorManager.startNewHypervisor(int(controlPort), processcheck=False)
   10.74 -                    globals.GApp.HypervisorManager.waitHypervisor(hypervisor)
   10.75 +                        pass
   10.76 +
   10.77 +                    hypervisor = globals.GApp.HypervisorManager.startNewHypervisor(int(controlPort), binding=server.host, processcheck=False)
   10.78 +                    globals.GApp.HypervisorManager.waitHypervisor(hypervisor, binding=server.host)
   10.79  
   10.80                      # Check if this is a relative working directory path and convert to an absolute path if necessary
   10.81                      if server['workingdir']:
    11.1 --- a/src/GNS3/HypervisorManager.py	Mon Jun 18 17:28:03 2012 -0600
    11.2 +++ b/src/GNS3/HypervisorManager.py	Thu Jun 28 21:36:05 2012 -0600
    11.3 @@ -19,13 +19,13 @@
    11.4  # http://www.gns3.net/contact
    11.5  #
    11.6  
    11.7 -import time, os, sys
    11.8 +import time, os, socket
    11.9  import GNS3.Globals as globals
   11.10  import GNS3.Dynagen.dynamips_lib as lib
   11.11 -from socket import socket, AF_INET, SOCK_STREAM
   11.12  from PyQt4 import QtCore, QtGui
   11.13  from GNS3.Utils import translate, debug, killAll
   11.14  from GNS3.Node.IOSRouter import IOSRouter
   11.15 +from distutils.version import LooseVersion
   11.16  
   11.17  class HypervisorManager(object):
   11.18      """ HypervisorManager class
   11.19 @@ -56,10 +56,13 @@
   11.20          globals.hypervisor_baseport = self.dynamips.port
   11.21          globals.GApp.dynagen.globaludp = self.dynamips.baseUDP
   11.22  
   11.23 -    def startNewHypervisor(self, port, processcheck=True):
   11.24 +    def startNewHypervisor(self, port, binding=None, processcheck=True):
   11.25          """ Create a new dynamips process and start it
   11.26          """
   11.27  
   11.28 +        if binding == None:
   11.29 +            binding = self.dynamips.HypervisorManager_binding
   11.30 +
   11.31          proc = QtCore.QProcess(globals.GApp.mainWindow)
   11.32  
   11.33          if self.hypervisor_wd:
   11.34 @@ -68,16 +71,14 @@
   11.35  
   11.36          if processcheck:
   11.37              # test if a hypervisor is already running on this port
   11.38 -            s = socket(AF_INET, SOCK_STREAM)
   11.39 -            s.setblocking(0)
   11.40 -            s.settimeout(300)
   11.41 +            timeout = 60.0
   11.42              try:
   11.43                  #FIXME: replace with bind() for faster process?
   11.44 -                s.connect(('localhost', port))
   11.45 +                s = socket.create_connection((binding, port), timeout)
   11.46                  s.close()
   11.47  
   11.48                  reply = QtGui.QMessageBox.question(globals.GApp.mainWindow, translate("HypervisorManager", "Hypervisor Manager"),
   11.49 -                                                   translate("HypervisorManager", "Apparently an hypervisor is already running on port %i, would you like to kill all Dynamips processes?") % port,
   11.50 +                                                   translate("HypervisorManager", "Apparently an hypervisor is already running on %s port %i, would you like to kill all Dynamips processes?") % (binding, port),
   11.51                                                     QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
   11.52                  if reply == QtGui.QMessageBox.Yes:
   11.53                      killAll(os.path.basename(self.hypervisor_path))
   11.54 @@ -92,26 +93,36 @@
   11.55                      port = globals.hypervisor_baseport
   11.56  
   11.57                  #FIXME: replace with bind() for faster process?
   11.58 -                s.connect(('localhost', port))
   11.59 +                s = socket.create_connection((binding, port), timeout)
   11.60                  s.close()
   11.61  
   11.62                  QtGui.QMessageBox.critical(globals.GApp.mainWindow, translate("HypervisorManager", "Hypervisor Manager"),
   11.63 -                                           translate("HypervisorManager", "A program is still running on port %i, you will have to stop it manually or change port settings") % port)
   11.64 +                                           translate("HypervisorManager", "A program is still running on %s port %i, you will have to stop it manually or change port settings") % (binding, port))
   11.65  
   11.66                  globals.hypervisor_baseport += 1
   11.67                  return None
   11.68              except:
   11.69 -                s.close()
   11.70 +                pass
   11.71  
   11.72 -        # start dynamips in hypervisor mode (-H)
   11.73 -        #FIXME: Dynamips ignores this format: -H <IP address:port> (bug inside Dynamips, for now binds on 0.0.0.0)
   11.74 -        proc.start(self.hypervisor_path,  ['-H', str(port)])
   11.75 +        try:
   11.76 +            # start dynamips in hypervisor mode (-H)
   11.77 +            # Dynamips version 0.2.8-RC3 and before cannot accept a specific port when binding on a chosen address with param -H <IP address:port> (bug is inside Dynamips).
   11.78 +            if self.dynamips.detected_version and LooseVersion(self.dynamips.detected_version) > '0.2.8-RC3':
   11.79 +                debug("Starting Dynamips with -H %s:%i" % (binding, port))
   11.80 +                proc.start(self.hypervisor_path,  ['-H', binding + ':' + str(port)])
   11.81 +            else:
   11.82 +                debug("Starting Dynamips with -H %i (old way with Dynamips version 0.2.8-RC3 and before)" % port)
   11.83 +                proc.start(self.hypervisor_path,  ['-H', str(port)])
   11.84 +        except:
   11.85 +            debug('Exception with LooseVersion()')
   11.86 +            proc.start(self.hypervisor_path,  ['-H', str(port)])
   11.87  
   11.88          if proc.waitForStarted() == False:
   11.89 -            QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'Hypervisor Manager', translate("HypervisorManager", "Can't start Dynamips on port %i") % port)
   11.90 +            QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'Hypervisor Manager', translate("HypervisorManager", "Can't start Dynamips on %s port %i") % (binding, port))
   11.91              return None
   11.92  
   11.93 -        hypervisor = {'port': port,
   11.94 +        hypervisor = {'host': binding,
   11.95 +                      'port': port,
   11.96                        'proc_instance': proc,
   11.97                        'load': 0,
   11.98                        'image_ref': ''}
   11.99 @@ -119,22 +130,23 @@
  11.100          self.hypervisors.append(hypervisor)
  11.101          return hypervisor
  11.102  
  11.103 -    def waitHypervisor(self, hypervisor):
  11.104 +    def waitHypervisor(self, hypervisor, binding=None):
  11.105          """ Wait the hypervisor until it accepts connections
  11.106          """
  11.107 +        
  11.108 +        if binding == None:
  11.109 +            binding = self.dynamips.HypervisorManager_binding
  11.110  
  11.111          last_exception = None
  11.112          # give 15 seconds to the hypervisor to accept connections
  11.113          count = 15
  11.114          progress = None
  11.115 +        timeout = 60.0
  11.116          connection_success = False
  11.117 -        debug("Hypervisor manager: connect on " + str(hypervisor['port']))
  11.118 -        for nb in range(count + 1):
  11.119 -            s = socket(AF_INET, SOCK_STREAM)
  11.120 -            s.setblocking(0)
  11.121 -            s.settimeout(300)
  11.122 +        debug("Hypervisor manager: connecting on %s:%i" % (binding, hypervisor['port']))
  11.123 +        for nb in range(count + 1):            
  11.124              if nb == 3:
  11.125 -                progress = QtGui.QProgressDialog(translate("HypervisorManager", "Connecting to a hypervisor on port %i ...") % hypervisor['port'],
  11.126 +                progress = QtGui.QProgressDialog(translate("HypervisorManager", "Connecting to an hypervisor on %s port %i ...") % (binding, hypervisor['port']),
  11.127                                                   translate("HypervisorManager", "Abort"), 0, count, globals.GApp.mainWindow)
  11.128                  progress.setMinimum(1)
  11.129                  progress.setWindowModality(QtCore.Qt.WindowModal)
  11.130 @@ -146,13 +158,12 @@
  11.131                      progress.reset()
  11.132                      break
  11.133              try:
  11.134 -                s.connect(('localhost', hypervisor['port']))
  11.135 +                s = socket.create_connection((binding, hypervisor['port']), timeout)
  11.136              except Exception, ex:
  11.137 -                s.close()
  11.138                  time.sleep(1)
  11.139                  last_exception = ex
  11.140                  continue
  11.141 -            debug("Hypervisor manager: hypervisor on port " +  str(hypervisor['port']) + " started")
  11.142 +            debug("Hypervisor manager: connected to hypervisor on %s port %i" % (binding, hypervisor['port']))
  11.143              connection_success = True
  11.144              break
  11.145  
  11.146 @@ -164,7 +175,7 @@
  11.147              if not last_exception:
  11.148                  last_exception = 'Unknown problem'
  11.149              QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'Hypervisor Manager',
  11.150 -                                       translate("HypervisorManager", "Can't connect to the hypervisor on port %i: %s") % (hypervisor['port'], last_exception))
  11.151 +                                       translate("HypervisorManager", "Can't connect to the hypervisor on %s port %i: %s") % (binding, hypervisor['port'], last_exception))
  11.152              hypervisor['proc_instance'].close()
  11.153              self.hypervisors.remove(hypervisor)
  11.154              return False
  11.155 @@ -184,10 +195,10 @@
  11.156                      if self.dynamips.allocateHypervisorPerIOS and hypervisor['image_ref'] != node.image_reference:
  11.157                          continue
  11.158                      hypervisor['load'] += node.default_ram
  11.159 -                debug('Hypervisor manager: allocates an already started hypervisor (port: ' + str(hypervisor['port']) + ')')
  11.160 -                if not globals.GApp.dynagen.dynamips.has_key(self.dynamips.HypervisorManager_binding + ':' + str(hypervisor['port'])):
  11.161 -                    globals.GApp.dynagen.create_dynamips_hypervisor(self.dynamips.HypervisorManager_binding, hypervisor['port'])
  11.162 -                dynamips_hypervisor = globals.GApp.dynagen.dynamips[self.dynamips.HypervisorManager_binding + ':' + str(hypervisor['port'])]
  11.163 +                debug("Hypervisor manager: allocates an already started hypervisor on %s port %i" % (hypervisor['host'], hypervisor['port']))
  11.164 +                if not globals.GApp.dynagen.dynamips.has_key(hypervisor['host'] + ':' + str(hypervisor['port'])):
  11.165 +                    globals.GApp.dynagen.create_dynamips_hypervisor(hypervisor['host'], hypervisor['port'])
  11.166 +                dynamips_hypervisor = globals.GApp.dynagen.dynamips[hypervisor['host'] + ':' + str(hypervisor['port'])]
  11.167                  node.set_hypervisor(dynamips_hypervisor)
  11.168                  return hypervisor
  11.169  
  11.170 @@ -214,14 +225,14 @@
  11.171                                            translate("HypervisorManager", "Working directory %s seems to not exist or be writable, please check") % self.hypervisor_wd)
  11.172              globals.GApp.dynagen.defaults_config['workingdir'] = self.hypervisor_wd
  11.173          try:
  11.174 -            dynamips_hypervisor = globals.GApp.dynagen.create_dynamips_hypervisor(self.dynamips.HypervisorManager_binding, hypervisor['port'])
  11.175 +            dynamips_hypervisor = globals.GApp.dynagen.create_dynamips_hypervisor(hypervisor['host'], hypervisor['port'])
  11.176          except:
  11.177              dynamips_hypervisor = None
  11.178          if not dynamips_hypervisor:
  11.179              QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'Hypervisor Manager',
  11.180 -                                       translate("HypervisorManager", "Can't set up hypervisor on port %i, please check the settings (writable working directory ...)") % hypervisor['port'])
  11.181 -            if globals.GApp.dynagen.dynamips.has_key(self.dynamips.HypervisorManager_binding + ':' + str(hypervisor['port'])):
  11.182 -                del globals.GApp.dynagen.dynamips[self.dynamips.HypervisorManager_binding + ':' + str(hypervisor['port'])]
  11.183 +                                       translate("HypervisorManager", "Can't set up hypervisor on %s port %i, please check the settings (writable working directory ...)") % (hypervisor['host'], hypervisor['port']))
  11.184 +            if globals.GApp.dynagen.dynamips.has_key(hypervisor['host'] + ':' + str(hypervisor['port'])):
  11.185 +                del globals.GApp.dynagen.dynamips[hypervisor['host'] + ':' + str(hypervisor['port'])]
  11.186              hypervisor['proc_instance'].close()
  11.187              hypervisor['proc_instance'] = None
  11.188              count = 0
  11.189 @@ -231,7 +242,7 @@
  11.190                      break
  11.191                  count += 1
  11.192              return None
  11.193 -        debug("Hypervisor manager: create a new hypervisor on port " + str(hypervisor['port']))
  11.194 +        debug("Hypervisor manager: create a new hypervisor on %s port %i" % (hypervisor['host'], hypervisor['port']))
  11.195          globals.GApp.dynagen.update_running_config()
  11.196          dynamips_hypervisor.configchange = True
  11.197          dynamips_hypervisor.udp = globals.GApp.dynagen.globaludp
  11.198 @@ -243,30 +254,31 @@
  11.199          node.set_hypervisor(dynamips_hypervisor)
  11.200          return hypervisor
  11.201  
  11.202 -    def unallocateHypervisor(self, node, port):
  11.203 +    def unallocateHypervisor(self, node, host, port):
  11.204          """ Unallocate a hypervisor for a given node
  11.205          """
  11.206  
  11.207          for hypervisor in self.hypervisors:
  11.208 -            if hypervisor['port'] == int(port):
  11.209 -                debug("Hypervisor manager: unallocate hypervisor (port: " + str(port) + ") for node " + node.hostname)
  11.210 +            if hypervisor['host'] == host and hypervisor['port'] == int(port):
  11.211 +                debug("Hypervisor manager: unallocate hypervisor on %s port %i for node %s" % (host, port, node.hostname))
  11.212                  hypervisor['load'] -= node.default_ram
  11.213                  if hypervisor['load'] <= 0:
  11.214                      hypervisor['load'] = 0
  11.215                  break
  11.216  
  11.217 -    def changeHypervisorLoad(self, node, port, old_default_ram):
  11.218 -        """ Change the hypervisor RAM load for a given node
  11.219 -        """
  11.220 -
  11.221 -        for hypervisor in self.hypervisors:
  11.222 -            if hypervisor['port'] == int(port):
  11.223 -                debug("Hypervisor manager: change hypervisor load (port: " + str(port) + ") for node " + node.hostname)
  11.224 -                hypervisor['load'] -= old_default_ram
  11.225 -                if hypervisor['load'] <= 0:
  11.226 -                    hypervisor['load'] = 0
  11.227 -                hypervisor['load'] += node.default_ram
  11.228 -                break
  11.229 +#FIXME: useless?
  11.230 +#    def changeHypervisorLoad(self, node, port, old_default_ram):
  11.231 +#        """ Change the hypervisor RAM load for a given node
  11.232 +#        """
  11.233 +#
  11.234 +#        for hypervisor in self.hypervisors:
  11.235 +#            if hypervisor['port'] == int(port):
  11.236 +#                debug("Hypervisor manager: change hypervisor load on %s port %i" % (self.dynamips.HypervisorManager_binding, port, node.hostname))
  11.237 +#                hypervisor['load'] -= old_default_ram
  11.238 +#                if hypervisor['load'] <= 0:
  11.239 +#                    hypervisor['load'] = 0
  11.240 +#                hypervisor['load'] += node.default_ram
  11.241 +#                break
  11.242  
  11.243      def getHypervisor(self, port):
  11.244          """ Get a hypervisor from the hypervisor manager
  11.245 @@ -288,14 +300,14 @@
  11.246              if isinstance(hypervisor, lib.Dynamips):
  11.247                  try:
  11.248                      if globals.GApp.dynagen.dynamips.has_key(hypervisor.host + ':' + hypervisor.port):
  11.249 -                        debug("Hypervisor manager: reset and close hypervisor on port " + str(hypervisor['port']))
  11.250 +                        debug("Hypervisor manager: reset and close hypervisor on %s port %i" % (hypervisor['host'], hypervisor['port']))
  11.251                          hypervisor.reset()
  11.252                          hypervisor.close()
  11.253                          del globals.GApp.dynagen.dynamips[hypervisor.host + ':' + hypervisor.port]
  11.254                  except:
  11.255                      continue
  11.256          for hypervisor in self.hypervisors:
  11.257 -            debug("Hypervisor manager: close hypervisor on port " + str(hypervisor['port']))
  11.258 +            debug("Hypervisor manager: close hypervisor on %s port %i" % (hypervisor['host'], hypervisor['port']))
  11.259              hypervisor['proc_instance'].terminate()
  11.260              time.sleep(0.5)
  11.261              hypervisor['proc_instance'].close()
  11.262 @@ -311,24 +323,29 @@
  11.263  
  11.264          if self.hypervisor_wd:
  11.265              # set the working directory
  11.266 -            proc.setWorkingDirectory(self.hypervisor_wd)
  11.267 -        # start dynamips in hypervisor mode (-H)
  11.268 -        #FIXME: Dynamips ignores this format: -H <IP address:port> (bug inside Dynamips, for now binds on 0.0.0.0)
  11.269 -        proc.start(self.hypervisor_path,  ['-H', str(port)])
  11.270 +            proc.setWorkingDirectory(self.hypervisor_wd)        
  11.271 +        try:
  11.272 +            # start dynamips in hypervisor mode (-H)
  11.273 +            # Dynamips version 0.2.8-RC3 and before cannot accept a specific port when binding on a chosen address with param -H <IP address:port> (bug is inside Dynamips).
  11.274 +            if self.dynamips.detected_version and LooseVersion(self.dynamips.detected_version) > '0.2.8-RC3':
  11.275 +                proc.start(self.hypervisor_path,  ['-H', self.dynamips.HypervisorManager_binding + ':' + str(port)])
  11.276 +            else:
  11.277 +                proc.start(self.hypervisor_path,  ['-H', str(port)])
  11.278 +        except:
  11.279 +            debug('Exception with LooseVersion')
  11.280 +            proc.start(self.hypervisor_path,  ['-H', str(port)])
  11.281 +
  11.282          if proc.waitForStarted() == False:
  11.283              return False
  11.284  
  11.285          # give 5 seconds to the hypervisor to accept connections
  11.286          count = 5
  11.287          connection_success = False
  11.288 +        timeout = 60.0
  11.289          for nb in range(count + 1):
  11.290 -            s = socket(AF_INET, SOCK_STREAM)
  11.291 -            s.setblocking(0)
  11.292 -            s.settimeout(300)
  11.293              try:
  11.294 -                s.connect(('localhost', port))
  11.295 +                s = socket.create_connection((self.dynamips.HypervisorManager_binding, port), timeout)
  11.296              except:
  11.297 -                s.close()
  11.298                  time.sleep(1)
  11.299                  continue
  11.300              connection_success = True
  11.301 @@ -345,8 +362,8 @@
  11.302          """ Show hypervisors port & load
  11.303          """
  11.304  
  11.305 -        print "Memory usage limit per hypervisor : " + str(self.dynamips.memory_limit) + " MB"
  11.306 -        print '%-10s %-10s' % ('Port','Memory load')
  11.307 +        print "Memory usage limit per hypervisor: %i MB" % self.dynamips.memory_limit
  11.308 +        print '%-10s %-10s %-10s' % ('Host/Binding','Port','Memory load')
  11.309          for hypervisor in self.hypervisors:
  11.310 -            print '%-10s %-10s' % (hypervisor['port'], str(hypervisor['load']) + ' MB')
  11.311 +            print '%-10s %-10s %-10s' % (hypervisor['host'], hypervisor['port'], str(hypervisor['load']) + ' MB')
  11.312  
    12.1 --- a/src/GNS3/MACTableDialog.py	Mon Jun 18 17:28:03 2012 -0600
    12.2 +++ b/src/GNS3/MACTableDialog.py	Thu Jun 28 21:36:05 2012 -0600
    12.3 @@ -29,9 +29,9 @@
    12.4      """ MACTableDialog class
    12.5      """
    12.6  
    12.7 -    def __init__(self, node):
    12.8 +    def __init__(self, node, parent=None):
    12.9  
   12.10 -        QtGui.QDialog.__init__(self)
   12.11 +        QtGui.QDialog.__init__(self, parent)
   12.12          self.setupUi(self)
   12.13  
   12.14          self.connect(self.pushButtonRefresh, QtCore.SIGNAL('clicked()'), self.__refreshTable)
    13.1 --- a/src/GNS3/Node/AbstractNode.py	Mon Jun 18 17:28:03 2012 -0600
    13.2 +++ b/src/GNS3/Node/AbstractNode.py	Thu Jun 28 21:36:05 2012 -0600
    13.3 @@ -82,10 +82,29 @@
    13.4          if globals.GApp.systconf['general'].term_close_on_delete:
    13.5              # closing terminal programs
    13.6              for console in self.consoleProcesses:
    13.7 -                if not console.returncode:
    13.8 +                console.poll()
    13.9 +                if console.returncode == None:
   13.10 +                    # the process hasn't returned yet (still active)
   13.11                      debug("Sending terminate signal to terminal program (pid %i)" % console.pid)
   13.12 -                    console.terminate()
   13.13 +                    try:
   13.14 +                        console.terminate()
   13.15 +                    except:
   13.16 +                        debug("Error while sending the signal to terminal program (pid %i)" % console.pid)
   13.17 +                        continue
   13.18          self.consoleProcesses = []
   13.19 +        
   13.20 +    def clearClosedConsoles(self):
   13.21 +        """ Refresh the list of opened terminal programs.
   13.22 +        """
   13.23 +
   13.24 +        updated_list = []
   13.25 +        for console in self.consoleProcesses:
   13.26 +            console.poll()
   13.27 +            if console.returncode == None:
   13.28 +                # the process hasn't returned yet (still active)
   13.29 +                updated_list.append(console)
   13.30 +        self.consoleProcesses = updated_list
   13.31 +        debug("%s has %i terminal program(s) connected to it" % (self.hostname, len(self.consoleProcesses)))
   13.32  
   13.33      def setRenderers(self, render_normal, render_select):
   13.34          """ renderer_normal: QtSvg.QSvgRenderer
    14.1 --- a/src/GNS3/Node/AnyEmuDevice.py	Mon Jun 18 17:28:03 2012 -0600
    14.2 +++ b/src/GNS3/Node/AnyEmuDevice.py	Thu Jun 28 21:36:05 2012 -0600
    14.3 @@ -360,6 +360,7 @@
    14.4              proc = console.connect(self.emudev.dynamips.host, self.emudev.console, self.hostname)
    14.5              if proc:
    14.6                  self.consoleProcesses.append(proc)
    14.7 +        AbstractNode.clearClosedConsoles(self)
    14.8  
    14.9      def isStarted(self):
   14.10          """ Returns True if this device is started
    15.1 --- a/src/GNS3/Node/AnyVBoxEmuDevice.py	Mon Jun 18 17:28:03 2012 -0600
    15.2 +++ b/src/GNS3/Node/AnyVBoxEmuDevice.py	Thu Jun 28 21:36:05 2012 -0600
    15.3 @@ -334,8 +334,10 @@
    15.4          try:
    15.5              if self.emu_vboxdev.state == 'stopped':
    15.6                  self.emu_vboxdev.start()
    15.7 +                self.displayWindowFocus()
    15.8              if self.emu_vboxdev.state == 'suspended':
    15.9                  self.emu_vboxdev.resume()
   15.10 +                self.displayWindowFocus()
   15.11          except:
   15.12              if progress:
   15.13                  raise
   15.14 @@ -406,10 +408,12 @@
   15.15                  proc = console.connect(self.emu_vboxdev.dynamips.host, self.emu_vboxdev.console, self.hostname)
   15.16              if proc:
   15.17                  self.consoleProcesses.append(proc)
   15.18 +        AbstractNode.clearClosedConsoles(self)
   15.19  
   15.20      def displayWindowFocus(self):
   15.21          """ Bring VM's display as foreground window and focus on it
   15.22          """
   15.23 +
   15.24          if self.emu_vboxdev.state == 'running' or self.emu_vboxdev.state == 'suspended':
   15.25              hwnd = int(self.emu_vboxdev.displayWindowFocus())
   15.26              if hwnd > 0:
   15.27 @@ -418,6 +422,7 @@
   15.28      def displayWindowHide(self):
   15.29          """ Hide VM's display window
   15.30          """
   15.31 +
   15.32          if self.emu_vboxdev.state == 'running' or self.emu_vboxdev.state == 'suspended':
   15.33              hwnd = int(self.emu_vboxdev.displayWindowFocus())
   15.34              if hwnd > 0:
    16.1 --- a/src/GNS3/Node/IOSRouter.py	Mon Jun 18 17:28:03 2012 -0600
    16.2 +++ b/src/GNS3/Node/IOSRouter.py	Thu Jun 28 21:36:05 2012 -0600
    16.3 @@ -674,6 +674,7 @@
    16.4              proc = console.connect(self.hypervisor.host, self.router.console, self.hostname)
    16.5              if proc:
    16.6                  self.consoleProcesses.append(proc)
    16.7 +        AbstractNode.clearClosedConsoles(self)
    16.8  
    16.9      def aux(self):
   16.10          """ Start a telnet console and connect it to this router's AUX port
   16.11 @@ -687,6 +688,7 @@
   16.12              proc = console.connect(self.hypervisor.host, self.router.aux, self.hostname)
   16.13              if proc:
   16.14                  self.consoleProcesses.append(proc)
   16.15 +        AbstractNode.clearClosedConsoles(self)
   16.16  
   16.17      def isStarted(self):
   16.18          """ Returns True if this router is started
    17.1 --- a/src/GNS3/QemuManager.py	Mon Jun 18 17:28:03 2012 -0600
    17.2 +++ b/src/GNS3/QemuManager.py	Thu Jun 28 21:36:05 2012 -0600
    17.3 @@ -22,12 +22,9 @@
    17.4  #This class is used to start "qemuwrapper" automatically on localhost.
    17.5  #It is not used, if you start wrapper manually.
    17.6  
    17.7 -import os
    17.8 -import sys
    17.9 -import time
   17.10 +import os, sys, time, socket
   17.11  import GNS3.Globals as globals
   17.12  import GNS3.Dynagen.qemu_lib as qlib
   17.13 -from socket import socket, AF_INET, AF_INET6, SOCK_STREAM
   17.14  from PyQt4 import QtCore, QtGui
   17.15  from GNS3.Utils import translate, debug, killAll
   17.16  from __main__ import VERSION
   17.17 @@ -45,32 +42,23 @@
   17.18      def __del__(self):
   17.19          """ Kill Qemu
   17.20          """
   17.21 -        #print "Entered QemuManager::__del__()"
   17.22 +
   17.23          if self.proc:
   17.24              self.proc.kill()
   17.25  
   17.26 -    def waitQemu(self):
   17.27 +    def waitQemu(self, binding):
   17.28          """ Wait Qemu until it accepts connections
   17.29          """
   17.30 -        #print "Entered QemuManager::waitQemu()"
   17.31 -        binding = globals.GApp.systconf['qemu'].QemuManager_binding
   17.32  
   17.33          # give 15 seconds to Qemu to accept connections
   17.34          count = 15
   17.35          progress = None
   17.36          connection_success = False
   17.37 -        #debug("Qemu manager: connect on " + str(self.port))
   17.38 -        debug("Qemu manager: connecting to %s on port %s" % (str(globals.GApp.systconf['qemu'].QemuManager_binding), str(self.port)))
   17.39 +        timeout = 60.0
   17.40 +        debug("Qemu manager: connecting to %s on port %i" % (binding, self.port))
   17.41          for nb in range(count + 1):
   17.42 -            if binding.__contains__(':'):
   17.43 -                # IPv6 address support
   17.44 -                s = socket(AF_INET6, SOCK_STREAM)
   17.45 -            else:
   17.46 -                s = socket(AF_INET, SOCK_STREAM)
   17.47 -            s.setblocking(0)
   17.48 -            s.settimeout(300)
   17.49              if nb == 3:
   17.50 -                progress = QtGui.QProgressDialog(translate("QemuManager", "Connecting to Qemu on port %i ...") % self.port,
   17.51 +                progress = QtGui.QProgressDialog(translate("QemuManager", "Connecting to Qemu on %s port %i ...") % (binding, self.port),
   17.52                                                   translate("QemuManager", "Abort"), 0, count, globals.GApp.mainWindow)
   17.53                  progress.setMinimum(1)
   17.54                  progress.setWindowModality(QtCore.Qt.WindowModal)
   17.55 @@ -82,9 +70,8 @@
   17.56                      progress.reset()
   17.57                      break
   17.58              try:
   17.59 -                s.connect((binding, self.port))
   17.60 +                s = socket.create_connection((binding, self.port), timeout)
   17.61              except:
   17.62 -                s.close()
   17.63                  time.sleep(1)
   17.64                  continue
   17.65              connection_success = True
   17.66 @@ -95,7 +82,7 @@
   17.67              time.sleep(0.2)
   17.68          else:
   17.69              QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'Qemu Manager',
   17.70 -                                       translate("QemuManager", "Can't connect to Qemu on port %i") % self.port)
   17.71 +                                       translate("QemuManager", "Can't connect to Qemu on %s port %i") % (binding, self.port))
   17.72              self.stopQemu()
   17.73              return False
   17.74          if progress:
   17.75 @@ -104,11 +91,12 @@
   17.76              progress = None
   17.77          return True
   17.78  
   17.79 -    def startQemu(self, port):
   17.80 +    def startQemu(self, port, binding=None):
   17.81          """ Start Qemu
   17.82          """
   17.83 -        #print "Entered QemuManager::startQemu()"
   17.84 -        binding = globals.GApp.systconf['qemu'].QemuManager_binding
   17.85 +
   17.86 +        if binding == None:
   17.87 +            binding = globals.GApp.systconf['qemu'].QemuManager_binding
   17.88          self.port = port
   17.89          if self.proc and self.proc.state():
   17.90              debug("QemuManager: Qemu is already started with pid %i" % int(self.proc.pid()))
   17.91 @@ -123,21 +111,15 @@
   17.92              self.proc.setWorkingDirectory(globals.GApp.systconf['qemu'].qemuwrapper_workdir)
   17.93  
   17.94          # test if Qemu is already running on this port
   17.95 -        if binding.__contains__(':'):
   17.96 -            # IPv6 address support
   17.97 -            s = socket(AF_INET6, SOCK_STREAM)
   17.98 -        else:
   17.99 -            s = socket(AF_INET, SOCK_STREAM)
  17.100 -        s.setblocking(0)
  17.101 -        s.settimeout(300)
  17.102 +        timeout = 60.0
  17.103          try:
  17.104 -            s.connect((binding, self.port))
  17.105 +            s = socket.create_connection((binding, self.port), timeout)
  17.106              QtGui.QMessageBox.warning(globals.GApp.mainWindow, 'Qemu Manager',
  17.107 -                                      translate("QemuManager", "Qemu is already running on port %i, it will not be shutdown after you quit GNS3") % self.port)
  17.108 +                                      translate("QemuManager", "Qemu is already running on %s port %i, it will not be shutdown after you quit GNS3") % (binding, self.port))
  17.109              s.close()
  17.110              return True
  17.111          except:
  17.112 -            s.close()
  17.113 +            pass
  17.114  
  17.115          # start Qemuwrapper, use python on all platform but Windows (in release mode)
  17.116          binding = globals.GApp.systconf['qemu'].QemuManager_binding
  17.117 @@ -150,10 +132,10 @@
  17.118              self.proc.start(sys.executable,  [globals.GApp.systconf['qemu'].qemuwrapper_path, '--listen', binding, '--port', str(self.port), '--no-path-check'])
  17.119  
  17.120          if self.proc.waitForStarted() == False:
  17.121 -            QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'Qemu Manager', translate("QemuManager", "Can't start Qemu on port %i") % self.port)
  17.122 +            QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'Qemu Manager', translate("QemuManager", "Can't start Qemu on %s port %i") % (binding, self.port))
  17.123              return False
  17.124  
  17.125 -        self.waitQemu()
  17.126 +        self.waitQemu(binding)
  17.127          if self.proc and self.proc.state():
  17.128              debug("QemuManager: Qemu has been started with pid %i"  % int(self.proc.pid()))
  17.129          return True
  17.130 @@ -161,7 +143,7 @@
  17.131      def stopQemu(self):
  17.132          """ Stop Qemu
  17.133          """
  17.134 -        #print "Entered QemuManager::stopQemu()"
  17.135 +
  17.136          for hypervisor in globals.GApp.dynagen.dynamips.values():
  17.137              if isinstance(hypervisor, qlib.Qemu):
  17.138                  try:
  17.139 @@ -179,7 +161,7 @@
  17.140      def preloadQemuwrapper(self):
  17.141          """ Preload Qemuwrapper
  17.142          """
  17.143 -        #print "Entered QemuManager::preloadQemuwrapper()"
  17.144 +
  17.145          proc = QtCore.QProcess(globals.GApp.mainWindow)
  17.146          binding = globals.GApp.systconf['qemu'].QemuManager_binding
  17.147  
  17.148 @@ -206,18 +188,11 @@
  17.149          # give 5 seconds to the hypervisor to accept connections
  17.150          count = 5
  17.151          connection_success = False
  17.152 +        timeout = 60.0
  17.153          for nb in range(count + 1):
  17.154 -            if binding.__contains__(':'):
  17.155 -                # IPv6 address support
  17.156 -                s = socket(AF_INET6, SOCK_STREAM)
  17.157 -            else:
  17.158 -                s = socket(AF_INET, SOCK_STREAM)
  17.159 -            s.setblocking(0)
  17.160 -            s.settimeout(300)
  17.161              try:
  17.162 -                s.connect((binding, self.port))
  17.163 +                s = socket.create_connection((binding, self.port), timeout)
  17.164              except:
  17.165 -                s.close()
  17.166                  time.sleep(1)
  17.167                  continue
  17.168              connection_success = True
    18.1 --- a/src/GNS3/Scene.py	Mon Jun 18 17:28:03 2012 -0600
    18.2 +++ b/src/GNS3/Scene.py	Thu Jun 28 21:36:05 2012 -0600
    18.3 @@ -376,7 +376,7 @@
    18.4  
    18.5          for item in self.__topology.selectedItems():
    18.6              if isinstance(item, ETHSW):
    18.7 -                table = MACTableDialog(item)
    18.8 +                table = MACTableDialog(item, globals.GApp.mainWindow)
    18.9                  table.show()
   18.10                  table.exec_()
   18.11  
    19.1 --- a/src/GNS3/Telnet.py	Mon Jun 18 17:28:03 2012 -0600
    19.2 +++ b/src/GNS3/Telnet.py	Thu Jun 28 21:36:05 2012 -0600
    19.3 @@ -86,7 +86,7 @@
    19.4          return winm.bringWindowToFront("Dynamips", "%s" % name)
    19.5      if sys.platform.startswith('darwin'):
    19.6          # Not implemented, this is handled by OSX
    19.7 -        return False
    19.8 +        return True
    19.9      # X11-based UNIX-like system
   19.10      return winm.bringWindowToFront("", "%s" % str(name))
   19.11      # X11-based UNIX-like system
    20.1 --- a/src/GNS3/Topology.py	Mon Jun 18 17:28:03 2012 -0600
    20.2 +++ b/src/GNS3/Topology.py	Thu Jun 28 21:36:05 2012 -0600
    20.3 @@ -602,8 +602,8 @@
    20.4                  for device in self.__nodes.itervalues():
    20.5                      if isinstance(device, VBoxDevice):
    20.6                          current_vboximages.append(device.get_config()['image'])
    20.7 -                for name in globals.GApp.vboximages.keys():
    20.8 -                    if not name in current_vboximages:
    20.9 +                for (name, conf) in globals.GApp.vboximages.iteritems():
   20.10 +                    if not conf.filename in current_vboximages:
   20.11                          devices.append(name)
   20.12                  if len(devices) == 0:
   20.13                      QtGui.QMessageBox.critical(globals.GApp.mainWindow, translate("Topology", "VirtualBox guest"), translate("Topology", "All configured VMs already in use. You may add or clone additional VMs in VirtualBox"))
   20.14 @@ -871,10 +871,14 @@
   20.15  
   20.16              if iosConfig:
   20.17                  self.applyIOSBaseConfig(node, iosConfig)
   20.18 -                
   20.19 -            #FIXME: temporary workaround to have VBox VMs with same hostname as in VirtualBox names (this is not clean as params are sent twice to vboxwrapper)
   20.20 +
   20.21 +            #FIXME: ugly temporary workaround to have VBox VMs with same hostname as in VirtualBox names (this is not a clean solution as params are sent twice to vboxwrapper)
   20.22              if isinstance(node, VBoxDevice) and globals.GApp.systconf['vbox'].use_VBoxVmnames:
   20.23 -                vmname = node.config['image'].strip()
   20.24 +                image = node.config['image'].strip()
   20.25 +                vmname = image
   20.26 +                for (name, conf) in globals.GApp.vboximages.iteritems():
   20.27 +                    if conf.filename == image:
   20.28 +                        vmname = name
   20.29                  # white spaces have to be replaced
   20.30                  p = re.compile('\s+', re.UNICODE)
   20.31                  vmname = p.sub("_", vmname)
   20.32 @@ -947,7 +951,7 @@
   20.33                      # internal hypervisor
   20.34                      image_conf = globals.GApp.iosimages[globals.GApp.systconf['dynamips'].HypervisorManager_binding + ':' + router.image]
   20.35                      if globals.GApp.HypervisorManager and len(image_conf.hypervisors) == 0:
   20.36 -                        globals.GApp.HypervisorManager.unallocateHypervisor(node, router.dynamips.port)
   20.37 +                        globals.GApp.HypervisorManager.unallocateHypervisor(node, router.dynamips.host ,router.dynamips.port)
   20.38                  else:
   20.39                      # external hypevisor
   20.40                      external_hypervisor_key = router.dynamips.host + ':' + str(router.dynamips.port)
    21.1 --- a/src/GNS3/Ui/ConfigurationPages/Form_PreferencesVirtualBox.py	Mon Jun 18 17:28:03 2012 -0600
    21.2 +++ b/src/GNS3/Ui/ConfigurationPages/Form_PreferencesVirtualBox.py	Thu Jun 28 21:36:05 2012 -0600
    21.3 @@ -1,8 +1,8 @@
    21.4  # -*- coding: utf-8 -*-
    21.5  
    21.6 -# Form implementation generated from reading ui file './ConfigurationPages/Form_PreferencesVirtualBox.ui'
    21.7 +# Form implementation generated from reading ui file 'ConfigurationPages/Form_PreferencesVirtualBox.ui'
    21.8  #
    21.9 -# Created: Sun Jun 17 21:09:15 2012
   21.10 +# Created: Tue Jun 26 18:21:17 2012
   21.11  #      by: PyQt4 UI code generator 4.8.6
   21.12  #
   21.13  # WARNING! All changes made in this file will be lost!
   21.14 @@ -185,26 +185,19 @@
   21.15          self.groupBox.setObjectName(_fromUtf8("groupBox"))
   21.16          self.gridLayout = QtGui.QGridLayout(self.groupBox)
   21.17          self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
   21.18 -        self.label_14 = QtGui.QLabel(self.groupBox)
   21.19 -        self.label_14.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "VM List / unique ID:", None, QtGui.QApplication.UnicodeUTF8))
   21.20 -        self.label_14.setObjectName(_fromUtf8("label_14"))
   21.21 -        self.gridLayout.addWidget(self.label_14, 0, 0, 1, 1)
   21.22 -        self.comboBoxNameVBoxImage = QtGui.QComboBox(self.groupBox)
   21.23 -        self.comboBoxNameVBoxImage.setEditable(True)
   21.24 -        self.comboBoxNameVBoxImage.setObjectName(_fromUtf8("comboBoxNameVBoxImage"))
   21.25 -        self.gridLayout.addWidget(self.comboBoxNameVBoxImage, 0, 1, 1, 2)
   21.26          self.label = QtGui.QLabel(self.groupBox)
   21.27          self.label.setEnabled(True)
   21.28 -        self.label.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "VM Name / UUID:", None, QtGui.QApplication.UnicodeUTF8))
   21.29 +        self.label.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "Identifier name:", None, QtGui.QApplication.UnicodeUTF8))
   21.30          self.label.setObjectName(_fromUtf8("label"))
   21.31          self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
   21.32 -        self.VBoxImage = QtGui.QLineEdit(self.groupBox)
   21.33 -        self.VBoxImage.setObjectName(_fromUtf8("VBoxImage"))
   21.34 -        self.gridLayout.addWidget(self.VBoxImage, 1, 1, 1, 2)
   21.35 +        self.VBoxID = QtGui.QLineEdit(self.groupBox)
   21.36 +        self.VBoxID.setReadOnly(False)
   21.37 +        self.VBoxID.setObjectName(_fromUtf8("VBoxID"))
   21.38 +        self.gridLayout.addWidget(self.VBoxID, 1, 1, 1, 2)
   21.39          self.label_37 = QtGui.QLabel(self.groupBox)
   21.40          self.label_37.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "Number of NICs:", None, QtGui.QApplication.UnicodeUTF8))
   21.41          self.label_37.setObjectName(_fromUtf8("label_37"))
   21.42 -        self.gridLayout.addWidget(self.label_37, 2, 0, 1, 1)
   21.43 +        self.gridLayout.addWidget(self.label_37, 3, 0, 1, 1)
   21.44          self.VBoxNICNb = QtGui.QSpinBox(self.groupBox)
   21.45          self.VBoxNICNb.setEnabled(True)
   21.46          self.VBoxNICNb.setMinimum(1)
   21.47 @@ -212,11 +205,11 @@
   21.48          self.VBoxNICNb.setSingleStep(1)
   21.49          self.VBoxNICNb.setProperty("value", 2)
   21.50          self.VBoxNICNb.setObjectName(_fromUtf8("VBoxNICNb"))
   21.51 -        self.gridLayout.addWidget(self.VBoxNICNb, 2, 1, 1, 2)
   21.52 +        self.gridLayout.addWidget(self.VBoxNICNb, 3, 1, 1, 2)
   21.53          self.label_10 = QtGui.QLabel(self.groupBox)
   21.54          self.label_10.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "NIC model:", None, QtGui.QApplication.UnicodeUTF8))
   21.55          self.label_10.setObjectName(_fromUtf8("label_10"))
   21.56 -        self.gridLayout.addWidget(self.label_10, 3, 0, 1, 1)
   21.57 +        self.gridLayout.addWidget(self.label_10, 4, 0, 1, 1)
   21.58          self.VBoxNIC = QtGui.QComboBox(self.groupBox)
   21.59          self.VBoxNIC.setEnabled(True)
   21.60          self.VBoxNIC.setObjectName(_fromUtf8("VBoxNIC"))
   21.61 @@ -230,42 +223,50 @@
   21.62          self.VBoxNIC.setItemText(3, QtGui.QApplication.translate("PreferencesVirtualBox", "pcnet3", None, QtGui.QApplication.UnicodeUTF8))
   21.63          self.VBoxNIC.addItem(_fromUtf8(""))
   21.64          self.VBoxNIC.setItemText(4, QtGui.QApplication.translate("PreferencesVirtualBox", "virtio", None, QtGui.QApplication.UnicodeUTF8))
   21.65 -        self.gridLayout.addWidget(self.VBoxNIC, 3, 1, 1, 2)
   21.66 +        self.gridLayout.addWidget(self.VBoxNIC, 4, 1, 1, 2)
   21.67          self.VBoxcheckBoxEnableGuestControl = QtGui.QCheckBox(self.groupBox)
   21.68          self.VBoxcheckBoxEnableGuestControl.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "Enable GuestControl (experimental)", None, QtGui.QApplication.UnicodeUTF8))
   21.69          self.VBoxcheckBoxEnableGuestControl.setObjectName(_fromUtf8("VBoxcheckBoxEnableGuestControl"))
   21.70 -        self.gridLayout.addWidget(self.VBoxcheckBoxEnableGuestControl, 8, 0, 1, 3)
   21.71 +        self.gridLayout.addWidget(self.VBoxcheckBoxEnableGuestControl, 9, 0, 1, 3)
   21.72          self.label_4 = QtGui.QLabel(self.groupBox)
   21.73 -        self.label_4.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "GuestControl User", None, QtGui.QApplication.UnicodeUTF8))
   21.74 +        self.label_4.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "GuestControl User:", None, QtGui.QApplication.UnicodeUTF8))
   21.75          self.label_4.setObjectName(_fromUtf8("label_4"))
   21.76 -        self.gridLayout.addWidget(self.label_4, 9, 0, 1, 1)
   21.77 +        self.gridLayout.addWidget(self.label_4, 10, 0, 1, 1)
   21.78          self.VBoxGuestControl_User = QtGui.QLineEdit(self.groupBox)
   21.79          self.VBoxGuestControl_User.setObjectName(_fromUtf8("VBoxGuestControl_User"))
   21.80 -        self.gridLayout.addWidget(self.VBoxGuestControl_User, 9, 2, 1, 1)
   21.81 +        self.gridLayout.addWidget(self.VBoxGuestControl_User, 10, 2, 1, 1)
   21.82          self.label_7 = QtGui.QLabel(self.groupBox)
   21.83 -        self.label_7.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "GuestControl Password", None, QtGui.QApplication.UnicodeUTF8))
   21.84 +        self.label_7.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "GuestControl Password:", None, QtGui.QApplication.UnicodeUTF8))
   21.85          self.label_7.setObjectName(_fromUtf8("label_7"))
   21.86 -        self.gridLayout.addWidget(self.label_7, 10, 0, 1, 2)
   21.87 +        self.gridLayout.addWidget(self.label_7, 11, 0, 1, 2)
   21.88          self.VBoxGuestControl_Password = QtGui.QLineEdit(self.groupBox)
   21.89          self.VBoxGuestControl_Password.setObjectName(_fromUtf8("VBoxGuestControl_Password"))
   21.90 -        self.gridLayout.addWidget(self.VBoxGuestControl_Password, 10, 2, 1, 1)
   21.91 +        self.gridLayout.addWidget(self.VBoxGuestControl_Password, 11, 2, 1, 1)
   21.92          self.checkBoxVBoxFirstInterfaceManaged = QtGui.QCheckBox(self.groupBox)
   21.93          self.checkBoxVBoxFirstInterfaceManaged.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "Do not use first NIC for connections with the host OS", None, QtGui.QApplication.UnicodeUTF8))
   21.94          self.checkBoxVBoxFirstInterfaceManaged.setChecked(False)
   21.95          self.checkBoxVBoxFirstInterfaceManaged.setObjectName(_fromUtf8("checkBoxVBoxFirstInterfaceManaged"))
   21.96 -        self.gridLayout.addWidget(self.checkBoxVBoxFirstInterfaceManaged, 4, 0, 1, 3)
   21.97 +        self.gridLayout.addWidget(self.checkBoxVBoxFirstInterfaceManaged, 5, 0, 1, 3)
   21.98          self.checkBoxVBoxHeadlessMode = QtGui.QCheckBox(self.groupBox)
   21.99          self.checkBoxVBoxHeadlessMode.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "Start in headless mode (without GUI)", None, QtGui.QApplication.UnicodeUTF8))
  21.100          self.checkBoxVBoxHeadlessMode.setObjectName(_fromUtf8("checkBoxVBoxHeadlessMode"))
  21.101 -        self.gridLayout.addWidget(self.checkBoxVBoxHeadlessMode, 7, 0, 1, 3)
  21.102 +        self.gridLayout.addWidget(self.checkBoxVBoxHeadlessMode, 8, 0, 1, 3)
  21.103          self.checkBoxVboxConsoleSupport = QtGui.QCheckBox(self.groupBox)
  21.104          self.checkBoxVboxConsoleSupport.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "Enable console support", None, QtGui.QApplication.UnicodeUTF8))
  21.105          self.checkBoxVboxConsoleSupport.setObjectName(_fromUtf8("checkBoxVboxConsoleSupport"))
  21.106 -        self.gridLayout.addWidget(self.checkBoxVboxConsoleSupport, 5, 0, 1, 3)
  21.107 +        self.gridLayout.addWidget(self.checkBoxVboxConsoleSupport, 6, 0, 1, 3)
  21.108          self.checkBoxVboxConsoleServer = QtGui.QCheckBox(self.groupBox)
  21.109          self.checkBoxVboxConsoleServer.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "Enable console server (optionnal on Windows)", None, QtGui.QApplication.UnicodeUTF8))
  21.110          self.checkBoxVboxConsoleServer.setObjectName(_fromUtf8("checkBoxVboxConsoleServer"))
  21.111 -        self.gridLayout.addWidget(self.checkBoxVboxConsoleServer, 6, 0, 1, 3)
  21.112 +        self.gridLayout.addWidget(self.checkBoxVboxConsoleServer, 7, 0, 1, 3)
  21.113 +        self.label_14 = QtGui.QLabel(self.groupBox)
  21.114 +        self.label_14.setText(QtGui.QApplication.translate("PreferencesVirtualBox", "VM List:", None, QtGui.QApplication.UnicodeUTF8))
  21.115 +        self.label_14.setObjectName(_fromUtf8("label_14"))
  21.116 +        self.gridLayout.addWidget(self.label_14, 2, 0, 1, 1)
  21.117 +        self.comboBoxNameVBoxImage = QtGui.QComboBox(self.groupBox)
  21.118 +        self.comboBoxNameVBoxImage.setEditable(False)
  21.119 +        self.comboBoxNameVBoxImage.setObjectName(_fromUtf8("comboBoxNameVBoxImage"))
  21.120 +        self.gridLayout.addWidget(self.comboBoxNameVBoxImage, 2, 1, 1, 2)
  21.121          self.verticalLayout.addWidget(self.groupBox)
  21.122          self.horizontalLayout = QtGui.QHBoxLayout()
  21.123          self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
  21.124 @@ -290,8 +291,8 @@
  21.125          self.verticalLayout.addWidget(self.label_20)
  21.126          self.treeWidgetVBoxImages = QtGui.QTreeWidget(self.scrollAreaWidgetContents)
  21.127          self.treeWidgetVBoxImages.setObjectName(_fromUtf8("treeWidgetVBoxImages"))
  21.128 -        self.treeWidgetVBoxImages.headerItem().setText(0, QtGui.QApplication.translate("PreferencesVirtualBox", "GNS3 Name", None, QtGui.QApplication.UnicodeUTF8))
  21.129 -        self.treeWidgetVBoxImages.headerItem().setText(1, QtGui.QApplication.translate("PreferencesVirtualBox", "Virtual Machine Name or Unique Identifier", None, QtGui.QApplication.UnicodeUTF8))
  21.130 +        self.treeWidgetVBoxImages.headerItem().setText(0, QtGui.QApplication.translate("PreferencesVirtualBox", "Name", None, QtGui.QApplication.UnicodeUTF8))
  21.131 +        self.treeWidgetVBoxImages.headerItem().setText(1, QtGui.QApplication.translate("PreferencesVirtualBox", "Virtual Machine Name", None, QtGui.QApplication.UnicodeUTF8))
  21.132          self.verticalLayout.addWidget(self.treeWidgetVBoxImages)
  21.133          self.scrollArea.setWidget(self.scrollAreaWidgetContents)
  21.134          self.verticalLayout_7.addWidget(self.scrollArea)
    22.1 --- a/src/GNS3/Ui/ConfigurationPages/Form_PreferencesVirtualBox.ui	Mon Jun 18 17:28:03 2012 -0600
    22.2 +++ b/src/GNS3/Ui/ConfigurationPages/Form_PreferencesVirtualBox.ui	Thu Jun 28 21:36:05 2012 -0600
    22.3 @@ -318,41 +318,31 @@
    22.4                <string>VirtualBox Guest Settings</string>
    22.5               </property>
    22.6               <layout class="QGridLayout" name="gridLayout">
    22.7 -              <item row="0" column="0">
    22.8 -               <widget class="QLabel" name="label_14">
    22.9 -                <property name="text">
   22.10 -                 <string>VM List / unique ID:</string>
   22.11 -                </property>
   22.12 -               </widget>
   22.13 -              </item>
   22.14 -              <item row="0" column="1" colspan="2">
   22.15 -               <widget class="QComboBox" name="comboBoxNameVBoxImage">
   22.16 -                <property name="editable">
   22.17 -                 <bool>true</bool>
   22.18 -                </property>
   22.19 -               </widget>
   22.20 -              </item>
   22.21                <item row="1" column="0">
   22.22                 <widget class="QLabel" name="label">
   22.23                  <property name="enabled">
   22.24                   <bool>true</bool>
   22.25                  </property>
   22.26                  <property name="text">
   22.27 -                 <string>VM Name / UUID:</string>
   22.28 +                 <string>Identifier name:</string>
   22.29                  </property>
   22.30                 </widget>
   22.31                </item>
   22.32                <item row="1" column="1" colspan="2">
   22.33 -               <widget class="QLineEdit" name="VBoxImage"/>
   22.34 +               <widget class="QLineEdit" name="VBoxID">
   22.35 +                <property name="readOnly">
   22.36 +                 <bool>false</bool>
   22.37 +                </property>
   22.38 +               </widget>
   22.39                </item>
   22.40 -              <item row="2" column="0">
   22.41 +              <item row="3" column="0">
   22.42                 <widget class="QLabel" name="label_37">
   22.43                  <property name="text">
   22.44                   <string>Number of NICs:</string>
   22.45                  </property>
   22.46                 </widget>
   22.47                </item>
   22.48 -              <item row="2" column="1" colspan="2">
   22.49 +              <item row="3" column="1" colspan="2">
   22.50                 <widget class="QSpinBox" name="VBoxNICNb">
   22.51                  <property name="enabled">
   22.52                   <bool>true</bool>
   22.53 @@ -371,14 +361,14 @@
   22.54                  </property>
   22.55                 </widget>
   22.56                </item>
   22.57 -              <item row="3" column="0">
   22.58 +              <item row="4" column="0">
   22.59                 <widget class="QLabel" name="label_10">
   22.60                  <property name="text">
   22.61                   <string>NIC model:</string>
   22.62                  </property>
   22.63                 </widget>
   22.64                </item>
   22.65 -              <item row="3" column="1" colspan="2">
   22.66 +              <item row="4" column="1" colspan="2">
   22.67                 <widget class="QComboBox" name="VBoxNIC">
   22.68                  <property name="enabled">
   22.69                   <bool>true</bool>
   22.70 @@ -413,34 +403,34 @@
   22.71                  </item>
   22.72                 </widget>
   22.73                </item>
   22.74 -              <item row="8" column="0" colspan="3">
   22.75 +              <item row="9" column="0" colspan="3">
   22.76                 <widget class="QCheckBox" name="VBoxcheckBoxEnableGuestControl">
   22.77                  <property name="text">
   22.78                   <string>Enable GuestControl (experimental)</string>
   22.79                  </property>
   22.80                 </widget>
   22.81                </item>
   22.82 -              <item row="9" column="0">
   22.83 +              <item row="10" column="0">
   22.84                 <widget class="QLabel" name="label_4">
   22.85                  <property name="text">
   22.86 -                 <string>GuestControl User</string>
   22.87 -                </property>
   22.88 -               </widget>
   22.89 -              </item>
   22.90 -              <item row="9" column="2">
   22.91 -               <widget class="QLineEdit" name="VBoxGuestControl_User"/>
   22.92 -              </item>
   22.93 -              <item row="10" column="0" colspan="2">
   22.94 -               <widget class="QLabel" name="label_7">
   22.95 -                <property name="text">
   22.96 -                 <string>GuestControl Password</string>
   22.97 +                 <string>GuestControl User:</string>
   22.98                  </property>
   22.99                 </widget>
  22.100                </item>
  22.101                <item row="10" column="2">
  22.102 +               <widget class="QLineEdit" name="VBoxGuestControl_User"/>
  22.103 +              </item>
  22.104 +              <item row="11" column="0" colspan="2">
  22.105 +               <widget class="QLabel" name="label_7">
  22.106 +                <property name="text">
  22.107 +                 <string>GuestControl Password:</string>
  22.108 +                </property>
  22.109 +               </widget>
  22.110 +              </item>
  22.111 +              <item row="11" column="2">
  22.112                 <widget class="QLineEdit" name="VBoxGuestControl_Password"/>
  22.113                </item>
  22.114 -              <item row="4" column="0" colspan="3">
  22.115 +              <item row="5" column="0" colspan="3">
  22.116                 <widget class="QCheckBox" name="checkBoxVBoxFirstInterfaceManaged">
  22.117                  <property name="text">
  22.118                   <string>Do not use first NIC for connections with the host OS</string>
  22.119 @@ -450,27 +440,41 @@
  22.120                  </property>
  22.121                 </widget>
  22.122                </item>
  22.123 -              <item row="7" column="0" colspan="3">
  22.124 +              <item row="8" column="0" colspan="3">
  22.125                 <widget class="QCheckBox" name="checkBoxVBoxHeadlessMode">
  22.126                  <property name="text">
  22.127                   <string>Start in headless mode (without GUI)</string>
  22.128                  </property>
  22.129                 </widget>
  22.130                </item>
  22.131 -              <item row="5" column="0" colspan="3">
  22.132 +              <item row="6" column="0" colspan="3">
  22.133                 <widget class="QCheckBox" name="checkBoxVboxConsoleSupport">
  22.134                  <property name="text">
  22.135                   <string>Enable console support</string>
  22.136                  </property>
  22.137                 </widget>
  22.138                </item>
  22.139 -              <item row="6" column="0" colspan="3">
  22.140 +              <item row="7" column="0" colspan="3">
  22.141                 <widget class="QCheckBox" name="checkBoxVboxConsoleServer">
  22.142                  <property name="text">
  22.143                   <string>Enable console server (optionnal on Windows)</string>
  22.144                  </property>
  22.145                 </widget>
  22.146                </item>
  22.147 +              <item row="2" column="0">
  22.148 +               <widget class="QLabel" name="label_14">
  22.149 +                <property name="text">
  22.150 +                 <string>VM List:</string>
  22.151 +                </property>
  22.152 +               </widget>
  22.153 +              </item>
  22.154 +              <item row="2" column="1" colspan="2">
  22.155 +               <widget class="QComboBox" name="comboBoxNameVBoxImage">
  22.156 +                <property name="editable">
  22.157 +                 <bool>false</bool>
  22.158 +                </property>
  22.159 +               </widget>
  22.160 +              </item>
  22.161               </layout>
  22.162              </widget>
  22.163             </item>
  22.164 @@ -523,12 +527,12 @@
  22.165              <widget class="QTreeWidget" name="treeWidgetVBoxImages">
  22.166               <column>
  22.167                <property name="text">
  22.168 -               <string>GNS3 Name</string>
  22.169 +               <string>Name</string>
  22.170                </property>
  22.171               </column>
  22.172               <column>
  22.173                <property name="text">
  22.174 -               <string>Virtual Machine Name or Unique Identifier</string>
  22.175 +               <string>Virtual Machine Name</string>
  22.176                </property>
  22.177               </column>
  22.178              </widget>
    23.1 --- a/src/GNS3/Ui/ConfigurationPages/Page_PreferencesDynamips.py	Mon Jun 18 17:28:03 2012 -0600
    23.2 +++ b/src/GNS3/Ui/ConfigurationPages/Page_PreferencesDynamips.py	Thu Jun 28 21:36:05 2012 -0600
    23.3 @@ -235,10 +235,12 @@
    23.4              version_2nd = int(version_raw.split('.')[1])
    23.5              version_3rd = int(version_raw.split('.')[2].split('-')[0])
    23.6              dynamips_ver = str(version_1st)+'.'+str(version_2nd)+'.'+str(version_3rd)+'-'+version_raw.split('.')[2].split('-')[1]
    23.7 +            globals.GApp.systconf['dynamips'].detected_version = unicode(dynamips_ver)
    23.8 +            ConfDB().sync()
    23.9          except:
   23.10              self.labelDynamipsStatus.setText('<font color="red">' + translate("UiConfig_PreferencesDynamips", "Failed to determine version of Dynamips.")  + '</font>')
   23.11 -            return            
   23.12 -        
   23.13 +            return
   23.14 +
   23.15          if version_2nd < 2 or version_3rd < 8:
   23.16              self.labelDynamipsStatus.setText('<font color="red">' + translate("UiConfig_PreferencesDynamips", "Found Dynamips %s, which is not supported. Use 0.2.8+ instead.") % dynamips_ver + '</font>')
   23.17              return
    24.1 --- a/src/GNS3/Ui/ConfigurationPages/Page_PreferencesVirtualBox.py	Mon Jun 18 17:28:03 2012 -0600
    24.2 +++ b/src/GNS3/Ui/ConfigurationPages/Page_PreferencesVirtualBox.py	Thu Jun 28 21:36:05 2012 -0600
    24.3 @@ -69,7 +69,7 @@
    24.4          self.connect(self.treeWidgetVBoxImages,  QtCore.SIGNAL('itemSelectionChanged()'),  self.slotVBoxImageSelectionChanged)
    24.5  
    24.6          # Auto-fill of VirtualBox VM name
    24.7 -        self.connect(self.comboBoxNameVBoxImage, QtCore.SIGNAL('editTextChanged(QString)'), self.VBoxImage, QtCore.SLOT('setText(QString)'))
    24.8 +        self.connect(self.comboBoxNameVBoxImage, QtCore.SIGNAL('editTextChanged(QString)'), self.VBoxID, QtCore.SLOT('setText(QString)'))
    24.9  
   24.10          # Refresh VM list
   24.11          self.connect(self.pushButtonRefresh, QtCore.SIGNAL('clicked()'), self.slotRefreshVMlist)
   24.12 @@ -267,7 +267,7 @@
   24.13          self.port.setValue(self.conf.vboxwrapper_port)
   24.14          self.baseUDP.setValue(self.conf.vboxwrapper_baseUDP)
   24.15          self.baseConsole.setValue(self.conf.vboxwrapper_baseConsole)
   24.16 -        
   24.17 +
   24.18          # VirtualBox settings
   24.19          for (name, conf) in globals.GApp.vboximages.iteritems():
   24.20  
   24.21 @@ -278,7 +278,7 @@
   24.22              item.setText(1, conf.filename)
   24.23              
   24.24          self.treeWidgetVBoxImages.resizeColumnToContents(0)
   24.25 -        self.treeWidgetVBoxImages.sortItems(0, QtCore.Qt.AscendingOrder) # Sort accoroding to GNS3 name
   24.26 +        self.treeWidgetVBoxImages.sortItems(1, QtCore.Qt.AscendingOrder) # Sort according to GNS3 name
   24.27  
   24.28      def saveConf(self):
   24.29  
   24.30 @@ -361,13 +361,12 @@
   24.31          """ Add/Save VBox Image in the list of VBox images
   24.32          """
   24.33  
   24.34 -        #name = unicode(self.comboBoxNameVBoxImage.text())
   24.35 -        name = unicode(self.comboBoxNameVBoxImage.currentText(), 'utf-8', errors='replace')
   24.36 -        image = unicode(self.VBoxImage.text(), 'utf-8', errors='replace')
   24.37 +        name = unicode(self.VBoxID.text(), 'utf-8', errors='replace')
   24.38 +        image = unicode(self.comboBoxNameVBoxImage.currentText(), 'utf-8', errors='replace')
   24.39          
   24.40          if not name or not image:
   24.41              QtGui.QMessageBox.critical(globals.preferencesWindow, translate("Page_PreferencesVirtualBox", "VirtualBox guest"), 
   24.42 -                                       translate("Page_PreferencesVirtualBox", "Identifier and binary image must be set!"))
   24.43 +                                       translate("Page_PreferencesVirtualBox", "Identifier and VM must be set!"))
   24.44              return
   24.45  
   24.46          if globals.GApp.vboximages.has_key(name):
   24.47 @@ -375,6 +374,14 @@
   24.48              item_to_update = self.treeWidgetVBoxImages.findItems(name, QtCore.Qt.MatchFixedString)[0]
   24.49              item_to_update.setText(1, image)
   24.50          else:
   24.51 +            
   24.52 +            # white spaces have to be replaced
   24.53 +            p = re.compile('\s+', re.UNICODE)
   24.54 +            name = p.sub("_", name)
   24.55 +            if not re.search(r"""^[\w,.-\[\]]*$""", name, re.UNICODE):
   24.56 +                QtGui.QMessageBox.critical(globals.preferencesWindow, translate("Page_PreferencesVirtualBox", "VirtualBox guest"), 
   24.57 +                                           translate("Page_PreferencesVirtualBox", "Identifier name must contains only alphanumeric characters!"))
   24.58 +                return
   24.59              # else create a new entry
   24.60              item = QtGui.QTreeWidgetItem(self.treeWidgetVBoxImages)
   24.61              # image name column
   24.62 @@ -443,9 +450,9 @@
   24.63  
   24.64              conf = globals.GApp.vboximages[name]
   24.65              
   24.66 -            self.comboBoxNameVBoxImage.setItemText(0 ,name)
   24.67 +            self.comboBoxNameVBoxImage.setItemText(0 , conf.filename)
   24.68              self.comboBoxNameVBoxImage.setCurrentIndex(0)
   24.69 -            self.VBoxImage.setText(conf.filename)
   24.70 +            self.VBoxID.setText(name)
   24.71  
   24.72              if self.conf.enable_GuestControl:
   24.73                  self.VBoxGuestControl_User.setEnabled(True)
    25.1 --- a/src/GNS3/VBoxManager.py	Mon Jun 18 17:28:03 2012 -0600
    25.2 +++ b/src/GNS3/VBoxManager.py	Thu Jun 28 21:36:05 2012 -0600
    25.3 @@ -22,12 +22,9 @@
    25.4  #This class is used to start "vboxwrapper" automatically on localhost.
    25.5  #It is not used, if you start wrapper manually.
    25.6  
    25.7 -import os
    25.8 -import sys
    25.9 -import time
   25.10 +import os, sys, time, socket
   25.11  import GNS3.Globals as globals
   25.12  import GNS3.Dynagen.dynagen_vbox_lib as vboxlib
   25.13 -from socket import socket, AF_INET, AF_INET6, SOCK_STREAM
   25.14  from PyQt4 import QtCore, QtGui
   25.15  from GNS3.Utils import translate, debug, killAll
   25.16  
   25.17 @@ -47,28 +44,19 @@
   25.18  
   25.19          self.stopVBox()
   25.20  
   25.21 -    def waitVBox(self):
   25.22 +    def waitVBox(self, binding):
   25.23          """ Wait VBox until it accepts connections
   25.24          """
   25.25 -        #print "Entered VBoxManager::waitVBox()"
   25.26 -        binding = globals.GApp.systconf['vbox'].VBoxManager_binding
   25.27  
   25.28          # give 15 seconds to VBox to accept connections
   25.29          count = 15
   25.30          progress = None
   25.31          connection_success = False
   25.32 -        debug("VBox manager: connecting to %s on port %s" % (str(binding), str(self.port)))
   25.33 +        timeout = 60.0
   25.34 +        debug("VBox manager: connecting to %s on port %i" % (binding, self.port))
   25.35          for nb in range(count + 1):
   25.36 -            #print "ADEBUG: VBoxManager.py: binding = " + binding
   25.37 -            if binding.__contains__(':'):
   25.38 -                # IPv6 address support
   25.39 -                s = socket(AF_INET6, SOCK_STREAM)
   25.40 -            else:
   25.41 -                s = socket(AF_INET, SOCK_STREAM)
   25.42 -            s.setblocking(0)
   25.43 -            s.settimeout(300)
   25.44              if nb == 3:
   25.45 -                progress = QtGui.QProgressDialog(translate("VBoxManager", "Connecting to VBox on port %i ...") % self.port,
   25.46 +                progress = QtGui.QProgressDialog(translate("VBoxManager", "Connecting to VBox on %s port %i ...") % (binding, self.port),
   25.47                                                   translate("VBoxManager", "Abort"), 0, count, globals.GApp.mainWindow)
   25.48                  progress.setMinimum(1)
   25.49                  progress.setWindowModality(QtCore.Qt.WindowModal)
   25.50 @@ -80,9 +68,8 @@
   25.51                      progress.reset()
   25.52                      break
   25.53              try:
   25.54 -                s.connect((binding, self.port))
   25.55 +                s = socket.create_connection((binding, self.port), timeout)
   25.56              except:
   25.57 -                s.close()
   25.58                  time.sleep(1)
   25.59                  continue
   25.60              connection_success = True
   25.61 @@ -93,7 +80,7 @@
   25.62              time.sleep(0.2)
   25.63          else:
   25.64              QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'VBox Manager',
   25.65 -                                       translate("VBoxManager", "Can't connect to VBox on port %i") % self.port)
   25.66 +                                       translate("VBoxManager", "Can't connect to VBox on %s port %i") % (binding, self.port))
   25.67              self.stopVBox()
   25.68              return False
   25.69          if progress:
   25.70 @@ -103,11 +90,12 @@
   25.71          return True
   25.72  
   25.73  
   25.74 -    def startVBox(self, port):
   25.75 +    def startVBox(self, port, binding=None):
   25.76          """ Start VBox
   25.77          """
   25.78 -        #print "Entered VBoxManager::startVBox()"
   25.79 -        binding = globals.GApp.systconf['vbox'].VBoxManager_binding
   25.80 +
   25.81 +        if binding == None:
   25.82 +            binding = globals.GApp.systconf['vbox'].VBoxManager_binding
   25.83          self.port = port
   25.84  
   25.85          if self.proc and self.proc.state():
   25.86 @@ -123,22 +111,15 @@
   25.87              self.proc.setWorkingDirectory(globals.GApp.systconf['vbox'].vboxwrapper_workdir)
   25.88  
   25.89          # test if VBox is already running on this port
   25.90 -        #print "ADEBUG: VBoxManager.py: binding = " + binding
   25.91 -        if binding.__contains__(':'):
   25.92 -            # IPv6 address support
   25.93 -            s = socket(AF_INET6, SOCK_STREAM)
   25.94 -        else:
   25.95 -            s = socket(AF_INET, SOCK_STREAM)
   25.96 -        s.setblocking(0)
   25.97 -        s.settimeout(300)
   25.98 +        timeout = 60.0
   25.99          try:
  25.100 -            s.connect((binding, self.port))
  25.101 +            s = socket.create_connection((binding, self.port), timeout)
  25.102              QtGui.QMessageBox.warning(globals.GApp.mainWindow, 'VBox Manager',
  25.103 -                                       translate("VBoxManager", "VBox is already running on port %i, it will not be shutdown after you quit GNS3") % self.port)
  25.104 +                                       translate("VBoxManager", "VBox is already running on %s port %i, it will not be shutdown after you quit GNS3") % (binding, self.port))
  25.105              s.close()
  25.106              return True
  25.107          except:
  25.108 -            s.close()
  25.109 +            pass
  25.110  
  25.111          # start VBoxwrapper, use python on all platform but Windows (in release mode)
  25.112          if sys.platform.startswith('win') and (globals.GApp.systconf['vbox'].vboxwrapper_path.split('.')[-1] == 'exe'):
  25.113 @@ -150,10 +131,10 @@
  25.114              self.proc.start(sys.executable, [globals.GApp.systconf['vbox'].vboxwrapper_path, '--listen', binding, '--port', str(self.port), '--no-vbox-checks'])
  25.115  
  25.116          if self.proc.waitForStarted() == False:
  25.117 -            QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'VBox Manager', translate("VBoxManager", "Can't start VBox on port %i") % self.port)
  25.118 +            QtGui.QMessageBox.critical(globals.GApp.mainWindow, 'VBox Manager', translate("VBoxManager", "Can't start VBox on %s port %i") % (binding, self.port))
  25.119              return False
  25.120  
  25.121 -        self.waitVBox()
  25.122 +        self.waitVBox(binding)
  25.123          if self.proc and self.proc.state():
  25.124              debug("VBoxManager: VBox has been started with pid %i" % int(self.proc.pid()))
  25.125          return True
  25.126 @@ -177,62 +158,3 @@
  25.127              time.sleep(0.5)
  25.128              self.proc.close()
  25.129          self.proc = None
  25.130 -
  25.131 -#    def preloadVBoxwrapper(self):
  25.132 -#        """ Preload VBoxwrapper
  25.133 -#        """
  25.134 -#        #print "Entered VBoxManager::preloadVBoxwrapper()"
  25.135 -#
  25.136 -#        proc = QtCore.QProcess(globals.GApp.mainWindow)
  25.137 -#        binding = globals.GApp.systconf['vbox'].VBoxManager_binding
  25.138 -#
  25.139 -#        if globals.GApp.systconf['vbox'].vboxwrapper_workdir:
  25.140 -#            if not os.access(globals.GApp.systconf['vbox'].vboxwrapper_workdir, os.F_OK | os.W_OK):
  25.141 -#                QtGui.QMessageBox.warning(globals.GApp.mainWindow, 'VBox Manager',
  25.142 -#                                          translate("VBoxManager", "Working directory %s seems to not exist or be writable, please check") % globals.GApp.systconf['vbox'].vboxwrapper_workdir)
  25.143 -#                return False
  25.144 -#            # set the working directory
  25.145 -#            proc.setWorkingDirectory(globals.GApp.systconf['vbox'].vboxwrapper_workdir)
  25.146 -#
  25.147 -#        # start VBoxwrapper, use python on all platform but Windows (in release mode)
  25.148 -#        if sys.platform.startswith('win')  and (globals.GApp.systconf['vbox'].vboxwrapper_path.split('.')[-1] == 'exe'):
  25.149 -#            # On Windows hosts, we remove python dependency by pre-compiling VBoxwrapper. (release mode)
  25.150 -#            proc.start('"' + globals.GApp.systconf['vbox'].vboxwrapper_path + '"', ['--listen', binding, '--no-vbox-checks'])
  25.151 -#        elif hasattr(sys, "frozen"):
  25.152 -#            proc.start('python',  [globals.GApp.systconf['vbox'].vboxwrapper_path, '--listen', binding, '--no-vbox-checks'])
  25.153 -#        else:
  25.154 -#            proc.start(sys.executable,  [globals.GApp.systconf['vbox'].vboxwrapper_path, '--listen', binding, '--no-vbox-checks'])
  25.155 -#
  25.156 -#        if proc.waitForStarted() == False:
  25.157 -#            return False
  25.158 -#
  25.159 -#        # give 5 seconds to the hypervisor to accept connections
  25.160 -#        count = 5
  25.161 -#        connection_success = False
  25.162 -#        for nb in range(count + 1):
  25.163 -#            #print "ADEBUG: VBoxManager.py: binding = " + binding
  25.164 -#            if binding.__contains__(':'):
  25.165 -#                # IPv6 address support
  25.166 -#                s = socket(AF_INET6, SOCK_STREAM)
  25.167 -#            else:
  25.168 -#                s = socket(AF_INET, SOCK_STREAM)
  25.169 -#            s.setblocking(0)
  25.170 -#            s.settimeout(300)
  25.171 -#            try:
  25.172 -#                s.connect((binding, self.port))
  25.173 -#            except:
  25.174 -#                s.close()
  25.175 -#                time.sleep(1)
  25.176 -#                continue
  25.177 -#            connection_success = True
  25.178 -#            break
  25.179 -#        if connection_success:
  25.180 -#            # check vboxwrapper version
  25.181 -#
  25.182 -#            s.close()
  25.183 -#            proc.close()
  25.184 -#            return True
  25.185 -#        if proc.state():
  25.186 -#            s.close()
  25.187 -#            proc.close()
  25.188 -#        return False