From 06da40cdcd0705c7eb8d05027d9e8db2cb1bc121 Mon Sep 17 00:00:00 2001 From: grossmj Date: Sat, 19 Mar 2016 11:32:15 -0600 Subject: [PATCH 01/10] Keep Dynamips stdout log file in the project directory. --- gns3server/modules/dynamips/hypervisor.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gns3server/modules/dynamips/hypervisor.py b/gns3server/modules/dynamips/hypervisor.py index 127e9239..18c35352 100644 --- a/gns3server/modules/dynamips/hypervisor.py +++ b/gns3server/modules/dynamips/hypervisor.py @@ -21,7 +21,6 @@ Represents a Dynamips hypervisor and starts/stops the associated Dynamips proces import os import subprocess -import tempfile import asyncio from gns3server.utils.asyncio import wait_for_process_termination @@ -120,10 +119,9 @@ class Hypervisor(DynamipsHypervisor): self._command = self._build_command() try: log.info("Starting Dynamips: {}".format(self._command)) - - with tempfile.NamedTemporaryFile(delete=False) as fd: - self._stdout_file = fd.name - log.info("Dynamips process logging to {}".format(fd.name)) + self._stdout_file = os.path.join(self.working_dir, "dynamips_i{}_stdout.txt".format(self._id)) + log.info("Dynamips process logging to {}".format(self._stdout_file)) + with open(self._stdout_file, "w", encoding="utf-8") as fd: self._process = yield from asyncio.create_subprocess_exec(*self._command, stdout=fd, stderr=subprocess.STDOUT, From 7cdf23f497a4188e61a618d867711a92b24fc3cf Mon Sep 17 00:00:00 2001 From: grossmj Date: Sat, 19 Mar 2016 12:08:44 -0600 Subject: [PATCH 02/10] Allow to stop a VMware VM from GNS3 even if halted within the VM. Fixes #1118. --- gns3server/modules/vmware/vmware_vm.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gns3server/modules/vmware/vmware_vm.py b/gns3server/modules/vmware/vmware_vm.py index dbec40a5..72a73278 100644 --- a/gns3server/modules/vmware/vmware_vm.py +++ b/gns3server/modules/vmware/vmware_vm.py @@ -488,11 +488,12 @@ class VMwareVM(BaseVM): yield from self._ubridge_hypervisor.stop() try: - if self.acpi_shutdown: - # use ACPI to shutdown the VM - yield from self._control_vm("stop", "soft") - else: - yield from self._control_vm("stop") + if (yield from self.is_running()): + if self.acpi_shutdown: + # use ACPI to shutdown the VM + yield from self._control_vm("stop", "soft") + else: + yield from self._control_vm("stop") finally: self._started = False From 19b46a4014c4b97f748e52576717ae205bd45e25 Mon Sep 17 00:00:00 2001 From: grossmj Date: Sat, 19 Mar 2016 15:41:26 -0600 Subject: [PATCH 03/10] Include VMware VMs paths found preferences.ini --- gns3server/modules/vmware/__init__.py | 29 +++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/gns3server/modules/vmware/__init__.py b/gns3server/modules/vmware/__init__.py index 2b1b146d..0dd8b6ef 100644 --- a/gns3server/modules/vmware/__init__.py +++ b/gns3server/modules/vmware/__init__.py @@ -616,26 +616,39 @@ class VMware(BaseManager): yield from self.check_vmware_version() inventory_path = self.get_vmware_inventory_path() - if os.path.exists(inventory_path): - # FIXME: inventory may exist if VMware workstation has not been fully uninstalled, therefore VMware player VMs are not searched + if os.path.exists(inventory_path) and self.host_type == "ws": + # inventory may exist for VMware player if VMware workstation has been previously installed return self._get_vms_from_inventory(inventory_path) else: - # VMware player has no inventory file, let's search the default location for VMs. + # VMware player has no inventory file, let's search the default location for VMs vmware_preferences_path = self.get_vmware_preferences_path() default_vm_path = self.get_vmware_default_vm_path() - + pairs = {} if os.path.exists(vmware_preferences_path): # the default vm path may be present in VMware preferences file. try: pairs = self.parse_vmware_file(vmware_preferences_path) - if "prefvmx.defaultvmpath" in pairs: - default_vm_path = pairs["prefvmx.defaultvmpath"] except OSError as e: log.warning('Could not read VMware preferences file "{}": {}'.format(vmware_preferences_path, e)) - + if "prefvmx.defaultvmpath" in pairs: + default_vm_path = pairs["prefvmx.defaultvmpath"] if not os.path.isdir(default_vm_path): raise VMwareError('Could not find the default VM directory: "{}"'.format(default_vm_path)) - return self._get_vms_from_directory(default_vm_path) + vms = self._get_vms_from_directory(default_vm_path) + + # looks for VMX paths in the preferences file in case not all VMs are in the default directory + for key, value in pairs: + m = re.match(r'pref.mruVM(\d+)\.filename', key) + if m: + display_name = "pref.mruVM{}.displayName".format(m.group(1)) + if display_name in pairs: + found = False + for vm in vms: + if vm["vmname"] == display_name: + found = True + if found is False: + vms.append({"vmname": pairs[display_name], "vmx_path": value}) + return vms @staticmethod def _get_linux_vmware_binary(): From 975e1c8fa76941fa7aba982363404abe7a175b48 Mon Sep 17 00:00:00 2001 From: grossmj Date: Sun, 20 Mar 2016 11:32:40 -0600 Subject: [PATCH 04/10] Fixes dev syntax bug. --- 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 0dd8b6ef..85831cbd 100644 --- a/gns3server/modules/vmware/__init__.py +++ b/gns3server/modules/vmware/__init__.py @@ -637,7 +637,7 @@ class VMware(BaseManager): vms = self._get_vms_from_directory(default_vm_path) # looks for VMX paths in the preferences file in case not all VMs are in the default directory - for key, value in pairs: + for key, value in pairs.items(): m = re.match(r'pref.mruVM(\d+)\.filename', key) if m: display_name = "pref.mruVM{}.displayName".format(m.group(1)) From e35ab1e8c0514cf69d864a73a826922606c1d0aa Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 21 Mar 2016 10:36:25 +0100 Subject: [PATCH 05/10] Remote install on 14.04 ubuntu --- scripts/remote-install.sh | 318 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 scripts/remote-install.sh diff --git a/scripts/remote-install.sh b/scripts/remote-install.sh new file mode 100644 index 00000000..61f7a683 --- /dev/null +++ b/scripts/remote-install.sh @@ -0,0 +1,318 @@ +#!/bin/bash +# +# Copyright (C) 2015 GNS3 Technologies Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# +# Install GNS3 on a remote Ubuntu 14.04 LTS server +# This create a dedicated user and setup all the package +# and optionnaly a VPN +# + +function help { + echo "Usage:" >&2 + echo "--with-openvpn: Install Open VPN" >&2 + echo "--help: This help" >&2 +} + +function log { + tput setaf 2 + echo "=> $1" >&2 + tput sgr0 +} + +lsb_release -d | grep "Ubuntu 14.04" > /dev/null +if [ $? != 0 ] +then + echo "You can use this script on Ubuntu 14.04 LTS only" + exit 1 +fi + +# Read the options +USE_VPN=0 + +TEMP=`getopt -o h --long with-openvpn,help -n 'gns3-remote-install.sh' -- "$@"` +if [ $? != 0 ] +then + help + exit 1 +fi +eval set -- "$TEMP" + +# extract options and their arguments into variables. +while true ; do + case "$1" in + --with-openvpn) + USE_VPN=1 + shift + ;; + -h|--help) + help + exit 1 + ;; + --) shift ; break ;; + *) echo "Internal error! $1" ; exit 1 ;; + esac +done + +# Exit in case of error +set -e + +export DEBIAN_FRONTEND="noninteractive" + +log "Add GNS3 repository" +cat > /etc/apt/sources.list.d/gns3.list << EOF +deb http://ppa.launchpad.net/gns3/ppa/ubuntu trusty main +deb-src http://ppa.launchpad.net/gns3/ppa/ubuntu trusty main +deb http://ppa.launchpad.net/gns3/qemu/ubuntu trusty main +deb-src http://ppa.launchpad.net/gns3/qemu/ubuntu trusty main +EOF + +apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A2E3EF7B + +log "Update system packages" +dpkg --add-architecture i386 +apt-get update + +log "Upgrade packages" +apt-get upgrade -y + +log " Install GNS3 packages" +apt-get install -y gns3-server + +log "Create user GNS3 with /opt/gns3 as home directory" +if [ ! -d "/opt/gns3/" ] +then + useradd -d /opt/gns3/ -m gns3 +fi + +log "Install docker" +if [ ! -f "/usr/bin/docker" ] +then + curl -sSL https://get.docker.com | bash +fi + +log "Add GNS3 to the docker group" +usermod -aG docker gns3 + +log "IOU setup" +#apt-get install -y gns3-iou + +# Force the host name to gns3vm +hostnamectl set-hostname gns3vm + +# Force hostid for IOU +dd if=/dev/zero bs=4 count=1 of=/etc/hostid + +# Block iou call. The server is down +echo "127.0.0.254 xml.cisco.com" | tee --append /etc/hosts + +log "Add gns3 to the kvm group" +usermod -aG kvm gns3 + +log "Setup VDE network" + +apt-get install -y vde2 uml-utilities + +usermod -a -G vde2-net gns3 + +cat < /etc/network/interfaces.d/qemu0.conf +# A vde network +auto qemu0 + iface qemu0 inet static + address 172.16.0.1 + netmask 255.255.255.0 + vde2-switch -t qemu0 +EOF + +log "Setup GNS3 server" + + +#TODO: 1.4.5 allow /etc/gns3/gns3_server.conf it's cleaner +cat < /opt/gns3/gns3_server.conf +[Server] +host = 0.0.0.0 +port = 8000 +images_path = /opt/gns3/images +projects_path = /opt/gns3/projects +report_errors = True + +[Qemu] +enable_kvm = True +EOF + +cat < /etc/init/gns3.conf +description "GNS3 server" +author "GNS3 Team" + +start on filesystem or runlevel [2345] +stop on runlevel [016] +respawn +console log + + +script + exec start-stop-daemon --start --make-pidfile --pidfile /var/run/gns3.pid --chuid gns3 --exec "/usr/bin/gns3server" +end script + +pre-start script + echo "" > /var/log/upstart/gns3.log + echo "[`date`] GNS3 Starting" +end script + +pre-stop script + echo "[`date`] GNS3 Stopping" +end script +EOF + +chown root:root /etc/init/gns3.conf +chmod 644 /etc/init/gns3.conf + + +log "Start GNS3 service" +set +e +service gns3 stop +set -e +service gns3 start + +log "GNS3 installed with success" + +if [ $USE_VPN == 1 ] +then +log "Setup VPN" + +cat < /opt/gns3/gns3_server.conf +[Server] +host = 172.16.253.1 +port = 8000 +images_path = /opt/gns3/images +projects_path = /opt/gns3/projects +report_errors = True + +[Qemu] +enable_kvm = True +EOF + +log "Install packages for Open VPN" + +apt-get install -y \ + openvpn \ + uuid \ + dnsutils \ + nginx-light + +MY_IP_ADDR=$(dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | sed 's/"//g') + +log "IP detected: $MY_IP_ADDR" + +UUID=$(uuid) + +log "Update motd" + +cat < /etc/update-motd.d/70-openvpn +#!/bin/sh +echo "" +echo "_______________________________________________________________________________________________" +echo "Download the VPN configuration here:" +echo "http://$MY_IP_ADDR:8003/$UUID/$HOSTNAME.ovpn" +echo "" +echo "And add it to your openvpn client." +echo "" +echo "apt-get remove nginx-light to disable the HTTP server." +echo "And remove this file with rm /etc/update-motd.d/70-openvpn" +EOF +chmod 755 /etc/update-motd.d/70-openvpn + + +mkdir -p /etc/openvpn/ + +[ -d /dev/net ] || mkdir -p /dev/net +[ -c /dev/net/tun ] || mknod /dev/net/tun c 10 200 + +log "Create keys" + +[ -f /etc/openvpn/dh.pem ] || openssl dhparam -out /etc/openvpn/dh.pem 2048 +[ -f /etc/openvpn/key.pem ] || openssl genrsa -out /etc/openvpn/key.pem 2048 +chmod 600 /etc/openvpn/key.pem +[ -f /etc/openvpn/csr.pem ] || openssl req -new -key /etc/openvpn/key.pem -out /etc/openvpn/csr.pem -subj /CN=OpenVPN/ +[ -f /etc/openvpn/cert.pem ] || openssl x509 -req -in /etc/openvpn/csr.pem -out /etc/openvpn/cert.pem -signkey /etc/openvpn/key.pem -days 24855 + +log "Create client configuration" +cat < /root/client.ovpn +client +nobind +comp-lzo +dev tun + +`cat /etc/openvpn/key.pem` + + +`cat /etc/openvpn/cert.pem` + + +`cat /etc/openvpn/cert.pem` + + +`cat /etc/openvpn/dh.pem` + + +remote $MY_IP_ADDR 1194 udp + +EOF + +cat < /etc/openvpn/udp1194.conf +server 172.16.253.0 255.255.255.0 +verb 3 +duplicate-cn +comp-lzo +key key.pem +ca cert.pem +cert cert.pem +dh dh.pem +keepalive 10 60 +persist-key +persist-tun +proto udp +port 1194 +dev tun1194 +status openvpn-status-1194.log +log-append /var/log/openvpn-udp1194.log +EOF + +echo "Setup HTTP server for serving client certificate" +mkdir -p /usr/share/nginx/openvpn/$UUID +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 +server { + listen 8003; + root /usr/share/nginx/openvpn; +} +EOF +[ -f /etc/nginx/sites-enabled/openvpn ] || ln -s /etc/nginx/sites-available/openvpn /etc/nginx/sites-enabled/ +service nginx stop +service nginx start + +log "Restart OpenVPN" + +set +e +service openvpn stop +service openvpn start + +log "Download http://$MY_IP_ADDR:8003/$UUID/$HOSTNAME.ovpn to setup your OpenVPN client" + +fi From dcc4ddf11b6976e35d114e3e3ab834b5ef5f9ed3 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 21 Mar 2016 16:53:11 +0100 Subject: [PATCH 06/10] Add a test for \r\n Fix #458 --- tests/modules/iou/test_iou_vm.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/modules/iou/test_iou_vm.py b/tests/modules/iou/test_iou_vm.py index 4eb63019..1e8ec0fc 100644 --- a/tests/modules/iou/test_iou_vm.py +++ b/tests/modules/iou/test_iou_vm.py @@ -118,6 +118,7 @@ def test_start(loop, vm, monkeypatch): assert vm.is_running() assert vm.command_line == ' '.join(mock_exec.call_args[0]) + def test_start_with_iourc(loop, vm, monkeypatch, tmpdir): fake_file = str(tmpdir / "iourc") @@ -412,6 +413,14 @@ def test_iourc_content(vm): assert f.read() == "test" +def test_iourc_content_fix_carriage_return(vm): + + vm.iourc_content = "test\r\n12" + + with open(os.path.join(vm.temporary_directory, "iourc")) as f: + assert f.read() == "test\n12" + + def test_extract_configs(vm): assert vm.extract_configs() == (None, None) From fa22e19321dc2a64bc10ffee0586da90a85017e5 Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 22 Mar 2016 14:43:47 -0600 Subject: [PATCH 07/10] Bump version to 1.4.5dev2 --- gns3server/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gns3server/version.py b/gns3server/version.py index 0cf55dec..35280f9c 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.4.5dev1" +__version__ = "1.4.5dev2" __version_info__ = (1, 4, 5, -99) From 427cb05c2ad0ea80a89d70bd6773d5dc98a3fdf1 Mon Sep 17 00:00:00 2001 From: grossmj Date: Wed, 23 Mar 2016 10:54:45 -0600 Subject: [PATCH 08/10] Stop the VMware VM if there is an error while setting up the network connections or console. --- gns3server/modules/vmware/vmware_vm.py | 32 +++++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/gns3server/modules/vmware/vmware_vm.py b/gns3server/modules/vmware/vmware_vm.py index 72a73278..354ee66b 100644 --- a/gns3server/modules/vmware/vmware_vm.py +++ b/gns3server/modules/vmware/vmware_vm.py @@ -454,21 +454,25 @@ class VMwareVM(BaseVM): else: yield from self._control_vm("start") - if self._use_ubridge and self._ubridge_hypervisor: - for adapter_number in range(0, self._adapters): - nio = self._ethernet_adapters[adapter_number].get_nio(0) - if nio: - yield from self._add_ubridge_connection(nio, adapter_number) + try: + if self._use_ubridge and self._ubridge_hypervisor: + for adapter_number in range(0, self._adapters): + nio = self._ethernet_adapters[adapter_number].get_nio(0) + if nio: + yield from self._add_ubridge_connection(nio, adapter_number) - if self._enable_remote_console and self._console is not None: - try: - if sys.platform.startswith("win"): - yield from wait_for_named_pipe_creation(self._get_pipe_name()) - else: - yield from wait_for_file_creation(self._get_pipe_name()) # wait for VMware to create the pipe file. - except asyncio.TimeoutError: - raise VMwareError('Pipe file "{}" for remote console has not been created by VMware'.format(self._get_pipe_name())) - self._start_remote_console() + if self._enable_remote_console and self._console is not None: + try: + if sys.platform.startswith("win"): + yield from wait_for_named_pipe_creation(self._get_pipe_name()) + else: + yield from wait_for_file_creation(self._get_pipe_name()) # wait for VMware to create the pipe file. + except asyncio.TimeoutError: + raise VMwareError('Pipe file "{}" for remote console has not been created by VMware'.format(self._get_pipe_name())) + self._start_remote_console() + except VMwareError: + yield from self.stop() + raise if self._get_vmx_setting("vhv.enable", "TRUE"): self._hw_virtualization = True From 01dbaea2e410c0a71830c8bdfe770069a2fdf171 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Wed, 23 Mar 2016 18:11:48 +0100 Subject: [PATCH 09/10] 1.4.5 --- CHANGELOG | 13 +++++++++++++ gns3server/version.py | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 631d7c62..31faa0b0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,18 @@ # Change Log +## 1.4.5 23/03/2016 + +* Stop the VMware VM if there is an error while setting up the network connections or console. +* Remote install on 14.04 ubuntu +* Include VMware VMs paths found preferences.ini +* Allow to stop a VMware VM from GNS3 even if halted within the VM. Fixes #1118. +* Keep Dynamips stdout log file in the project directory. +* Get MAC addresses for host interfaces to use for filtering frames from vmnet interfaces. +* Dynamips uuid hypervisor command is no longer supported. +* Restart NPF service after adding vmnet adapters on Windows. +* Support /etc/gns3/gns3_server.conf for the config +* Improve warning if fusion is not installed or in non standard location + ## 1.4.4 23/02/2016 * Check if VMware Fusion is correctly installed when retrieving the VM list. diff --git a/gns3server/version.py b/gns3server/version.py index 35280f9c..adf26cc0 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.4.5dev2" -__version_info__ = (1, 4, 5, -99) +__version__ = "1.4.5" +__version_info__ = (1, 4, 5, 0) From 3fe801693890047a195d1e78c0a489ed9ecc17bf Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Wed, 23 Mar 2016 18:14:04 +0100 Subject: [PATCH 10/10] 1.4.6 dev1 --- gns3server/version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gns3server/version.py b/gns3server/version.py index adf26cc0..aaced8f2 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.4.5" -__version_info__ = (1, 4, 5, 0) +__version__ = "1.4.6dev1" +__version_info__ = (1, 4, 6, -99)