From 2739483751d7ded2dd887c49ef97114b9209cefa Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 27 Jun 2016 20:24:53 +0200 Subject: [PATCH 1/8] 1.5.0 --- CHANGELOG | 9 +++++++++ gns3server/version.py | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9e50db48..e7e59199 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,14 @@ # Change Log +## 1.5.0 27/06/2016 + +* Fix import of project with no disk +* Allow for (a lot) more docker container ports. Fixes #593. +* Raise an error if you try to use Docker on non Linux host +* Fix a crash in Docker if daemon stop to respond +* Fix a crash if Dynamips router has no initial configuration +* Kill ghosts process at startup (Dynamips, VPCS, Ubridge) + ## 1.5.0rc2 15/06/2016 * Fix black screen with Qt app in Docker container diff --git a/gns3server/version.py b/gns3server/version.py index 3557ac90..6570771f 100644 --- a/gns3server/version.py +++ b/gns3server/version.py @@ -23,5 +23,5 @@ # or negative for a release candidate or beta (after the base version # number has been incremented) -__version__ = "1.5.0dev6" -__version_info__ = (1, 5, 0, -99) +__version__ = "1.5.0" +__version_info__ = (1, 5, 0, 0) From 5fab48ba75642956b3649ee5adbda60699d46e34 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 27 Jun 2016 20:35:08 +0200 Subject: [PATCH 2/8] 1.5.1dev1 --- gns3server/version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gns3server/version.py b/gns3server/version.py index 6570771f..3a76b51c 100644 --- a/gns3server/version.py +++ b/gns3server/version.py @@ -23,5 +23,5 @@ # or negative for a release candidate or beta (after the base version # number has been incremented) -__version__ = "1.5.0" -__version_info__ = (1, 5, 0, 0) +__version__ = "1.5.1dev1" +__version_info__ = (1, 5, 1, -99) From ead8a6caa2980f1bb7978ce49877dd68f1b82435 Mon Sep 17 00:00:00 2001 From: grossmj Date: Fri, 24 Jun 2016 17:26:40 -0600 Subject: [PATCH 3/8] Allows hot-linking for Docker containers. Ref #267. --- gns3server/modules/docker/docker_vm.py | 28 +++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/gns3server/modules/docker/docker_vm.py b/gns3server/modules/docker/docker_vm.py index d3729400..105de81c 100644 --- a/gns3server/modules/docker/docker_vm.py +++ b/gns3server/modules/docker/docker_vm.py @@ -290,7 +290,7 @@ class DockerVM(BaseVM): params["Cmd"] = [] if len(params["Cmd"]) == 0 and len(params["Entrypoint"]) == 0: params["Cmd"] = ["/bin/sh"] - params["Entrypoint"].insert(0, "/gns3/init.sh") + params["Entrypoint"].insert(0, "/gns3/init.sh") # FIXME /gns3/init.sh is not found? # Give the information to the container on how many interface should be inside params["Env"].append("GNS3_MAX_ETHERNET=eth{}".format(self.adapters - 1)) @@ -670,11 +670,8 @@ class DockerVM(BaseVM): :param adapter_number: adapter number """ - if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): - return adapter = self._ethernet_adapters[adapter_number] - try: yield from self._ubridge_hypervisor.send("bridge delete bridge{name}".format( name=adapter_number)) @@ -704,6 +701,18 @@ class DockerVM(BaseVM): "Adapter {adapter_number} doesn't exist on Docker container '{name}'".format( name=self.name, adapter_number=adapter_number)) + if self.status == "started" and self.ubridge and self.ubridge.is_running(): + # the container is running, let's add the UDP tunnel to connect to another node + yield from self._ubridge_send('bridge create bridge{}'.format(adapter_number)) + yield from self._ubridge_send('bridge add_nio_linux_raw bridge{adapter} {ifc}'.format(ifc=adapter.host_ifc, adapter=adapter_number)) + + yield from self._ubridge_send('bridge add_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number, + lport=nio.lport, + rhost=nio.rhost, + rport=nio.rport)) + + yield from self._ubridge_send('bridge start bridge{adapter}'.format(adapter=adapter_number)) + adapter.add_nio(0, nio) log.info( "Docker container '{name}' [{id}]: {nio} added to adapter {adapter_number}".format( @@ -729,7 +738,12 @@ class DockerVM(BaseVM): name=self.name, adapter_number=adapter_number)) adapter.remove_nio(0) - yield from self._delete_ubridge_connection(adapter_number) + if self.status == "started" and self.ubridge and self.ubridge.is_running(): + # the container is running, just delete the UDP tunnel so we can reconnect it later if needed + yield from self._ubridge_send("bridge delete bridge{name}".format(name=adapter_number)) + else: + # the container is not running, let's completely delete the connection + yield from self._delete_ubridge_connection(adapter_number) log.info( "Docker VM '{name}' [{id}]: {nio} removed from adapter {adapter_number}".format( @@ -843,7 +857,7 @@ class DockerVM(BaseVM): nio.startPacketCapture(output_file) - if self.status == "started": + if self.status == "started" and self.ubridge and self.ubridge.is_running(): yield from self._start_ubridge_capture(adapter_number, output_file) log.info("Docker VM '{name}' [{id}]: starting packet capture on adapter {adapter_number}".format(name=self.name, @@ -870,7 +884,7 @@ class DockerVM(BaseVM): nio.stopPacketCapture() - if self.status == "started": + if self.status == "started" and self.ubridge and self.ubridge.is_running(): yield from self._stop_ubridge_capture(adapter_number) log.info("Docker VM '{name}' [{id}]: stopping packet capture on adapter {adapter_number}".format(name=self.name, From f9bc745ddb8e4ac5fcf465bdad84442711ede2fd Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 4 Jul 2016 11:17:38 +0200 Subject: [PATCH 4/8] Backport Docker node hot linking Fix #596 --- gns3server/modules/docker/docker_vm.py | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/gns3server/modules/docker/docker_vm.py b/gns3server/modules/docker/docker_vm.py index 105de81c..99fe4297 100644 --- a/gns3server/modules/docker/docker_vm.py +++ b/gns3server/modules/docker/docker_vm.py @@ -671,6 +671,9 @@ class DockerVM(BaseVM): :param adapter_number: adapter number """ + if not self._ubridge_hypervisor: + return + adapter = self._ethernet_adapters[adapter_number] try: yield from self._ubridge_hypervisor.send("bridge delete bridge{name}".format( @@ -701,17 +704,17 @@ class DockerVM(BaseVM): "Adapter {adapter_number} doesn't exist on Docker container '{name}'".format( name=self.name, adapter_number=adapter_number)) - if self.status == "started" and self.ubridge and self.ubridge.is_running(): + if self.status == "started" and self._ubridge_hypervisor and self._ubridge_hypervisor.is_running(): # the container is running, let's add the UDP tunnel to connect to another node - yield from self._ubridge_send('bridge create bridge{}'.format(adapter_number)) - yield from self._ubridge_send('bridge add_nio_linux_raw bridge{adapter} {ifc}'.format(ifc=adapter.host_ifc, adapter=adapter_number)) + yield from self._ubridge_hypervisor.send('bridge create bridge{}'.format(adapter_number)) + yield from self._ubridge_hypervisor.send('bridge add_nio_linux_raw bridge{adapter} {ifc}'.format(ifc=adapter.host_ifc, adapter=adapter_number)) - yield from self._ubridge_send('bridge add_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number, - lport=nio.lport, - rhost=nio.rhost, - rport=nio.rport)) + yield from self._ubridge_hypervisor.send('bridge add_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number, + lport=nio.lport, + rhost=nio.rhost, + rport=nio.rport)) - yield from self._ubridge_send('bridge start bridge{adapter}'.format(adapter=adapter_number)) + yield from self._ubridge_hypervisor.send('bridge start bridge{adapter}'.format(adapter=adapter_number)) adapter.add_nio(0, nio) log.info( @@ -738,9 +741,9 @@ class DockerVM(BaseVM): name=self.name, adapter_number=adapter_number)) adapter.remove_nio(0) - if self.status == "started" and self.ubridge and self.ubridge.is_running(): + if self.status == "started" and self._ubridge_hypervisor and self._ubridge_hypervisor.is_running(): # the container is running, just delete the UDP tunnel so we can reconnect it later if needed - yield from self._ubridge_send("bridge delete bridge{name}".format(name=adapter_number)) + yield from self._ubridge_hypervisor.send("bridge delete bridge{name}".format(name=adapter_number)) else: # the container is not running, let's completely delete the connection yield from self._delete_ubridge_connection(adapter_number) @@ -857,7 +860,7 @@ class DockerVM(BaseVM): nio.startPacketCapture(output_file) - if self.status == "started" and self.ubridge and self.ubridge.is_running(): + if self.status == "started" and self._ubridge_hypervisor and self._ubridge_hypervisor.is_running(): yield from self._start_ubridge_capture(adapter_number, output_file) log.info("Docker VM '{name}' [{id}]: starting packet capture on adapter {adapter_number}".format(name=self.name, @@ -884,7 +887,7 @@ class DockerVM(BaseVM): nio.stopPacketCapture() - if self.status == "started" and self.ubridge and self.ubridge.is_running(): + if self.status == "started" and self._ubridge_hypervisor and self._ubridge_hypervisor.is_running(): yield from self._stop_ubridge_capture(adapter_number) log.info("Docker VM '{name}' [{id}]: stopping packet capture on adapter {adapter_number}".format(name=self.name, From b905760635231d541272b85691ec97d32b5b48b4 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 4 Jul 2016 14:12:39 +0200 Subject: [PATCH 5/8] Fix a crash when docker is used but not installed Fix #605 --- gns3server/modules/docker/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gns3server/modules/docker/__init__.py b/gns3server/modules/docker/__init__.py index f0f19669..5f0a7faf 100644 --- a/gns3server/modules/docker/__init__.py +++ b/gns3server/modules/docker/__init__.py @@ -114,7 +114,7 @@ class Docker(BaseManager): data=data, headers={"content-type": "application/json", }, ) - except aiohttp.ClientResponseError as e: + except (aiohttp.ClientResponseError, aiohttp.ClientOSError) as e: raise DockerError("Docker has returned an error: {}".format(str(e))) if response.status >= 300: body = yield from response.read() From e0a2553be4f37b5b408d0cfe3730fb7596593473 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 4 Jul 2016 14:46:06 +0200 Subject: [PATCH 6/8] Fix a rare crash in IOU Fix #604 --- gns3server/modules/iou/iou_vm.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gns3server/modules/iou/iou_vm.py b/gns3server/modules/iou/iou_vm.py index 8bbd8bb8..b6dd548f 100644 --- a/gns3server/modules/iou/iou_vm.py +++ b/gns3server/modules/iou/iou_vm.py @@ -663,7 +663,10 @@ class IOUVM(BaseVM): except asyncio.TimeoutError: if self._iou_process.returncode is None: log.warn("IOU process {} is still running... killing it".format(self._iou_process.pid)) - self._iou_process.kill() + try: + self._iou_process.kill() + except ProcessLookupError: + pass self._iou_process = None if self.is_iouyap_running(): From 5f88db93ffcaba40fd2630050f89a2d7f249510e Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 4 Jul 2016 15:00:46 +0200 Subject: [PATCH 7/8] Add the method in the bad request answer --- gns3server/web/route.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gns3server/web/route.py b/gns3server/web/route.py index 4511cbc2..c588a0a0 100644 --- a/gns3server/web/route.py +++ b/gns3server/web/route.py @@ -180,7 +180,7 @@ class Route(object): except aiohttp.web.HTTPBadRequest as e: response = Response(request=request, route=route) response.set_status(e.status) - response.json({"message": e.text, "status": e.status, "path": route, "request": request.json}) + response.json({"message": e.text, "status": e.status, "path": route, "request": request.json, "method": request.method}) except aiohttp.web.HTTPException as e: response = Response(request=request, route=route) response.set_status(e.status) From e175650fb079d085cb20d2ba35892d157115a41c Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 4 Jul 2016 17:22:54 +0200 Subject: [PATCH 8/8] Increase the number of interface for docker Fix #593 --- gns3server/modules/docker/docker_vm.py | 6 +++--- tests/modules/docker/test_docker_vm.py | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/gns3server/modules/docker/docker_vm.py b/gns3server/modules/docker/docker_vm.py index 99fe4297..2c602e04 100644 --- a/gns3server/modules/docker/docker_vm.py +++ b/gns3server/modules/docker/docker_vm.py @@ -623,10 +623,10 @@ class DockerVM(BaseVM): "Adapter {adapter_number} doesn't exist on Docker container '{name}'".format(name=self.name, adapter_number=adapter_number)) for index in range(4096): - if "veth-gns3-ext{}".format(index) not in psutil.net_if_addrs(): + if "veth-gns3-e{}".format(index) not in psutil.net_if_addrs(): adapter.ifc = "eth{}".format(str(index)) - adapter.host_ifc = "veth-gns3-ext{}".format(str(index)) - adapter.guest_ifc = "veth-gns3-int{}".format(str(index)) + adapter.host_ifc = "veth-gns3-e{}".format(str(index)) + adapter.guest_ifc = "veth-gns3-i{}".format(str(index)) break if not hasattr(adapter, "ifc"): raise DockerError( diff --git a/tests/modules/docker/test_docker_vm.py b/tests/modules/docker/test_docker_vm.py index 06778576..af4ca459 100644 --- a/tests/modules/docker/test_docker_vm.py +++ b/tests/modules/docker/test_docker_vm.py @@ -692,10 +692,10 @@ def test_add_ubridge_connection(loop, vm): loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0, 42))) calls = [ - call.send("docker create_veth veth-gns3-ext0 veth-gns3-int0"), - call.send('docker move_to_ns veth-gns3-int0 42 eth0'), + call.send("docker create_veth veth-gns3-e0 veth-gns3-i0"), + call.send('docker move_to_ns veth-gns3-i0 42 eth0'), call.send('bridge create bridge0'), - call.send('bridge add_nio_linux_raw bridge0 veth-gns3-ext0'), + call.send('bridge add_nio_linux_raw bridge0 veth-gns3-e0'), call.send('bridge add_nio_udp bridge0 4242 127.0.0.1 4343'), call.send('bridge start_capture bridge0 "/tmp/capture.pcap"'), call.send('bridge start bridge0') @@ -712,8 +712,8 @@ def test_add_ubridge_connection_none_nio(loop, vm): loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0, 42))) calls = [ - call.send("docker create_veth veth-gns3-ext0 veth-gns3-int0"), - call.send('docker move_to_ns veth-gns3-int0 42 eth0'), + call.send("docker create_veth veth-gns3-e0 veth-gns3-i0"), + call.send('docker move_to_ns veth-gns3-i0 42 eth0'), ] # We need to check any_order ortherwise mock is confused by asyncio vm._ubridge_hypervisor.assert_has_calls(calls, any_order=True) @@ -740,7 +740,7 @@ def test_add_ubridge_connection_no_free_interface(loop, vm): with pytest.raises(DockerError): # We create fake ethernet interfaces for docker - interfaces = ["veth-gns3-ext{}".format(index) for index in range(4096)] + interfaces = ["veth-gns3-e{}".format(index) for index in range(4096)] with patch("psutil.net_if_addrs", return_value=interfaces): loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0, 42))) @@ -760,7 +760,7 @@ def test_delete_ubridge_connection(loop, vm): calls = [ call.send("bridge delete bridge0"), - call.send('docker delete_veth veth-gns3-ext0') + call.send('docker delete_veth veth-gns3-e0') ] vm._ubridge_hypervisor.assert_has_calls(calls, any_order=True)