Hello community,

here is the log from the commit of package gns3-server for openSUSE:Factory 
checked in at 2017-08-08 11:58:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gns3-server (Old)
 and      /work/SRC/openSUSE:Factory/.gns3-server.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gns3-server"

Tue Aug  8 11:58:55 2017 rev:10 rq:511359 version:2.0.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/gns3-server/gns3-server.changes  2017-05-17 
17:19:00.911482097 +0200
+++ /work/SRC/openSUSE:Factory/.gns3-server.new/gns3-server.changes     
2017-08-08 11:58:57.002470661 +0200
@@ -1,0 +2,8 @@
+Sat Jun 24 19:42:05 UTC 2017 - mrueck...@suse.de
+
+- update to 2.0.3
+  https://github.com/GNS3/gns3-server/releases/tag/v2.0.1
+  https://github.com/GNS3/gns3-server/releases/tag/v2.0.2
+  https://github.com/GNS3/gns3-server/releases/tag/v2.0.3
+
+-------------------------------------------------------------------

Old:
----
  gns3-server-2.0.0.tar.gz

New:
----
  gns3-server-2.0.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ gns3-server.spec ++++++
--- /var/tmp/diff_new_pack.dAF1Fo/_old  2017-08-08 11:58:59.118172678 +0200
+++ /var/tmp/diff_new_pack.dAF1Fo/_new  2017-08-08 11:58:59.146168735 +0200
@@ -27,28 +27,28 @@
 Summary:        GNS3 is a graphical network simulator
 License:        GPL-3.0+
 Group:          Productivity/Networking/Other
-Version:        2.0.0
+Version:        2.0.3
 Release:        0
 Url:            http://www.gns3.net/
 Source0:        %{name}-%{version}.tar.gz
 Source1:               %{name}-rpmlintrc
+BuildRequires:  busybox
 BuildRequires:  python3-devel >= 3.3
 BuildRequires:  python3-pip
 BuildRequires:  python3-setuptools
-BuildRequires: busybox
+Requires:       busybox
 Requires:       cpulimit
-Requires:       dynamips >= 0.2.11
 Requires:              docker
+Requires:       dynamips >= 0.2.11
 Requires:       iouyap
 Requires:       python3-Jinja2 >= 2.7.3
 Requires:       python3-aiohttp >= 0.21.5
+Requires:       python3-docker-py >= 1.4.0
 Requires:       python3-jsonschema >= 2.4.0
-Requires:       python3-raven >= 5.2.0
 Requires:              python3-psutil >= 3.0.0
-Requires:              python3-docker-py >= 1.4.0
+Requires:       python3-raven >= 5.2.0
 Requires:              python3-zipstream >= 1.1.3
 Requires:       qemu
-Requires:              busybox
 Requires:       vpcs >= 0.5b1
 Requires:       wireshark
 %if 0%{?suse_version}

++++++ gns3-server-2.0.0.tar.gz -> gns3-server-2.0.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/.gitignore 
new/gns3-server-2.0.3/.gitignore
--- old/gns3-server-2.0.0/.gitignore    2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/.gitignore    2017-06-13 10:35:50.000000000 +0200
@@ -53,3 +53,6 @@
 vpcs.hist
 startup.vpcs
 .gns3_shell_history
+
+# Virtualenv
+env
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/.travis.yml 
new/gns3-server-2.0.3/.travis.yml
--- old/gns3-server-2.0.0/.travis.yml   2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/.travis.yml   2017-06-13 10:35:50.000000000 +0200
@@ -9,7 +9,8 @@
 - python setup.py install
 - pip install -rdev-requirements.txt
 script:
-- py.test -v -s tests
+- mkdir ‡
+- py.test -v -s tests --basetemp=‡
 deploy:
   provider: pypi
   user: noplay
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/CHANGELOG 
new/gns3-server-2.0.3/CHANGELOG
--- old/gns3-server-2.0.0/CHANGELOG     2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/CHANGELOG     2017-06-13 10:35:50.000000000 +0200
@@ -1,5 +1,62 @@
 # Change Log
 
+## 2.0.3 13/06/2017
+
+* Fixes #1068 - handle zipfile encoding issues at project duplication
+* Fix: #1066 - Catching parsing errors at linked vbox file
+* Ignoring virtualenv directory at gitignore
+* Escaping VPCS name in regex #1067
+* Fix racecondition when listing interface
+* Fix Qemu disk creation with unicode characters not supported by local 
filesystem #1058 (#1063)
+* Fix when config file doesn't have computes section (#1062)
+* Check aiohttp version
+
+## 2.0.2 30/05/2017
+
+* Set correct permission on ubridge when doing a remote installation
+* Remote install script should be totally non interactive
+* Duplicate project on remote server use UUID
+* Fix import of some old topologies from 1.3
+* Fix error in logging of error during starting GNS3 VM
+* Fix an error when logging Docker container fail to start
+* Use docker version in error message of outdated docker installation
+* Support images created by "docker commit". Fixes #1039
+* Do not wait auto start to finish in order to complete project opening
+* Improve logging for remote server connection lost
+
+## 2.0.1 16/05/2017
+
+* Handle HTTP 504 errors from compute node
+* When connecting to a compute node ask for qemu images list
+* When importing portable project NAT node is loaded on GNS3 VM
+* Fix port numbering for Wic slot 1 & 2
+* Fixes issue with connections when loading an ATM switch.
+* Fixes ATM mapping.
+* Fixes Frame-relay VC mapping.
+* Fix export project is looking into the wrong directory
+* Fix a race condition in logging when ubridge exit fast
+* Fix conversion issue with old topology with C3640
+* Fix error when you have a directory in your symbols directory
+* Catch VMWare errors when getting status after GNS3 VM start
+* Make sure upstart LANG is utf8
+* Always install typing module (compat with python 3.4 on ubuntu)
+* Fix KeyError: 'filename'
+* Catch missing function listxattr on some Linux host.
+* Sort image list
+* Handle a race condition at project closing
+* Fix unicode error when reading ios configuration
+* Fix AttributeError: 'NoneType' object has no attribute 'send'
+* Fix a conversion issue with some 1.3 topologies
+* Fix an error with ethernetswitch when ethertype is null
+* Raise an error if we can't create the dynamips configuration directory
+* Catch timeout error when loading virtualbox VM
+* Handle broken compute at server startup
+* Catch error when we can't backup the topology
+* Catch error when writting the topology file on read only device
+* Catch a race condition in VirtualBox when editing and linking
+* Fix a race condition when editing a qemu vm and connecting it
+* Docker aux console is a VT100 terminal
+
 ## 2.0.0 02/05/2017
 
 * Fix connection to websocket with last docker release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/README.rst 
new/gns3-server-2.0.3/README.rst
--- old/gns3-server-2.0.0/README.rst    2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/README.rst    2017-06-13 10:35:50.000000000 +0200
@@ -22,7 +22,7 @@
 master is the next stable release, you can test it in your day to day 
activities.
 Bug fixes or small improvements pull requests go here.
 
-1.x (1.4 for example)
+2.x (2.1 for example)
 ********
 Next major release
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/dev-requirements.txt 
new/gns3-server-2.0.3/dev-requirements.txt
--- old/gns3-server-2.0.0/dev-requirements.txt  2017-05-02 10:16:11.000000000 
+0200
+++ new/gns3-server-2.0.3/dev-requirements.txt  2017-06-13 10:35:50.000000000 
+0200
@@ -1,7 +1,7 @@
 -rrequirements.txt
 
-sphinx==1.5.5
-pytest==3.0.7
+sphinx==1.6.2
+pytest==3.1.1
 pep8==1.7.0
 pytest-catchlog==1.2.2
 pytest-timeout==1.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/compute/base_manager.py 
new/gns3-server-2.0.3/gns3server/compute/base_manager.py
--- old/gns3-server-2.0.0/gns3server/compute/base_manager.py    2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/base_manager.py    2017-06-13 
10:35:50.000000000 +0200
@@ -344,7 +344,7 @@
                 # test the 2nd byte and check if the 13th bit (CAP_NET_RAW) is 
set
                 if struct.unpack("<IIIII", caps)[1] & 1 << 13:
                     return True
