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/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,
diff --git a/gns3server/modules/vmware/__init__.py b/gns3server/modules/vmware/__init__.py
index 2b1b146d..85831cbd 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.items():
+ 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():
diff --git a/gns3server/modules/vmware/vmware_vm.py b/gns3server/modules/vmware/vmware_vm.py
index 1fafea7a..879ca934 100644
--- a/gns3server/modules/vmware/vmware_vm.py
+++ b/gns3server/modules/vmware/vmware_vm.py
@@ -318,7 +318,7 @@ class VMwareVM(BaseVM):
vmnet_interface = os.path.basename(self._vmx_pairs[vnet])
if sys.platform.startswith("linux"):
yield from self._ubridge_hypervisor.send('bridge add_nio_linux_raw {name} "{interface}"'.format(name=vnet,
- interface=vmnet_interface))
+ interface=vmnet_interface))
elif sys.platform.startswith("win"):
windows_interfaces = get_windows_interfaces()
npf = None
@@ -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
@@ -488,11 +492,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
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
diff --git a/tests/modules/iou/test_iou_vm.py b/tests/modules/iou/test_iou_vm.py
index c5db24ff..a14746ae 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)