From 7f77c6688809b7b60215b1be482de0b1e439c47f Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Wed, 13 Apr 2016 09:38:58 +0200 Subject: [PATCH 1/5] Support VMware VM in non standard location for fusion --- gns3server/modules/vmware/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gns3server/modules/vmware/__init__.py b/gns3server/modules/vmware/__init__.py index 5a112019..29150421 100644 --- a/gns3server/modules/vmware/__init__.py +++ b/gns3server/modules/vmware/__init__.py @@ -618,7 +618,7 @@ class VMware(BaseManager): yield from self.check_vmware_version() inventory_path = self.get_vmware_inventory_path() - if os.path.exists(inventory_path) and self.host_type == "ws": + if os.path.exists(inventory_path) and self.host_type != "player": # inventory may exist for VMware player if VMware workstation has been previously installed return self._get_vms_from_inventory(inventory_path) else: From 40aec61701e6029d038d7e9e4127a9f013cf85ba Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Thu, 14 Apr 2016 16:16:31 +0200 Subject: [PATCH 2/5] Ask user to reboot after the remote install script --- scripts/remote-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh index 95680efe..8bc6b70e 100644 --- a/scripts/remote-install.sh +++ b/scripts/remote-install.sh @@ -332,6 +332,6 @@ set +e service openvpn stop service openvpn start -log "Download http://$MY_IP_ADDR:8003/$UUID/$HOSTNAME.ovpn to setup your OpenVPN client" +log "Download http://$MY_IP_ADDR:8003/$UUID/$HOSTNAME.ovpn to setup your OpenVPN client after rebooting the server" fi From 4afbf816ab254eaae597ae04a42f7c24a0a4719f Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Thu, 14 Apr 2016 16:20:13 +0200 Subject: [PATCH 3/5] Fix errors in remote install script --- scripts/remote-install.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh index 8bc6b70e..b1a9c7cb 100644 --- a/scripts/remote-install.sh +++ b/scripts/remote-install.sh @@ -289,9 +289,9 @@ dev tun remote $MY_IP_ADDR 1194 udp -EOF +EOFCLIENT -cat < /etc/openvpn/udp1194.conf +cat < /etc/openvpn/udp1194.conf server 172.16.253.0 255.255.255.0 verb 3 duplicate-cn @@ -308,7 +308,7 @@ port 1194 dev tun1194 status openvpn-status-1194.log log-append /var/log/openvpn-udp1194.log -EOF +EOFUDP echo "Setup HTTP server for serving client certificate" mkdir -p /usr/share/nginx/openvpn/$UUID @@ -316,12 +316,13 @@ cp /root/client.ovpn /usr/share/nginx/openvpn/$UUID/$HOSTNAME.ovpn touch /usr/share/nginx/openvpn/$UUID/index.html touch /usr/share/nginx/openvpn/index.html -cat < /etc/nginx/sites-available/openvpn +cat < /etc/nginx/sites-available/openvpn server { listen 8003; root /usr/share/nginx/openvpn; } -EOFCLIENT +EOFNGINX + [ -f /etc/nginx/sites-enabled/openvpn ] || ln -s /etc/nginx/sites-available/openvpn /etc/nginx/sites-enabled/ service nginx stop service nginx start From 75196b8a55b1e54f70e085152bc1423990da472a Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 25 Apr 2016 16:36:20 +0200 Subject: [PATCH 4/5] Fix incrementation of qemu mac address Fix #501 --- gns3server/modules/qemu/qemu_vm.py | 4 ++- gns3server/utils/__init__.py | 18 +++++++++++++ tests/modules/qemu/test_qemu_vm.py | 43 ++++++++++++++++++++++++++++++ tests/test_utils.py | 10 ++++++- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/gns3server/modules/qemu/qemu_vm.py b/gns3server/modules/qemu/qemu_vm.py index 996451a5..2b9c44fc 100644 --- a/gns3server/modules/qemu/qemu_vm.py +++ b/gns3server/modules/qemu/qemu_vm.py @@ -40,6 +40,8 @@ from ..base_vm import BaseVM from ...schemas.qemu import QEMU_OBJECT_SCHEMA, QEMU_PLATFORMS from ...utils.asyncio import monitor_process from ...utils.images import md5sum +from ...utils import macaddress_to_int, int_to_macaddress + import logging log = logging.getLogger(__name__) @@ -1374,7 +1376,7 @@ class QemuVM(BaseVM): patched_qemu = True for adapter_number, adapter in enumerate(self._ethernet_adapters): - mac = "%s%02x" % (self._mac_address[:-2], (int(self._mac_address[-2:]) + adapter_number) % 255) + mac = int_to_macaddress(macaddress_to_int(self._mac_address) + adapter_number) nio = adapter.get_nio(0) if self._legacy_networking: # legacy QEMU networking syntax (-net) diff --git a/gns3server/utils/__init__.py b/gns3server/utils/__init__.py index 753df140..fb58158b 100644 --- a/gns3server/utils/__init__.py +++ b/gns3server/utils/__init__.py @@ -16,6 +16,7 @@ # along with this program. If not, see . +import textwrap import posixpath @@ -26,3 +27,20 @@ def force_unix_path(path): path = path.replace("\\", "/") return posixpath.normpath(path) + + +def macaddress_to_int(macaddress): + """ + Convert a macaddress with the format 00:0c:29:11:b0:0a to a int + + :param macaddress: The mac address + :returns: Integer + """ + return int(macaddress.replace(":", ""), 16) + + +def int_to_macaddress(integer): + """ + Convert an integer to a macaddress + """ + return ":".join(textwrap.wrap("%012x" % (integer), width=2)) diff --git a/tests/modules/qemu/test_qemu_vm.py b/tests/modules/qemu/test_qemu_vm.py index 209f270c..33b069af 100644 --- a/tests/modules/qemu/test_qemu_vm.py +++ b/tests/modules/qemu/test_qemu_vm.py @@ -419,6 +419,49 @@ def test_build_command_without_display(vm, loop, fake_qemu_binary): assert "-nographic" in cmd +def test_build_command_two_adapters(vm, loop, fake_qemu_binary, port_manager): + + vm.adapters = 2 + with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: + cmd = loop.run_until_complete(asyncio.async(vm._build_command())) + assert cmd == [ + fake_qemu_binary, + "-name", + "test", + "-m", + "256M", + "-smp", + "cpus=1", + "-boot", + "order=c", + "-serial", + "telnet:127.0.0.1:{},server,nowait".format(vm.console), + "-net", + "none", + "-device", + "e1000,mac=00:00:ab:0e:0f:00", + "-device", + "e1000,mac=00:00:ab:0e:0f:01", + "-nographic" + ] + + +def test_build_command_two_adapters_mac_address(vm, loop, fake_qemu_binary, port_manager): + + vm.adapters = 2 + vm.mac_address = "00:00:ab:0e:0f:09" + with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: + cmd = loop.run_until_complete(asyncio.async(vm._build_command())) + assert "e1000,mac=00:00:ab:0e:0f:09" in cmd + assert "e1000,mac=00:00:ab:0e:0f:0a" in cmd + + vm.mac_address = "00:00:ab:0e:0f:0a" + with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process: + cmd = loop.run_until_complete(asyncio.async(vm._build_command())) + assert "e1000,mac=00:00:ab:0e:0f:0a" in cmd + assert "e1000,mac=00:00:ab:0e:0f:0b" in cmd + + # Windows accept this kind of mistake @pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows") def test_build_command_with_invalid_options(vm, loop, fake_qemu_binary): diff --git a/tests/test_utils.py b/tests/test_utils.py index 33af1a0b..567bcccc 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -16,10 +16,18 @@ # along with this program. If not, see . -from gns3server.utils import force_unix_path +from gns3server.utils import force_unix_path, macaddress_to_int, int_to_macaddress def test_force_unix_path(): assert force_unix_path("a/b") == "a/b" assert force_unix_path("a\\b") == "a/b" assert force_unix_path("a\\b\\..\\c") == "a/c" + + +def test_macaddress_to_int(): + assert macaddress_to_int("00:0c:29:11:b0:0a") == 52228632586 + + +def test_int_to_macaddress(): + assert int_to_macaddress(52228632586) == "00:0c:29:11:b0:0a" From 6d6e8196d236747385170651b1d4197b1e565cab Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Tue, 26 Apr 2016 09:52:18 +0200 Subject: [PATCH 5/5] Allow only .pcap to be downloaded from remote stream API Fix #500 --- gns3server/handlers/api/file_handler.py | 3 +++ tests/handlers/api/test_file.py | 23 +++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/gns3server/handlers/api/file_handler.py b/gns3server/handlers/api/file_handler.py index 4342f6c6..b6d88c40 100644 --- a/gns3server/handlers/api/file_handler.py +++ b/gns3server/handlers/api/file_handler.py @@ -37,6 +37,9 @@ class FileHandler: def read(request, response): response.enable_chunked_encoding() + if not request.json.get("location").endswith(".pcap"): + raise aiohttp.web.HTTPForbidden(text="Only .pcap file are allowed") + try: with open(request.json.get("location"), "rb") as f: loop = asyncio.get_event_loop() diff --git a/tests/handlers/api/test_file.py b/tests/handlers/api/test_file.py index 0b110b2e..a524977d 100644 --- a/tests/handlers/api/test_file.py +++ b/tests/handlers/api/test_file.py @@ -27,15 +27,15 @@ from gns3server.version import __version__ def test_stream(server, tmpdir, loop): - with open(str(tmpdir / "test"), 'w+') as f: + with open(str(tmpdir / "test.pcap"), 'w+') as f: f.write("hello") def go(future): - query = json.dumps({"location": str(tmpdir / "test")}) + query = json.dumps({"location": str(tmpdir / "test.pcap")}) headers = {'content-type': 'application/json'} response = yield from aiohttp.request("GET", server.get_url("/files/stream", 1), data=query, headers=headers) response.body = yield from response.content.read(5) - with open(str(tmpdir / "test"), 'a') as f: + with open(str(tmpdir / "test.pcap"), 'a') as f: f.write("world") response.body += yield from response.content.read(5) response.close() @@ -48,7 +48,8 @@ def test_stream(server, tmpdir, loop): assert response.body == b'helloworld' -def test_stream_file_not_found(server, tmpdir, loop): + +def test_stream_file_not_pcap(server, tmpdir, loop): def go(future): query = json.dumps({"location": str(tmpdir / "test")}) headers = {'content-type': 'application/json'} @@ -56,6 +57,20 @@ def test_stream_file_not_found(server, tmpdir, loop): response.close() future.set_result(response) + future = asyncio.Future() + asyncio.async(go(future)) + response = loop.run_until_complete(future) + assert response.status == 403 + + +def test_stream_file_not_found(server, tmpdir, loop): + def go(future): + query = json.dumps({"location": str(tmpdir / "test.pcap")}) + headers = {'content-type': 'application/json'} + response = yield from aiohttp.request("GET", server.get_url("/files/stream", 1), data=query, headers=headers) + response.close() + future.set_result(response) + future = asyncio.Future() asyncio.async(go(future)) response = loop.run_until_complete(future)