-        except OSError as e:
+        except (AttributeError, OSError) as e:
             log.error("could not determine if CAP_NET_RAW capability is set 
for {}: {}".format(executable, e))
 
         return False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/compute/base_node.py 
new/gns3-server-2.0.3/gns3server/compute/base_node.py
--- old/gns3-server-2.0.0/gns3server/compute/base_node.py       2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/base_node.py       2017-06-13 
10:35:50.000000000 +0200
@@ -541,8 +541,9 @@
             self._ubridge_hypervisor = Hypervisor(self._project, 
self.ubridge_path, self.working_dir, server_host)
         log.info("Starting new uBridge hypervisor 
{}:{}".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port))
         yield from self._ubridge_hypervisor.start()
-        log.info("Hypervisor {}:{} has successfully 
started".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port))
-        yield from self._ubridge_hypervisor.connect()
+        if self._ubridge_hypervisor:
+            log.info("Hypervisor {}:{} has successfully 
started".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port))
+            yield from self._ubridge_hypervisor.connect()
 
     @asyncio.coroutine
     def _stop_ubridge(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/docker/__init__.py 
new/gns3-server-2.0.3/gns3server/compute/docker/__init__.py
--- old/gns3-server-2.0.0/gns3server/compute/docker/__init__.py 2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/docker/__init__.py 2017-06-13 
10:35:50.000000000 +0200
@@ -33,7 +33,9 @@
 log = logging.getLogger(__name__)
 
 
+# Be carefull to keep it consistent
 DOCKER_MINIMUM_API_VERSION = "1.25"
+DOCKER_MINIMUM_VERSION = "1.13"
 
 
 class Docker(BaseManager):
@@ -60,7 +62,7 @@
                 self._connected = False
                 raise DockerError("Can't connect to docker daemon")
             if parse_version(version["ApiVersion"]) < 
parse_version(DOCKER_MINIMUM_API_VERSION):
-                raise DockerError("Docker API version is {}. GNS3 requires a 
minimum API version of {}".format(version["ApiVersion"], 
DOCKER_MINIMUM_API_VERSION))
+                raise DockerError("Docker version is {}. GNS3 requires a 
minimum version of {}".format(version["Version"], DOCKER_MINIMUM_VERSION))
 
     def connector(self):
         if self._connector is None or self._connector.closed:
@@ -113,11 +115,13 @@
         :returns: HTTP response
         """
         data = json.dumps(data)
-        url = "http://docker/v"; + DOCKER_MINIMUM_API_VERSION + "/" + path
-
         if timeout is None:
             timeout = 60 * 60 * 24 * 31  # One month timeout
 
+        if path == 'version':
+            url = "http://docker/v1.12/"; + path         # API of docker v1.0
+        else:
+            url = "http://docker/v"; + DOCKER_MINIMUM_API_VERSION + "/" + path
         try:
             if path != "version":  # version is use by check connection
                 yield from self._check_connection()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/docker/docker_vm.py 
new/gns3-server-2.0.3/gns3server/compute/docker/docker_vm.py
--- old/gns3-server-2.0.0/gns3server/compute/docker/docker_vm.py        
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/docker/docker_vm.py        
2017-06-13 10:35:50.000000000 +0200
@@ -213,7 +213,7 @@
 
         self._volumes = ["/etc/network"]
 
-        volumes = image_infos.get("ContainerConfig", {}).get("Volumes")
+        volumes = image_infos.get("Config", {}).get("Volumes")
         if volumes is None:
             return binds
         for volume in volumes.keys():
@@ -361,7 +361,7 @@
                     try:
                         yield from self._add_ubridge_connection(nio, 
adapter_number)
                     except UbridgeNamespaceError:
-                        log.error("Container {} failed to start", self.name)
+                        log.error("Container %s failed to start", self.name)
                         yield from self.stop()
 
                         # The container can crash soon after the start, this 
means we can not move the interface to the container namespace
@@ -393,7 +393,7 @@
         # We can not use the API because docker doesn't expose a websocket api 
for exec
         # https://github.com/GNS3/gns3-gui/issues/1039
         process = yield from asyncio.subprocess.create_subprocess_exec(
-            "docker", "exec", "-i", self._cid, "/gns3/bin/busybox", "script", 
"-qfc", "while true; do /gns3/bin/busybox sh; done", "/dev/null",
+            "docker", "exec", "-i", self._cid, "/gns3/bin/busybox", "script", 
"-qfc", "while true; do TERM=vt100 /gns3/bin/busybox sh; done", "/dev/null",
             stdout=asyncio.subprocess.PIPE,
             stderr=asyncio.subprocess.STDOUT,
             stdin=asyncio.subprocess.PIPE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/atm_switch.py 
new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/atm_switch.py
--- old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/atm_switch.py       
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/atm_switch.py       
2017-06-13 10:35:50.000000000 +0200
@@ -188,22 +188,33 @@
             raise DynamipsError("Port {} is not allocated".format(port_number))
 
         # remove VCs mapped with the port
-        pvc_entry = re.compile(r"""^([0-9]*):([0-9]*):([0-9]*)$""")
         for source, destination in self._active_mappings.copy().items():
-            match_source_pvc = pvc_entry.search(source)
-            match_destination_pvc = pvc_entry.search(destination)
-            if match_source_pvc and match_destination_pvc:
+            if len(source) == 3 and len(destination) == 3:
                 # remove the virtual channels mapped with this port/nio
-                source_port, source_vpi, source_vci = map(int, 
match_source_pvc.group(1, 2, 3))
-                destination_port, destination_vpi, destination_vci = map(int, 
match_destination_pvc.group(1, 2, 3))
+                source_port, source_vpi, source_vci = source
+                destination_port, destination_vpi, destination_vci = 
destination
                 if port_number == source_port:
+                    log.info('ATM switch "{name}" [{id}]: unmapping VCC 
between port {source_port} VPI {source_vpi} VCI {source_vci} and port 
{destination_port} VPI {destination_vpi} VCI 
{destination_vci}'.format(name=self._name,
+                                                                               
                                                                                
                                                      id=self._id,
+                                                                               
                                                                                
                                                      source_port=source_port,
+                                                                               
                                                                                
                                                      source_vpi=source_vpi,
+                                                                               
                                                                                
                                                      source_vci=source_vci,
+                                                                               
                                                                                
                                                      
destination_port=destination_port,
+                                                                               
                                                                                
                                                      
destination_vpi=destination_vpi,
+                                                                               
                                                                                
                                                      
destination_vci=destination_vci))
                     yield from self.unmap_pvc(source_port, source_vpi, 
source_vci, destination_port, destination_vpi, destination_vci)
                     yield from self.unmap_pvc(destination_port, 
destination_vpi, destination_vci, source_port, source_vpi, source_vci)
             else:
                 # remove the virtual paths mapped with this port/nio
-                source_port, source_vpi = map(int, source.split(':'))
-                destination_port, destination_vpi = map(int, 
destination.split(':'))
+                source_port, source_vpi = source
+                destination_port, destination_vpi = destination
                 if port_number == source_port:
+                    log.info('ATM switch "{name}" [{id}]: unmapping VPC 
between port {source_port} VPI {source_vpi} and port {destination_port} VPI 
{destination_vpi}'.format(name=self._name,
+                                                                               
                                                                                
               id=self._id,
+                                                                               
                                                                                
               source_port=source_port,
+                                                                               
                                                                                
               source_vpi=source_vpi,
+                                                                               
                                                                                
               destination_port=destination_port,
+                                                                               
                                                                                
               destination_vpi=destination_vpi))
                     yield from self.unmap_vp(source_port, source_vpi, 
destination_port, destination_vpi)
                     yield from self.unmap_vp(destination_port, 
destination_vpi, source_port, source_vpi)
 
@@ -239,6 +250,14 @@
                 if self.has_port(destination_port):
                     if (source_port, source_vpi, source_vci) not in 
self._active_mappings and \
                        (destination_port, destination_vpi, destination_vci) 
not in self._active_mappings:
+                        log.info('ATM switch "{name}" [{id}]: mapping VCC 
between port {source_port} VPI {source_vpi} VCI {source_vci} and port 
{destination_port} VPI {destination_vpi} VCI 
{destination_vci}'.format(name=self._name,
+                                                                               
                                                                                
                                                        id=self._id,
+                                                                               
                                                                                
                                                        source_port=source_port,
+                                                                               
                                                                                
                                                        source_vpi=source_vpi,
+                                                                               
                                                                                
                                                        source_vci=source_vci,
+                                                                               
                                                                                
                                                        
destination_port=destination_port,
+                                                                               
                                                                                
                                                        
destination_vpi=destination_vpi,
+                                                                               
                                                                                
                                                        
destination_vci=destination_vci))
                         yield from self.map_pvc(source_port, source_vpi, 
source_vci, destination_port, destination_vpi, destination_vci)
                         yield from self.map_pvc(destination_port, 
destination_vpi, destination_vci, source_port, source_vpi, source_vci)
             else:
@@ -247,6 +266,12 @@
                 destination_port, destination_vpi = map(int, 
destination.split(':'))
                 if self.has_port(destination_port):
                     if (source_port, source_vpi) not in self._active_mappings 
and (destination_port, destination_vpi) not in self._active_mappings:
+                        log.info('ATM switch "{name}" [{id}]: mapping VPC 
between port {source_port} VPI {source_vpi} and port {destination_port} VPI 
{destination_vpi}'.format(name=self._name,
+                                                                               
                                                                                
                 id=self._id,
+                                                                               
                                                                                
                 source_port=source_port,
+                                                                               
                                                                                
                 source_vpi=source_vpi,
+                                                                               
                                                                                
                 destination_port=destination_port,
+                                                                               
                                                                                
                 destination_vpi=destination_vpi))
                         yield from self.map_vp(source_port, source_vpi, 
destination_port, destination_vpi)
                         yield from self.map_vp(destination_port, 
destination_vpi, source_port, source_vpi)
 
@@ -262,10 +287,10 @@
         """
 
         if port1 not in self._nios:
-            raise DynamipsError("Port {} is not allocated".format(port1))
+            return
 
         if port2 not in self._nios:
-            raise DynamipsError("Port {} is not allocated".format(port2))
+            return
 
         nio1 = self._nios[port1]
         nio2 = self._nios[port2]
@@ -283,7 +308,7 @@
                                                                                
                                           port2=port2,
                                                                                
                                           vpi2=vpi2))
 
-        self._active_mappings["{}:{}".format(port1, vpi1)] = 
"{}:{}".format(port2, vpi2)
+        self._active_mappings[(port1, vpi1)] = (port2, vpi2)
 
     @asyncio.coroutine
     def unmap_vp(self, port1, vpi1, port2, vpi2):
@@ -297,10 +322,10 @@
         """
 
         if port1 not in self._nios:
-            raise DynamipsError("Port {} is not allocated".format(port1))
+            return
 
         if port2 not in self._nios:
-            raise DynamipsError("Port {} is not allocated".format(port2))
+            return
 
         nio1 = self._nios[port1]
         nio2 = self._nios[port2]
@@ -318,7 +343,7 @@
                                                                                
                                           port2=port2,
                                                                                
                                           vpi2=vpi2))
 
-        del self._active_mappings["{}:{}".format(port1, vpi1)]
+        del self._active_mappings[(port1, vpi1)]
 
     @asyncio.coroutine
     def map_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
@@ -334,10 +359,10 @@
         """
 
         if port1 not in self._nios:
-            raise DynamipsError("Port {} is not allocated".format(port1))
+            return
 
         if port2 not in self._nios:
-            raise DynamipsError("Port {} is not allocated".format(port2))
+            return
 
         nio1 = self._nios[port1]
         nio2 = self._nios[port2]
@@ -359,7 +384,7 @@
                                                                                
                                                                 vpi2=vpi2,
                                                                                
                                                                 vci2=vci2))
 
-        self._active_mappings["{}:{}:{}".format(port1, vpi1, vci1)] = 
"{}:{}:{}".format(port2, vpi2, vci2)
+        self._active_mappings[(port1, vpi1, vci1)] = (port2, vpi2, vci2)
 
     @asyncio.coroutine
     def unmap_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
@@ -375,10 +400,10 @@
         """
 
         if port1 not in self._nios:
-            raise DynamipsError("Port {} is not allocated".format(port1))
+            return
 
         if port2 not in self._nios:
-            raise DynamipsError("Port {} is not allocated".format(port2))
+            return
 
         nio1 = self._nios[port1]
         nio2 = self._nios[port2]
@@ -399,7 +424,7 @@
                                                                                
                                                                 port2=port2,
                                                                                
                                                                 vpi2=vpi2,
                                                                                
                                                                 vci2=vci2))
-        del self._active_mappings["{}:{}:{}".format(port1, vpi1, vci1)]
+        del self._active_mappings[(port1, vpi1, vci1)]
 
     @asyncio.coroutine
     def start_capture(self, port_number, output_file, 
data_link_type="DLT_ATM_RFC1483"):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/bridge.py 
new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/bridge.py
--- old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/bridge.py   
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/bridge.py   
2017-06-13 10:35:50.000000000 +0200
@@ -103,8 +103,8 @@
 
         :param nio: NIO instance to remove
         """
-
-        yield from self._hypervisor.send('nio_bridge remove_nio "{name}" 
{nio}'.format(name=self._name, nio=nio))
+        if self._hypervisor:
+            yield from self._hypervisor.send('nio_bridge remove_nio "{name}" 
{nio}'.format(name=self._name, nio=nio))
         self._nios.remove(nio)
 
     @property
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/ethernet_switch.py 
new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/ethernet_switch.py
--- old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/ethernet_switch.py  
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/ethernet_switch.py  
2017-06-13 10:35:50.000000000 +0200
@@ -246,7 +246,7 @@
         elif settings["type"] == "dot1q":
             yield from self.set_dot1q_port(port_number, settings["vlan"])
         elif settings["type"] == "qinq":
-            yield from self.set_qinq_port(port_number, settings["vlan"], 
settings["ethertype"])
+            yield from self.set_qinq_port(port_number, settings["vlan"], 
settings.get("ethertype"))
 
     @asyncio.coroutine
     def set_access_port(self, port_number, vlan_id):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/frame_relay_switch.py 
new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/frame_relay_switch.py
--- 
old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/frame_relay_switch.py   
    2017-05-02 10:16:11.000000000 +0200
+++ 
new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/frame_relay_switch.py   
    2017-06-13 10:35:50.000000000 +0200
@@ -191,9 +191,15 @@
 
         # remove VCs mapped with the port
         for source, destination in self._active_mappings.copy().items():
-            source_port, source_dlci = map(int, source.split(':'))
-            destination_port, destination_dlci = map(int, 
destination.split(':'))
+            source_port, source_dlci = source
+            destination_port, destination_dlci = destination
             if port_number == source_port:
+                log.info('Frame Relay switch "{name}" [{id}]: unmapping VC 
between port {source_port} DLCI {source_dlci} and port {destination_port} DLCI 
{destination_dlci}'.format(name=self._name,
+                                                                               
                                                                                
                      id=self._id,
+                                                                               
                                                                                
                      source_port=source_port,
+                                                                               
                                                                                
                      source_dlci=source_dlci,
+                                                                               
                                                                                
                      destination_port=destination_port,
+                                                                               
                                                                                
                      destination_dlci=destination_dlci))
                 yield from self.unmap_vc(source_port, source_dlci, 
destination_port, destination_dlci)
                 yield from self.unmap_vc(destination_port, destination_dlci, 
source_port, source_dlci)
 
@@ -224,6 +230,13 @@
             destination_port, destination_dlci = map(int, 
destination.split(':'))
             if self.has_port(destination_port):
                 if (source_port, source_dlci) not in self._active_mappings and 
(destination_port, destination_dlci) not in self._active_mappings:
+                    log.info('Frame Relay switch "{name}" [{id}]: mapping VC 
between port {source_port} DLCI {source_dlci} and port {destination_port} DLCI 
{destination_dlci}'.format(name=self._name,
+                                                                               
                                                                                
                        id=self._id,
+                                                                               
                                                                                
                        source_port=source_port,
+                                                                               
                                                                                
                        source_dlci=source_dlci,
+                                                                               
                                                                                
                        destination_port=destination_port,
+                                                                               
                                                                                
                        destination_dlci=destination_dlci))
+
                     yield from self.map_vc(source_port, source_dlci, 
destination_port, destination_dlci)
                     yield from self.map_vc(destination_port, destination_dlci, 
source_port, source_dlci)
 
@@ -260,7 +273,7 @@
                                                                                
                                                      port2=port2,
                                                                                
                                                      dlci2=dlci2))
 
-        self._active_mappings["{}:{}".format(port1, dlci1)] = 
"{}:{}".format(port2, dlci2)
+        self._active_mappings[(port1, dlci1)] = (port2, dlci2)
 
     @asyncio.coroutine
     def unmap_vc(self, port1, dlci1, port2, dlci2):
@@ -294,7 +307,7 @@
                                                                                
                                                      dlci1=dlci1,
                                                                                
                                                      port2=port2,
                                                                                
                                                      dlci2=dlci2))
-        del self._active_mappings["{}:{}".format(port1, dlci1)]
+        del self._active_mappings[(port1, dlci1)]
 
     @asyncio.coroutine
     def start_capture(self, port_number, output_file, 
data_link_type="DLT_FRELAY"):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/router.py 
new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/router.py
--- old/gns3-server-2.0.0/gns3server/compute/dynamips/nodes/router.py   
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/dynamips/nodes/router.py   
2017-06-13 10:35:50.000000000 +0200
@@ -71,7 +71,10 @@
         super().__init__(name, node_id, project, manager, console=console, 
aux=aux, allocate_aux=aux)
 
         self._working_directory = 
os.path.join(self.project.module_working_directory(self.manager.module_name.lower()),
 self.id)
-        os.makedirs(os.path.join(self._working_directory, "configs"), 
exist_ok=True)
+        try:
+            os.makedirs(os.path.join(self._working_directory, "configs"), 
exist_ok=True)
+        except OSError as e:
+            raise DynamipsError("Can't create the dynamips config directory: 
{}".format(str(e)))
         if dynamips_id:
             self._convert_before_2_0_0_b3(dynamips_id)
 
@@ -1553,7 +1556,7 @@
             try:
                 startup_config_path = os.path.join(self._working_directory, 
startup_config)
                 if os.path.exists(startup_config_path):
-                    with open(startup_config_path) as f:
+                    with open(startup_config_path, encoding="utf-8") as f:
                         self._startup_config_content = f.read()
                 else:
                     self._startup_config_content = ''
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/qemu/__init__.py 
new/gns3-server-2.0.3/gns3server/compute/qemu/__init__.py
--- old/gns3-server-2.0.0/gns3server/compute/qemu/__init__.py   2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/qemu/__init__.py   2017-06-13 
10:35:50.000000000 +0200
@@ -247,8 +247,13 @@
                 directory = self.get_images_directory()
                 os.makedirs(directory, exist_ok=True)
                 path = os.path.join(directory, os.path.basename(path))
-            if os.path.exists(path):
-                raise QemuError("Could not create disk image {} already 
exist".format(path))
+
+            try:
+                if os.path.exists(path):
+                    raise QemuError("Could not create disk image {} already 
exist".format(path))
+            except UnicodeEncodeError:
+                raise QemuError("Could not create disk image {}, "
+                                "path contains characters not supported by 
filesystem".format(path))
 
             command = [qemu_img, "create", "-f", img_format]
             for option in sorted(options.keys()):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/compute/qemu/qemu_vm.py 
new/gns3-server-2.0.3/gns3server/compute/qemu/qemu_vm.py
--- old/gns3-server-2.0.0/gns3server/compute/qemu/qemu_vm.py    2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/qemu/qemu_vm.py    2017-06-13 
10:35:50.000000000 +0200
@@ -1131,9 +1131,13 @@
                                                                                
                  adapter_number=adapter_number))
 
         if self.ubridge:
-            yield from 
self._add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number),
-                                                        
self._local_udp_tunnels[adapter_number][1],
-                                                        nio)
+            try:
+                yield from 
self._add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number),
+                                                            
self._local_udp_tunnels[adapter_number][1],
+                                                            nio)
+            except IndexError:
+                raise QemuError('Adapter {adapter_number} does not exist on 
QEMU VM "{name}"'.format(name=self._name,
+                                                                               
                      adapter_number=adapter_number))
         elif self.is_running():
             raise QemuError("Sorry, adding a link to a started Qemu VM is not 
supported without using uBridge.")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/virtualbox/__init__.py 
new/gns3-server-2.0.3/gns3server/compute/virtualbox/__init__.py
--- old/gns3-server-2.0.0/gns3server/compute/virtualbox/__init__.py     
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/virtualbox/__init__.py     
2017-06-13 10:35:50.000000000 +0200
@@ -94,7 +94,7 @@
             if not vboxmanage_path:
                 vboxmanage_path = self.find_vboxmanage()
             if not vboxmanage_path:
-                raise VirtualBoxError("Could not found VBoxManage")
+                raise VirtualBoxError("Could not find VBoxManage")
 
             command = [vboxmanage_path, "--nologo", subcommand]
             command.extend(args)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/compute/virtualbox/virtualbox_vm.py 
new/gns3-server-2.0.3/gns3server/compute/virtualbox/virtualbox_vm.py
--- old/gns3-server-2.0.0/gns3server/compute/virtualbox/virtualbox_vm.py        
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/virtualbox/virtualbox_vm.py        
2017-06-13 10:35:50.000000000 +0200
@@ -209,7 +209,12 @@
         Fix the VM uuid in the case of linked clone
         """
         if os.path.exists(self._linked_vbox_file()):
-            tree = ET.parse(self._linked_vbox_file())
+            try:
+                tree = ET.parse(self._linked_vbox_file())
+            except ET.ParseError:
+                raise VirtualBoxError("Cannot modify VirtualBox linked nodes 
file. "
+                                      "File {} is 
corrupted.".format(self._linked_vbox_file()))
+
             machine = 
tree.getroot().find("{http://www.virtualbox.org/}Machine";)
             if machine is not None and machine.get("uuid") != "{" + self.id + 
"}":
 
@@ -968,9 +973,13 @@
                                                                                
                             adapter_number=adapter_number))
 
         if self.ubridge:
-            yield from 
self._add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number),
-                                                        
self._local_udp_tunnels[adapter_number][1],
-                                                        nio)
+            try:
+                yield from 
self._add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number),
+                                                            
self._local_udp_tunnels[adapter_number][1],
+                                                            nio)
+            except KeyError:
+                raise VirtualBoxError("Adapter {adapter_number} doesn't exist 
on VirtualBox VM '{name}'".format(name=self.name,
+                                                                               
                                 adapter_number=adapter_number))
             yield from self._control_vm("setlinkstate{} 
on".format(adapter_number + 1))
         else:
             vm_state = yield from self._get_vm_state()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/compute/vpcs/vpcs_vm.py 
new/gns3-server-2.0.3/gns3server/compute/vpcs/vpcs_vm.py
--- old/gns3-server-2.0.0/gns3server/compute/vpcs/vpcs_vm.py    2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/compute/vpcs/vpcs_vm.py    2017-06-13 
10:35:50.000000000 +0200
@@ -171,7 +171,8 @@
         if self.script_file:
             content = self.startup_script
             content = content.replace(self._name, new_name)
-            content = re.sub(r"^set pcname .+$", "set pcname " + new_name, 
content, flags=re.MULTILINE)
+            escaped_name = re.escape(new_name)
+            content = re.sub(r"^set pcname .+$", "set pcname " + escaped_name, 
content, flags=re.MULTILINE)
             self.startup_script = content
 
         super(VPCSVM, VPCSVM).name.__set__(self, new_name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/controller/__init__.py 
new/gns3-server-2.0.3/gns3server/controller/__init__.py
--- old/gns3-server-2.0.0/gns3server/controller/__init__.py     2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/__init__.py     2017-06-13 
10:35:50.000000000 +0200
@@ -82,12 +82,12 @@
                                                              
password=server_config.get("password", ""),
                                                              force=True)
         except aiohttp.web_exceptions.HTTPConflict as e:
-            log.fatal("Can't acces to the local server, make sure anything 
else is not running on the same port")
+            log.fatal("Can't access to the local server, make sure anything 
else is not running on the same port")
             sys.exit(1)
         for c in computes:
             try:
                 yield from self.add_compute(**c)
-            except (aiohttp.web_exceptions.HTTPConflict):
+            except (aiohttp.web_exceptions.HTTPConflict, KeyError):
                 pass  # Skip not available servers at loading
         yield from self.load_projects()
         try:
@@ -176,7 +176,7 @@
         if "gns3vm" in data:
             self.gns3vm.settings = data["gns3vm"]
 
-        return data["computes"]
+        return data.get("computes", [])
 
     @asyncio.coroutine
     def load_projects(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/controller/compute.py 
new/gns3-server-2.0.3/gns3server/controller/compute.py
--- old/gns3-server-2.0.0/gns3server/controller/compute.py      2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/compute.py      2017-06-13 
10:35:50.000000000 +0200
@@ -23,6 +23,7 @@
 import uuid
 import sys
 import io
+from operator import itemgetter
 
 from ..utils import parse_version
 from ..utils.images import list_images
@@ -528,7 +529,7 @@
                 raise aiohttp.web.HTTPForbidden(text=msg)
             elif response.status == 404:
                 raise aiohttp.web.HTTPNotFound(text="{} {} not 
found".format(method, path))
-            elif response.status == 408:
+            elif response.status == 408 or response.status == 504:
                 raise aiohttp.web.HTTPRequestTimeout(text="{} {} request 
timeout".format(method, path))
             elif response.status == 409:
                 try:
@@ -579,8 +580,10 @@
         Forward a call to the emulator on compute
         """
         try:
-            res = yield from self.http_query(method, "/{}/{}".format(type, 
path), data=data, timeout=None)
+            action = "/{}/{}".format(type, path)
+            res = yield from self.http_query(method, action, data=data, 
timeout=None)
         except aiohttp.errors.DisconnectedError:
+            log.error("Connection lost to %s during %s %s", self._id, method, 
action)
             raise aiohttp.web.HTTPGatewayTimeout()
         return res.json
 
@@ -600,6 +603,9 @@
                 for local_image in list_images(type):
                     if local_image['filename'] not in [i['filename'] for i in 
images]:
                         images.append(local_image)
+                images = sorted(images, key=itemgetter('filename'))
+            else:
+                images = sorted(images, key=itemgetter('image'))
         except OSError as e:
             raise ComputeError("Can't list images: {}".format(str(e)))
         return images
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/controller/export_project.py 
new/gns3-server-2.0.3/gns3server/controller/export_project.py
--- old/gns3-server-2.0.0/gns3server/controller/export_project.py       
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/export_project.py       
2017-06-13 10:35:50.000000000 +0200
@@ -190,6 +190,5 @@
         if os.path.exists(path):
             arcname = os.path.join("images", directory, 
os.path.basename(image))
             z.write(path, arcname)
-            break
-        else:
-            raise aiohttp.web.HTTPConflict(text="Topology could not be 
exported because the image {} is not available. If you use multiple server, we 
need a copy of the image on the main server.".format(path))
+            return
+    raise aiohttp.web.HTTPConflict(text="Topology could not be exported 
because the image {} is not available. If you use multiple server, we need a 
copy of the image on the main server.".format(image))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/controller/gns3vm/__init__.py 
new/gns3-server-2.0.3/gns3server/controller/gns3vm/__init__.py
--- old/gns3-server-2.0.0/gns3server/controller/gns3vm/__init__.py      
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/gns3vm/__init__.py      
2017-06-13 10:35:50.000000000 +0200
@@ -250,7 +250,7 @@
                                                             force=True)
                 except aiohttp.web.HTTPConflict:
                     pass
-                log.error("Can't start the GNS3 VM: {}", str(e))
+                log.error("Can't start the GNS3 VM: %s", str(e))
 
     @asyncio.coroutine
     def exit_vm(self):
@@ -287,7 +287,7 @@
                 yield from engine.start()
             except Exception as e:
                 yield from self._controller.delete_compute("vm")
-                log.error("Can't start the GNS3 VM: {}", str(e))
+                log.error("Can't start the GNS3 VM: {}".format(str(e)))
                 yield from compute.update(name="GNS3 VM 
({})".format(engine.vmname))
                 raise e
             yield from compute.update(name="GNS3 VM 
({})".format(engine.vmname),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/controller/gns3vm/virtualbox_gns3_vm.py 
new/gns3-server-2.0.3/gns3server/controller/gns3vm/virtualbox_gns3_vm.py
--- old/gns3-server-2.0.0/gns3server/controller/gns3vm/virtualbox_gns3_vm.py    
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/gns3vm/virtualbox_gns3_vm.py    
2017-06-13 10:35:50.000000000 +0200
@@ -228,7 +228,7 @@
             try:
                 resp = None
                 resp = yield from 
session.get('http://127.0.0.1:{}/v2/compute/network/interfaces'.format(api_port))
-            except (OSError, aiohttp.errors.ClientHttpProcessingError, 
TimeoutError):
+            except (OSError, aiohttp.errors.ClientHttpProcessingError, 
TimeoutError, asyncio.TimeoutError):
                 pass
 
             if resp:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/controller/gns3vm/vmware_gns3_vm.py 
new/gns3-server-2.0.3/gns3server/controller/gns3vm/vmware_gns3_vm.py
--- old/gns3-server-2.0.0/gns3server/controller/gns3vm/vmware_gns3_vm.py        
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/gns3vm/vmware_gns3_vm.py        
2017-06-13 10:35:50.000000000 +0200
@@ -118,7 +118,10 @@
         if vmware_tools_state not in ("installed", "running"):
             raise GNS3VMError("VMware tools are not installed in 
{}".format(self.vmname))
 
-        running = yield from self._is_running()
+        try:
+            running = yield from self._is_running()
+        except VMwareError as e:
+            raise GNS3VMError("Could not list VMware VMs: {}".format(str(e)))
         if not running:
             log.info("Update GNS3 VM settings")
             # set the number of vCPUs and amount of RAM
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/controller/import_project.py 
new/gns3-server-2.0.3/gns3server/controller/import_project.py
--- old/gns3-server-2.0.0/gns3server/controller/import_project.py       
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/import_project.py       
2017-06-13 10:35:50.000000000 +0200
@@ -24,7 +24,6 @@
 import zipfile
 import aiohttp
 
-from ..config import Config
 from .topology import load_topology
 
 
@@ -74,7 +73,7 @@
                 path = location
             else:
                 projects_path = controller.projects_directory()
-                path = os.path.join(projects_path, project_name)
+                path = os.path.join(projects_path, project_id)
             try:
                 os.makedirs(path, exist_ok=True)
             except UnicodeEncodeError as e:
@@ -114,7 +113,7 @@
                 # unless it's a linux host without GNS3 VM
                 if not sys.platform.startswith("linux") or 
controller.has_compute("vm"):
                     for node in topology["topology"]["nodes"]:
-                        if node["node_type"] in ("docker", "qemu", "iou"):
+                        if node["node_type"] in ("docker", "qemu", "iou", 
"nat"):
                             node["compute_id"] = "vm"
                 else:
                     for node in topology["topology"]["nodes"]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/controller/ports/port.py 
new/gns3-server-2.0.3/gns3server/controller/ports/port.py
--- old/gns3-server-2.0.0/gns3server/controller/ports/port.py   2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/ports/port.py   2017-06-13 
10:35:50.000000000 +0200
@@ -70,6 +70,10 @@
             return self._name
         return self.short_name_type + "{}/{}".format(self._interface_number, 
self._port_number)
 
+    @short_name.setter
+    def short_name(self, val):
+        self._short_name = val
+
     def __json__(self):
         return {
             "name": self._name,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/controller/ports/port_factory.py 
new/gns3-server-2.0.3/gns3server/controller/ports/port_factory.py
--- old/gns3-server-2.0.0/gns3server/controller/ports/port_factory.py   
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/ports/port_factory.py   
2017-06-13 10:35:50.000000000 +0200
@@ -181,7 +181,9 @@
         ports = []
 
         adapter_number = 0
-        wic_port_number = 16
+        wic_slot = 1
+        wic_port_number = wic_slot * 16
+        display_wic_port_number = 0
         for name in sorted(properties.keys()):
             if name.startswith("slot") and properties[name]:
                 port_class = cls.ADAPTER_MATRIX[properties[name]]["port"]
@@ -194,7 +196,13 @@
                 port_class = cls.WIC_MATRIX[properties[name]]["port"]
                 if port_class:
                     for port_number in range(0, 
cls.WIC_MATRIX[properties[name]]["nb_ports"]):
-                        name = "{}{}/{}".format(port_class.long_name_type(), 
0, wic_port_number)
-                        ports.append(port_class(name, 0, 0, wic_port_number))
+                        name = "{}{}/{}".format(port_class.long_name_type(), 
0, display_wic_port_number)
+                        port = port_class(name, 0, 0, wic_port_number)
+                        port.short_name = 
"{}{}/{}".format(port.short_name_type, 0, display_wic_port_number)
+                        ports.append(port)
+                        display_wic_port_number += 1
                         wic_port_number += 1
+                    wic_slot += 1
+                    wic_port_number = wic_slot * 16
+
         return ports
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/controller/project.py 
new/gns3-server-2.0.3/gns3server/controller/project.py
--- old/gns3-server-2.0.0/gns3server/controller/project.py      2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/project.py      2017-06-13 
10:35:50.000000000 +0200
@@ -675,7 +675,10 @@
         self._loading = False
         # Should we start the nodes when project is open
         if self._auto_start:
-            yield from self.start_all()
+            # Start all in the background without waiting for completion
+            # we ignore errors because we want to let the user open
+            # their project and fix it
+            asyncio.async(self.start_all())
 
     @asyncio.coroutine
     def wait_loaded(self):
@@ -711,7 +714,7 @@
                         f.write(data)
                 with open(os.path.join(tmpdir, "project.gns3p"), "rb") as f:
                     project = yield from import_project(self._controller, 
str(uuid.uuid4()), f, location=location, name=name, keep_compute_id=True)
-        except OSError as e:
+        except (OSError, UnicodeEncodeError) as e:
             raise aiohttp.web.HTTPConflict(text="Can not duplicate project: 
{}".format(str(e)))
 
         if previous_status == "closed":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/controller/symbols.py 
new/gns3-server-2.0.3/gns3server/controller/symbols.py
--- old/gns3-server-2.0.0/gns3server/controller/symbols.py      2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/symbols.py      2017-06-13 
10:35:50.000000000 +0200
@@ -55,6 +55,8 @@
             for file in os.listdir(directory):
                 if file.startswith('.'):
                     continue
+                if not os.path.isfile(os.path.join(directory, file)):
+                    continue
                 symbol_id = file
                 symbols.append({
                     'symbol_id': symbol_id,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/controller/topology.py 
new/gns3-server-2.0.3/gns3server/controller/topology.py
--- old/gns3-server-2.0.0/gns3server/controller/topology.py     2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/controller/topology.py     2017-06-13 
10:35:50.000000000 +0200
@@ -125,7 +125,10 @@
     if "revision" not in topo or topo["revision"] < GNS3_FILE_FORMAT_REVISION:
         # If it's an old GNS3 file we need to convert it
         # first we backup the file
-        shutil.copy(path, path + ".backup{}".format(topo.get("revision", 0)))
+        try:
+            shutil.copy(path, path + ".backup{}".format(topo.get("revision", 
0)))
+        except (OSError) as e:
+            raise aiohttp.web.HTTPConflict(text="Can't write backup of the 
topology {}: {}".format(path, str(e)))
         changed = True
 
     if "revision" not in topo or topo["revision"] < 5:
@@ -146,8 +149,11 @@
         raise e
 
     if changed:
-        with open(path, "w+", encoding="utf-8") as f:
-            json.dump(topo, f, indent=4, sort_keys=True)
+        try:
+            with open(path, "w+", encoding="utf-8") as f:
+                json.dump(topo, f, indent=4, sort_keys=True)
+        except (OSError) as e:
+            raise aiohttp.web.HTTPConflict(text="Can't write the topology {}: 
{}".format(path, str(e)))
     return topo
 
 
@@ -283,6 +289,10 @@
 
         node["properties"] = {}
 
+        # Some old dynamips node don't have type
+        if "type" not in old_node:
+            old_node["type"] = old_node["properties"]["platform"].upper()
+
         if old_node["type"] == "VPCSDevice":
             node["node_type"] = "vpcs"
         elif old_node["type"] == "QemuVM":
@@ -300,7 +310,7 @@
             node["console_type"] = None
             node["symbol"] = ":/symbols/hub.svg"
             node["properties"]["ports_mapping"] = []
-            for port in old_node["ports"]:
+            for port in old_node.get("ports", []):
                 node["properties"]["ports_mapping"].append({
                     "name": "Ethernet{}".format(port["port_number"] - 1),
                     "port_number": port["port_number"] - 1
@@ -310,7 +320,7 @@
             node["symbol"] = ":/symbols/ethernet_switch.svg"
             node["console_type"] = None
             node["properties"]["ports_mapping"] = []
-            for port in old_node["ports"]:
+            for port in old_node.get("ports", []):
                 node["properties"]["ports_mapping"].append({
                     "name": "Ethernet{}".format(port["port_number"] - 1),
                     "port_number": port["port_number"] - 1,
@@ -321,13 +331,15 @@
             node["node_type"] = "frame_relay_switch"
             node["symbol"] = ":/symbols/frame_relay_switch.svg"
             node["console_type"] = None
-        elif old_node["type"] in ["C1700", "C2600", "C2691", "C3600", "C3725", 
"C3745", "C7200", "EtherSwitchRouter"]:
+        elif old_node["type"].upper() in ["C1700", "C2600", "C2691", "C3600", 
"C3620", "C3640", "C3660", "C3725", "C3745", "C7200", "EtherSwitchRouter"]:
             if node["symbol"] is None:
                 node["symbol"] = ":/symbols/router.svg"
             node["node_type"] = "dynamips"
             node["properties"]["dynamips_id"] = old_node.get("dynamips_id")
-            if "platform" not in node["properties"] and 
old_node["type"].startswith("C"):
+            if "platform" not in node["properties"] and 
old_node["type"].upper().startswith("C"):
                 node["properties"]["platform"] = old_node["type"].lower()
+                if node["properties"]["platform"].startswith("c36"):
+                    node["properties"]["platform"] = "c3600"
             if "ram" not in node["properties"] and 
old_node["type"].startswith("C"):
                 node["properties"]["ram"] = 
PLATFORMS_DEFAULT_RAM[old_node["type"].lower()]
         elif old_node["type"] == "VMwareVM":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/crash_report.py 
new/gns3-server-2.0.3/gns3server/crash_report.py
--- old/gns3-server-2.0.0/gns3server/crash_report.py    2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/crash_report.py    2017-06-13 
10:35:50.000000000 +0200
@@ -54,7 +54,7 @@
     Report crash to a third party service
     """
 
-    DSN = 
"sync+https://fd4397dee2e145da9227af29df24ded1:61a0e2c9b9f64204bb8ef7ac17b98...@sentry.io/38482";
+    DSN = 
"sync+https://9b15627f2ddf4e21a9880536354bfcb5:b31dee5d3abf4c74844895432193d...@sentry.io/38482";
     if hasattr(sys, "frozen"):
         cacert = get_resource("cacert.pem")
         if cacert is not None and os.path.isfile(cacert):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/handlers/api/compute/project_handler.py 
new/gns3-server-2.0.3/gns3server/handlers/api/compute/project_handler.py
--- old/gns3-server-2.0.0/gns3server/handlers/api/compute/project_handler.py    
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/handlers/api/compute/project_handler.py    
2017-06-13 10:35:50.000000000 +0200
@@ -112,7 +112,10 @@
         if ProjectHandler._notifications_listening.setdefault(project.id, 0) 
<= 1:
             yield from project.close()
             pm.remove_project(project.id)
-            del ProjectHandler._notifications_listening[project.id]
+            try:
+                del ProjectHandler._notifications_listening[project.id]
+            except KeyError:
+                pass
         else:
             log.warning("Skip project closing, another client is listening for 
project notifications")
         response.set_status(204)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/gns3server/handlers/api/controller/project_handler.py 
new/gns3-server-2.0.3/gns3server/handlers/api/controller/project_handler.py
--- old/gns3-server-2.0.0/gns3server/handlers/api/controller/project_handler.py 
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/handlers/api/controller/project_handler.py 
2017-06-13 10:35:50.000000000 +0200
@@ -23,7 +23,6 @@
 
 from gns3server.web.route import Route
 from gns3server.controller import Controller
-from gns3server.controller.project import Project
 from gns3server.controller.import_project import import_project
 from gns3server.controller.export_project import export_project
 from gns3server.config import Config
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/schemas/dynamips_vm.py 
new/gns3-server-2.0.3/gns3server/schemas/dynamips_vm.py
--- old/gns3-server-2.0.0/gns3server/schemas/dynamips_vm.py     2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/schemas/dynamips_vm.py     2017-06-13 
10:35:50.000000000 +0200
@@ -33,7 +33,7 @@
         },
         "dynamips_id": {
             "description": "Dynamips ID",
-            "type": "integer"
+            "type": ["integer", "null"]
         },
         "name": {
             "description": "Dynamips VM instance name",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/utils/interfaces.py 
new/gns3-server-2.0.3/gns3server/utils/interfaces.py
--- old/gns3-server-2.0.0/gns3server/utils/interfaces.py        2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/utils/interfaces.py        2017-06-13 
10:35:50.000000000 +0200
@@ -198,12 +198,13 @@
 
     results = []
     if not sys.platform.startswith("win"):
-        for interface in sorted(psutil.net_if_addrs().keys()):
+        net_if_addrs = psutil.net_if_addrs()
+        for interface in sorted(net_if_addrs.keys()):
             ip_address = ""
             mac_address = ""
             netmask = ""
             interface_type = "ethernet"
-            for addr in psutil.net_if_addrs()[interface]:
+            for addr in net_if_addrs[interface]:
                 # get the first available IPv4 address only
                 if addr.family == socket.AF_INET:
                     ip_address = addr.address
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/version.py 
new/gns3-server-2.0.3/gns3server/version.py
--- old/gns3-server-2.0.0/gns3server/version.py 2017-05-02 10:16:11.000000000 
+0200
+++ new/gns3-server-2.0.3/gns3server/version.py 2017-06-13 10:35:50.000000000 
+0200
@@ -23,7 +23,7 @@
 # or negative for a release candidate or beta (after the base version
 # number has been incremented)
 
-__version__ = "2.0.0"
+__version__ = "2.0.3"
 
 # If it's a git checkout try to add the commit
 if "dev" in __version__:
@@ -36,4 +36,4 @@
     except Exception as e:
         print(e)
 
-__version_info__ = (2, 0, 0, 0)
+__version_info__ = (2, 0, 3, 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/web/logger.py 
new/gns3-server-2.0.3/gns3server/web/logger.py
--- old/gns3-server-2.0.0/gns3server/web/logger.py      2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/web/logger.py      2017-06-13 
10:35:50.000000000 +0200
@@ -98,6 +98,16 @@
             self.handleError(record)
 
 
+class LogFilter:
+    """
+    This filter some noise from the logs
+    """
+    def filter(record):
+        if record.name == "aiohttp.access" and "/settings" in record.msg and 
"200" in record.msg:
+            return 0
+        return 1
+
+
 def init_logger(level, logfile=None, quiet=False):
     if logfile and len(logfile) > 0:
         stream_handler = logging.FileHandler(logfile)
@@ -111,5 +121,7 @@
     if quiet:
         stream_handler.addFilter(logging.Filter(name="user_facing"))
         logging.getLogger('user_facing').propagate = False
+    if level > logging.DEBUG:
+        stream_handler.addFilter(LogFilter)
     logging.basicConfig(level=level, handlers=[stream_handler])
     return logging.getLogger('user_facing')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/gns3server/web/web_server.py 
new/gns3-server-2.0.3/gns3server/web/web_server.py
--- old/gns3-server-2.0.0/gns3server/web/web_server.py  2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/gns3server/web/web_server.py  2017-06-13 
10:35:50.000000000 +0200
@@ -33,6 +33,7 @@
 from ..config import Config
 from ..compute import MODULES
 from ..compute.port_manager import PortManager
+from ..compute.qemu import Qemu
 from ..controller import Controller
 
 
@@ -42,6 +43,9 @@
 import logging
 log = logging.getLogger(__name__)
 
+if not aiohttp.__version__.startswith("1.3"):
+    raise RuntimeError("You need aiohttp 1.3 for running GNS3")
+
 
 class WebServer:
 
@@ -192,6 +196,10 @@
         Called when the HTTP server start
         """
         yield from Controller.instance().start()
+        # Because with a large image collection
+        # without md5sum already computed we start the
+        # computing with server start
+        asyncio.async(Qemu.instance().list_images())
 
     def run(self):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/init/gns3.conf.upstart 
new/gns3-server-2.0.3/init/gns3.conf.upstart
--- old/gns3-server-2.0.0/init/gns3.conf.upstart        2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/init/gns3.conf.upstart        2017-06-13 
10:35:50.000000000 +0200
@@ -1,5 +1,6 @@
 description "GNS3 server"
 author      "GNS3 Team"
+env LANG=en_US.UTF-8
 
 start on filesystem or runlevel [2345]
 stop on shutdown
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/requirements.txt 
new/gns3-server-2.0.3/requirements.txt
--- old/gns3-server-2.0.0/requirements.txt      2017-05-02 10:16:11.000000000 
+0200
+++ new/gns3-server-2.0.3/requirements.txt      2017-06-13 10:35:50.000000000 
+0200
@@ -6,3 +6,4 @@
 raven>=5.23.0
 psutil>=3.0.0
 zipstream>=1.1.4
+typing>=3.5.3.0 # Otherwise yarl fail with python 3.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/scripts/remote-install.sh 
new/gns3-server-2.0.3/scripts/remote-install.sh
--- old/gns3-server-2.0.0/scripts/remote-install.sh     2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/scripts/remote-install.sh     2017-06-13 
10:35:50.000000000 +0200
@@ -152,7 +152,7 @@
 apt-get update
 
 log "Upgrade packages"
-apt-get upgrade -y
+apt-get upgrade --yes --force-yes -o Dpkg::Options::="--force-confdef" -o 
Dpkg::Options::="--force-confold"
 
 log " Install GNS3 packages"
 apt-get install -y gns3-server
@@ -163,6 +163,10 @@
   useradd -d /opt/gns3/ -m gns3
 fi
 
+
+log "Add GNS3 to the ubridge group"
+usermod -aG ubridge gns3
+
 log "Install docker"
 if [ ! -f "/usr/bin/docker" ]
 then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/setup.py 
new/gns3-server-2.0.3/setup.py
--- old/gns3-server-2.0.0/setup.py      2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/setup.py      2017-06-13 10:35:50.000000000 +0200
@@ -40,9 +40,6 @@
 
 dependencies = open("requirements.txt", "r").read().splitlines()
 
-if sys.version_info <= (3, 4):
-    dependencies.append('typing>=3.5.3.0 # Otherwise yarl fail with python 
3.4')
-
 setup(
     name="gns3-server",
     version=__import__("gns3server").__version__,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/tests/compute/docker/test_docker_vm.py 
new/gns3-server-2.0.3/tests/compute/docker/test_docker_vm.py
--- old/gns3-server-2.0.0/tests/compute/docker/test_docker_vm.py        
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/compute/docker/test_docker_vm.py        
2017-06-13 10:35:50.000000000 +0200
@@ -840,7 +840,7 @@
 @pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on 
Windows")
 def test_mount_binds(vm, tmpdir):
     image_infos = {
-        "ContainerConfig": {
+        "Config": {
             "Volumes": {
                 "/test/experimental": {}
             }
@@ -879,7 +879,7 @@
 
     with asyncio_patch("asyncio.subprocess.create_subprocess_exec", 
return_value=MagicMock()) as mock_exec:
         loop.run_until_complete(asyncio.async(vm._start_aux()))
-    mock_exec.assert_called_with('docker', 'exec', '-i', 'e90e34656842', 
'/gns3/bin/busybox', 'script', '-qfc', 'while true; do /gns3/bin/busybox sh; 
done', '/dev/null', stderr=asyncio.subprocess.STDOUT, 
stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE)
+    mock_exec.assert_called_with('docker', 'exec', '-i', 'e90e34656842', 
'/gns3/bin/busybox', 'script', '-qfc', 'while true; do TERM=vt100 
/gns3/bin/busybox sh; done', '/dev/null', stderr=asyncio.subprocess.STDOUT, 
stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE)
 
 
 def test_create_network_interfaces(vm):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/tests/compute/qemu/test_qemu_manager.py 
new/gns3-server-2.0.3/tests/compute/qemu/test_qemu_manager.py
--- old/gns3-server-2.0.0/tests/compute/qemu/test_qemu_manager.py       
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/compute/qemu/test_qemu_manager.py       
2017-06-13 10:35:50.000000000 +0200
@@ -178,6 +178,26 @@
                 assert not process.called
 
 
+def test_create_image_with_not_supported_characters_by_filesystem(loop, 
tmpdir, fake_qemu_img_binary):
+    open(str(tmpdir / "hda.qcow2"), "w+").close()
+
+    options = {
+        "format": "raw",
+        "size": 100
+    }
+
+    # patching os.makedirs is necessary as it depends on already mocked 
os.path.exists
+    with asyncio_patch("asyncio.create_subprocess_exec", 
return_value=MagicMock()) as process, \
+        patch("gns3server.compute.qemu.Qemu.get_images_directory", 
return_value=str(tmpdir)), \
+        patch("os.path.exists", side_effect=UnicodeEncodeError('error', u"", 
1, 2, 'Emulated Unicode Err')),\
+        patch("os.makedirs"):
+
+        with pytest.raises(QemuError):
+            loop.run_until_complete(asyncio.async(Qemu.instance().create_disk(
+                fake_qemu_img_binary, "hda.qcow2", options)))
+            assert not process.called
+
+
 def test_get_kvm_archs_kvm_ok(loop):
 
     with patch("os.path.exists", return_value=True):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/tests/compute/virtualbox/test_virtualbox_vm.py 
new/gns3-server-2.0.3/tests/compute/virtualbox/test_virtualbox_vm.py
--- old/gns3-server-2.0.0/tests/compute/virtualbox/test_virtualbox_vm.py        
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/compute/virtualbox/test_virtualbox_vm.py        
2017-06-13 10:35:50.000000000 +0200
@@ -113,3 +113,15 @@
     with open(vm._linked_vbox_file()) as f:
         c = f.read()
         assert "{" + vm.id + "}" in c
+
+
+def test_patch_vm_uuid_with_corrupted_file(vm):
+    xml = """<?xml version="1.0"?>
+    <VirtualBox>
+    """
+    os.makedirs(os.path.join(vm.working_dir, vm._vmname), exist_ok=True)
+    with open(vm._linked_vbox_file(), "w+") as f:
+        f.write(xml)
+    vm._linked_clone = True
+    with pytest.raises(VirtualBoxError):
+        vm._patch_vm_uuid()
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/tests/compute/vpcs/test_vpcs_vm.py 
new/gns3-server-2.0.3/tests/compute/vpcs/test_vpcs_vm.py
--- old/gns3-server-2.0.0/tests/compute/vpcs/test_vpcs_vm.py    2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/compute/vpcs/test_vpcs_vm.py    2017-06-13 
10:35:50.000000000 +0200
@@ -251,6 +251,12 @@
         assert f.read() == "set pcname pc1\n"
 
 
+def test_update_startup_script_with_escaping_characters_in_name(vm):
+    vm.startup_script = "set pcname initial-name\n"
+    vm.name = "test\\"
+    assert vm.startup_script == "set pcname test\\\n"
+
+
 def test_get_startup_script(vm):
     content = "echo GNS3 VPCS\nip 192.168.1.2"
     vm.startup_script = content
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/tests/controller/test_compute.py 
new/gns3-server-2.0.3/tests/controller/test_compute.py
--- old/gns3-server-2.0.0/tests/controller/test_compute.py      2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/controller/test_compute.py      2017-06-13 
10:35:50.000000000 +0200
@@ -360,8 +360,10 @@
         images = async_run(compute.images("qemu"))
         mock.assert_called_with("GET", 
"https://example.com:84/v2/compute/qemu/images";, auth=None, data=None, 
headers={'content-type': 'application/json'}, chunked=False, timeout=None)
 
-    assert images == [{"filename": "linux.qcow2", "path": "linux.qcow2", 
"md5sum": "d41d8cd98f00b204e9800998ecf8427e", "filesize": 0},
-                      {"filename": "asa.qcow2", "path": "asa.qcow2", "md5sum": 
"d41d8cd98f00b204e9800998ecf8427e", "filesize": 0}]
+    assert images == [
+        {"filename": "asa.qcow2", "path": "asa.qcow2", "md5sum": 
"d41d8cd98f00b204e9800998ecf8427e", "filesize": 0},
+        {"filename": "linux.qcow2", "path": "linux.qcow2", "md5sum": 
"d41d8cd98f00b204e9800998ecf8427e", "filesize": 0}
+    ]
 
 
 def test_list_files(project, async_run, compute):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/tests/controller/test_controller.py 
new/gns3-server-2.0.3/tests/controller/test_controller.py
--- old/gns3-server-2.0.0/tests/controller/test_controller.py   2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/controller/test_controller.py   2017-06-13 
10:35:50.000000000 +0200
@@ -65,6 +65,16 @@
     assert controller.gns3vm.settings["vmname"] == "Test VM"
 
 
+def test_load_controller_settings_with_no_computes_section(controller, 
controller_config_path, async_run):
+    controller.save()
+    with open(controller_config_path) as f:
+        data = json.load(f)
+    del data['computes']
+    with open(controller_config_path, "w+") as f:
+        json.dump(data, f)
+    assert len(async_run(controller._load_controller_settings())) == 0
+
+
 def test_import_computes_1_x(controller, controller_config_path, async_run):
     """
     At first start the server should import the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/tests/controller/test_import_project.py 
new/gns3-server-2.0.3/tests/controller/test_import_project.py
--- old/gns3-server-2.0.0/tests/controller/test_import_project.py       
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/controller/test_import_project.py       
2017-06-13 10:35:50.000000000 +0200
@@ -35,6 +35,8 @@
     topology = {
         "project_id": str(uuid.uuid4()),
         "name": "test",
+        "auto_open": True,
+        "auto_start": True,
         "topology": {
         },
         "version": "2.0.0"
@@ -67,6 +69,8 @@
     # A new project name is generated when you import twice the same name
     with open(zip_path, "rb") as f:
         project = async_run(import_project(controller, str(uuid.uuid4()), f))
+    assert project.auto_open is False
+    assert project.auto_start is False
     assert project.name != "test"
 
 
@@ -228,6 +232,50 @@
                     "name": "test",
                     "properties": {}
                 }
+            ],
+            "links": [],
+            "computes": [],
+            "drawings": []
+        },
+        "revision": 5,
+        "version": "2.0.0"
+    }
+
+    with open(str(tmpdir / "project.gns3"), 'w+') as f:
+        json.dump(topology, f)
+
+    zip_path = str(tmpdir / "project.zip")
+    with zipfile.ZipFile(zip_path, 'w') as myzip:
+        myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
+
+    with open(zip_path, "rb") as f:
+        project = async_run(import_project(controller, project_id, f))
+
+    with open(os.path.join(project.path, "test.gns3")) as f:
+        topo = json.load(f)
+        assert topo["topology"]["nodes"][0]["compute_id"] == "vm"
+
+
+def test_import_nat_non_linux(windows_platform, async_run, tmpdir, controller):
+    """
+    On non linux host NAT should be moved to the GNS3 VM
+    """
+    project_id = str(uuid.uuid4())
+    controller._computes["vm"] = AsyncioMagicMock()
+
+    topology = {
+        "project_id": str(uuid.uuid4()),
+        "name": "test",
+        "type": "topology",
+        "topology": {
+            "nodes": [
+                {
+                    "compute_id": "local",
+                    "node_id": "0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b",
+                    "node_type": "nat",
+                    "name": "test",
+                    "properties": {}
+                }
             ],
             "links": [],
             "computes": [],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/tests/controller/test_node_port_name.py 
new/gns3-server-2.0.3/tests/controller/test_node_port_name.py
--- old/gns3-server-2.0.0/tests/controller/test_node_port_name.py       
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/controller/test_node_port_name.py       
2017-06-13 10:35:50.000000000 +0200
@@ -548,8 +548,8 @@
             "link_type": "ethernet"
         },
         {
-            "name": "Serial0/16",
-            "short_name": "s0/16",
+            "name": "Serial0/0",
+            "short_name": "s0/0",
             "data_link_types": {
                 "Cisco HDLC": "DLT_C_HDLC",
                 "Cisco PPP": "DLT_PPP_SERIAL",
@@ -559,8 +559,8 @@
             "link_type": "serial"
         },
         {
-            "name": "Serial0/17",
-            "short_name": "s0/17",
+            "name": "Serial0/1",
+            "short_name": "s0/1",
             "data_link_types": {
                 "Cisco HDLC": "DLT_C_HDLC",
                 "Cisco PPP": "DLT_PPP_SERIAL",
@@ -570,24 +570,24 @@
             "link_type": "serial"
         },
         {
-            "name": "Serial0/18",
-            "short_name": "s0/18",
+            "name": "Serial0/2",
+            "short_name": "s0/2",
             "data_link_types": {
                 "Cisco HDLC": "DLT_C_HDLC",
                 "Cisco PPP": "DLT_PPP_SERIAL",
                 "Frame Relay": "DLT_FRELAY"},
-            "port_number": 18,
+            "port_number": 32,
             "adapter_number": 0,
             "link_type": "serial"
         },
         {
-            "name": "Serial0/19",
-            "short_name": "s0/19",
+            "name": "Serial0/3",
+            "short_name": "s0/3",
             "data_link_types": {
                 "Cisco HDLC": "DLT_C_HDLC",
                 "Cisco PPP": "DLT_PPP_SERIAL",
                 "Frame Relay": "DLT_FRELAY"},
-            "port_number": 19,
+            "port_number": 33,
             "adapter_number": 0,
             "link_type": "serial"
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/tests/controller/test_project.py 
new/gns3-server-2.0.3/tests/controller/test_project.py
--- old/gns3-server-2.0.0/tests/controller/test_project.py      2017-05-02 
10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/controller/test_project.py      2017-06-13 
10:35:50.000000000 +0200
@@ -23,6 +23,7 @@
 import pytest
 import aiohttp
 import zipfile
+import zipstream
 from unittest.mock import MagicMock
 from tests.utils import AsyncioMagicMock, asyncio_patch
 from unittest.mock import patch
@@ -439,6 +440,15 @@
     assert list(new_project.nodes.values())[1].compute.id == "remote"
 
 
+def test_duplicate_with_zipfile_encoding_issues(project, async_run, 
controller):
+    zf = zipstream.ZipFile()
+    zf.writestr('test\udcc3', "data")
+
+    with asyncio_patch('gns3server.controller.project.export_project', 
return_value=zf):
+        with pytest.raises(aiohttp.web.HTTPConflict):
+            async_run(project.duplicate(name="Hello"))
+
+
 def test_snapshots(project):
     """
     List the snapshots
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/tests/handlers/api/controller/test_gns3vm.py 
new/gns3-server-2.0.3/tests/handlers/api/controller/test_gns3vm.py
--- old/gns3-server-2.0.0/tests/handlers/api/controller/test_gns3vm.py  
2017-05-02 10:16:11.000000000 +0200
+++ new/gns3-server-2.0.3/tests/handlers/api/controller/test_gns3vm.py  
2017-06-13 10:35:50.000000000 +0200
@@ -46,4 +46,3 @@
 def test_get_gns3vm(http_controller):
     response = http_controller.get('/gns3vm', example=True)
     assert response.status == 200
-    print(response.json)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/tests/topologies/1_3_dynamips_missing_type/after/1_3_dynamips.gns3
 
new/gns3-server-2.0.3/tests/topologies/1_3_dynamips_missing_type/after/1_3_dynamips.gns3
--- 
old/gns3-server-2.0.0/tests/topologies/1_3_dynamips_missing_type/after/1_3_dynamips.gns3
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/gns3-server-2.0.3/tests/topologies/1_3_dynamips_missing_type/after/1_3_dynamips.gns3
    2017-06-13 10:35:50.000000000 +0200
@@ -0,0 +1,77 @@
+{
+    "auto_start": false,
+    "name": "1_3_dynamips",
+    "project_id": "ba5790e1-2f51-443e-a3cc-1a2eee132888",
+    "revision": 6,
+    "topology": {
+        "computes": [
+            {
+                "compute_id": "local",
+                "host": "127.0.0.1",
+                "name": "Local",
+                "port": 8000,
+                "protocol": "http"
+            }
+        ],
+        "drawings": [],
+        "links": [],
+        "nodes": [
+            {
+                "symbol": ":/symbols/iosv_virl.svg",
+                "compute_id": "local",
+                "console": 2001,
+                "console_type": "telnet",
+                "label": {
+                    "rotation": 0,
+                    "style": "font-family: TypeWriter;font-size: 
10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+                    "text": "R1",
+                    "x": 22,
+                    "y": -25
+                },
+                "name": "R1",
+                "node_id": "0bce6ad5-c688-4d4d-a425-f21aaf3927e2",
+                "node_type": "dynamips",
+                "port_name_format": "Ethernet{0}",
+                "port_segment_size": 0,
+                "first_port_name": null,
+                "properties": {
+                    "dynamips_id": 1,
+                    "auto_delete_disks": true,
+                    "clock_divisor": 4,
+                    "disk0": 0,
+                    "disk1": 0,
+                    "exec_area": 64,
+                    "idlemax": 500,
+                    "idlesleep": 30,
+                    "image": "c7200-adventerprisek9-mz.124-24.T8.image",
+                    "mac_addr": "ca01.2f39.0000",
+                    "midplane": "vxr",
+                    "mmap": true,
+                    "npe": "npe-400",
+                    "nvram": 512,
+                    "platform": "c7200",
+                    "power_supplies": [
+                        1,
+                        1
+                    ],
+                    "ram": 512,
+                    "sensors": [
+                        22,
+                        22,
+                        22,
+                        22
+                    ],
+                    "slot0": "C7200-IO-FE",
+                    "sparsemem": true,
+                    "startup_config": "configs/i1_startup-config.cfg",
+                    "system_id": "FTX0945W0MY"
+                },
+                "x": -112,
+                "y": -100,
+                "z": 1
+            }
+        ]
+    },
+    "type": "topology",
+    "version": "ANYSTR"
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gns3-server-2.0.0/tests/topologies/1_3_dynamips_missing_type/before/1_3_dynamips.gns3
 
new/gns3-server-2.0.3/tests/topologies/1_3_dynamips_missing_type/before/1_3_dynamips.gns3
--- 
old/gns3-server-2.0.0/tests/topologies/1_3_dynamips_missing_type/before/1_3_dynamips.gns3
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/gns3-server-2.0.3/tests/topologies/1_3_dynamips_missing_type/before/1_3_dynamips.gns3
   2017-06-13 10:35:50.000000000 +0200
@@ -0,0 +1,80 @@
+{
+    "auto_start": false,
+    "name": "1_3_dynamips",
+    "project_id": "ba5790e1-2f51-443e-a3cc-1a2eee132888",
+    "revision": 3,
+    "topology": {
+        "nodes": [
+            {
+                "default_symbol": ":/symbols/iosv_virl.normal.svg",
+                "description": "Router c7200",
+                "dynamips_id": 1,
+                "hover_symbol": ":/symbols/iosv_virl.selected.svg",
+                "id": 1,
+                "label": {
+                    "color": "#000000",
+                    "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+                    "text": "R1",
+                    "x": 22.6171875,
+                    "y": -25.0
+                },
+                "ports": [
+                    {
+                        "adapter_number": 0,
+                        "id": 1,
+                        "name": "FastEthernet0/0",
+                        "port_number": 0
+                    }
+                ],
+                "properties": {
+                    "auto_delete_disks": true,
+                    "clock_divisor": 4,
+                    "console": 2001,
+                    "disk0": 0,
+                    "disk1": 0,
+                    "exec_area": 64,
+                    "idlemax": 500,
+                    "idlesleep": 30,
+                    "image": "c7200-adventerprisek9-mz.124-24.T8.image",
+                    "mac_addr": "ca01.2f39.0000",
+                    "midplane": "vxr",
+                    "mmap": true,
+                    "name": "R1",
+                    "npe": "npe-400",
+                    "nvram": 512,
+                    "platform": "c7200",
+                    "power_supplies": [
+                        1,
+                        1
+                    ],
+                    "ram": 512,
+                    "sensors": [
+                        22,
+                        22,
+                        22,
+                        22
+                    ],
+                    "slot0": "C7200-IO-FE",
+                    "sparsemem": true,
+                    "startup_config": "configs/i1_startup-config.cfg",
+                    "system_id": "FTX0945W0MY"
+                },
+                "server_id": 1,
+                "vm_id": "0bce6ad5-c688-4d4d-a425-f21aaf3927e2",
+                "x": -112.0,
+                "y": -100.0
+            }
+        ],
+        "servers": [
+            {
+                "cloud": false,
+                "host": "127.0.0.1",
+                "id": 1,
+                "local": true,
+                "port": 8000
+            }
+        ]
+    },
+    "type": "topology",
+    "version": "1.3.13"
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gns3-server-2.0.0/tests/utils.py 
new/gns3-server-2.0.3/tests/utils.py
--- old/gns3-server-2.0.0/tests/utils.py        2017-05-02 10:16:11.000000000 
+0200
+++ new/gns3-server-2.0.3/tests/utils.py        2017-06-13 10:35:50.000000000 
+0200
@@ -16,6 +16,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import io
+import types
 import asyncio
 import unittest.mock
 
@@ -69,6 +70,10 @@
     """
     Magic mock returning coroutine
     """
+    try:
+        __class__ = types.CoroutineType
+    except AttributeError:  # Not supported with Python 3.4
+        __class__ = types.GeneratorType
 
     def __init__(self, return_value=None, return_values=None, **kwargs):
         """


Reply via email to