mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-13 18:35:15 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a19afd618 | ||
|
|
85f571ee8b | ||
|
|
4fc5364ab5 | ||
|
|
4a91d8a6a5 | ||
|
|
b408f29726 | ||
|
|
6d6e8196d2 | ||
|
|
75196b8a55 | ||
|
|
4afbf816ab | ||
|
|
40aec61701 | ||
|
|
7f77c66888 | ||
|
|
a5b5f6c811 | ||
|
|
dc236eba09 | ||
|
|
6eca621b19 | ||
|
|
ba006f105f | ||
|
|
e167a81080 | ||
|
|
9f05b80d01 | ||
|
|
3fe8016938 | ||
|
|
01dbaea2e4 | ||
|
|
427cb05c2a | ||
|
|
39c41336db | ||
|
|
fa22e19321 | ||
|
|
dcc4ddf11b | ||
|
|
e35ab1e8c0 | ||
|
|
975e1c8fa7 | ||
|
|
19b46a4014 | ||
|
|
7cdf23f497 | ||
|
|
06da40cdcd | ||
|
|
75212cda3f | ||
|
|
a018c5b0f5 | ||
|
|
93e2d4096d | ||
|
|
c077f3b990 | ||
|
|
04b02171bb | ||
|
|
e91e3525c4 | ||
|
|
ebb8c0d0b0 | ||
|
|
4c4613b29b | ||
|
|
9d8cb4521d | ||
|
|
9dd09ccde1 | ||
|
|
86ebb9b840 | ||
|
|
569da0ce3a | ||
|
|
f73b288a28 | ||
|
|
e34c266ee1 | ||
|
|
80e15c86dc | ||
|
|
90109e04aa | ||
|
|
c36de3393d |
No files matched your search
@@ -1,5 +1,35 @@
|
||||
# Change Log
|
||||
|
||||
## 1.4.6 28/04/2016
|
||||
|
||||
* More robust save/restore for VirtualBox linked clone VM hard disks.
|
||||
* Prevent non linked cloned hard disks to be detached when using VirtualBox linked cloned VMs. Fixes #1184.
|
||||
* Stricter checks to match VMware version to the right vmrun (VIX library) version. Also checks the VIX library version when only using the GNS3 VM running in VMware.
|
||||
* Allow only .pcap to be downloaded from remote stream API
|
||||
* Fix incrementation of qemu mac address
|
||||
* Clear warnings about using linked clones with VMware Player.
|
||||
* Alternative method to find the Documents folder on Windows.
|
||||
* Add IOU support and install config in /etc
|
||||
|
||||
## 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.
|
||||
|
||||
## 1.4.3 19/02/2016
|
||||
* Nothing! (changes made in the GUI only).
|
||||
|
||||
## 1.4.2 17/02/2016
|
||||
* Fix missing format in IOU export
|
||||
* Fix number of arguments to the UDP errors on VBOX
|
||||
|
||||
@@ -75,7 +75,7 @@ class Config(object):
|
||||
# 2: $HOME/.config/GNS3.conf
|
||||
# 3: /etc/xdg/GNS3/gns3_server.conf
|
||||
# 4: /etc/xdg/GNS3.conf
|
||||
# 5: server.conf in the current working directory
|
||||
# 5: gns3_server.conf in the current working directory
|
||||
|
||||
appname = "GNS3"
|
||||
home = os.path.expanduser("~")
|
||||
@@ -84,6 +84,7 @@ class Config(object):
|
||||
self._files = [os.path.join(os.getcwd(), filename),
|
||||
os.path.join(home, ".config", appname, filename),
|
||||
os.path.join(home, ".config", appname + ".conf"),
|
||||
os.path.join("/etc/gns3", filename),
|
||||
os.path.join("/etc/xdg", appname, filename),
|
||||
os.path.join("/etc/xdg", appname + ".conf")]
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -55,7 +55,6 @@ class DynamipsHypervisor:
|
||||
self._working_dir = working_dir
|
||||
self._version = "N/A"
|
||||
self._timeout = timeout
|
||||
self._uuid = None
|
||||
self._reader = None
|
||||
self._writer = None
|
||||
self._io_lock = asyncio.Lock()
|
||||
@@ -99,8 +98,6 @@ class DynamipsHypervisor:
|
||||
except IndexError:
|
||||
self._version = "Unknown"
|
||||
|
||||
self._uuid = yield from self.send("hypervisor uuid")
|
||||
|
||||
# this forces to send the working dir to Dynamips
|
||||
yield from self.set_working_dir(self._working_dir)
|
||||
|
||||
@@ -174,16 +171,6 @@ class DynamipsHypervisor:
|
||||
|
||||
return self._working_dir
|
||||
|
||||
@property
|
||||
def uuid(self):
|
||||
"""
|
||||
Returns this hypervisor UUID.
|
||||
|
||||
:Returns: uuid string
|
||||
"""
|
||||
|
||||
return self._uuid
|
||||
|
||||
@property
|
||||
def devices(self):
|
||||
"""
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -159,7 +159,7 @@ class VirtualBoxVM(BaseVM):
|
||||
if self.id and os.path.isdir(os.path.join(self.working_dir, self._vmname)):
|
||||
vbox_file = os.path.join(self.working_dir, self._vmname, self._vmname + ".vbox")
|
||||
yield from self.manager.execute("registervm", [vbox_file])
|
||||
yield from self._reattach_hdds()
|
||||
yield from self._reattach_linked_hdds()
|
||||
else:
|
||||
yield from self._create_linked_clone()
|
||||
|
||||
@@ -314,7 +314,10 @@ class VirtualBoxVM(BaseVM):
|
||||
return hdds
|
||||
|
||||
@asyncio.coroutine
|
||||
def _reattach_hdds(self):
|
||||
def _reattach_linked_hdds(self):
|
||||
"""
|
||||
Reattach linked cloned hard disks.
|
||||
"""
|
||||
|
||||
hdd_info_file = os.path.join(self.working_dir, self._vmname, "hdd_info.json")
|
||||
try:
|
||||
@@ -333,10 +336,67 @@ class VirtualBoxVM(BaseVM):
|
||||
device=hdd_info["device"],
|
||||
medium=hdd_file))
|
||||
|
||||
yield from self._storage_attach('--storagectl "{}" --port {} --device {} --type hdd --medium "{}"'.format(hdd_info["controller"],
|
||||
hdd_info["port"],
|
||||
hdd_info["device"],
|
||||
hdd_file))
|
||||
try:
|
||||
yield from self._storage_attach('--storagectl "{}" --port {} --device {} --type hdd --medium "{}"'.format(hdd_info["controller"],
|
||||
hdd_info["port"],
|
||||
hdd_info["device"],
|
||||
hdd_file))
|
||||
|
||||
except VirtualBoxError as e:
|
||||
log.warn("VirtualBox VM '{name}' [{id}] error reattaching HDD {controller} {port} {device} {medium}: {error}".format(name=self.name,
|
||||
id=self.id,
|
||||
controller=hdd_info["controller"],
|
||||
port=hdd_info["port"],
|
||||
device=hdd_info["device"],
|
||||
medium=hdd_file,
|
||||
error=e))
|
||||
continue
|
||||
|
||||
@asyncio.coroutine
|
||||
def save_linked_hdds_info(self):
|
||||
"""
|
||||
Save linked cloned hard disks information.
|
||||
|
||||
:returns: disk table information
|
||||
"""
|
||||
|
||||
hdd_table = []
|
||||
if self._linked_clone:
|
||||
if os.path.exists(self.working_dir):
|
||||
hdd_files = yield from self._get_all_hdd_files()
|
||||
vm_info = yield from self._get_vm_info()
|
||||
for entry, value in vm_info.items():
|
||||
match = re.search("^([\s\w]+)\-(\d)\-(\d)$", entry) # match Controller-PortNumber-DeviceNumber entry
|
||||
if match:
|
||||
controller = match.group(1)
|
||||
port = match.group(2)
|
||||
device = match.group(3)
|
||||
if value in hdd_files and os.path.exists(os.path.join(self.working_dir, self._vmname, "Snapshots", os.path.basename(value))):
|
||||
log.info("VirtualBox VM '{name}' [{id}] detaching HDD {controller} {port} {device}".format(name=self.name,
|
||||
id=self.id,
|
||||
controller=controller,
|
||||
port=port,
|
||||
device=device))
|
||||
hdd_table.append(
|
||||
{
|
||||
"hdd": os.path.basename(value),
|
||||
"controller": controller,
|
||||
"port": port,
|
||||
"device": device,
|
||||
}
|
||||
)
|
||||
|
||||
if hdd_table:
|
||||
try:
|
||||
hdd_info_file = os.path.join(self.working_dir, self._vmname, "hdd_info.json")
|
||||
with open(hdd_info_file, "w", encoding="utf-8") as f:
|
||||
json.dump(hdd_table, f, indent=4)
|
||||
except OSError as e:
|
||||
log.warning("VirtualBox VM '{name}' [{id}] could not write HHD info file: {error}".format(name=self.name,
|
||||
id=self.id,
|
||||
error=e.strerror))
|
||||
|
||||
return hdd_table
|
||||
|
||||
@asyncio.coroutine
|
||||
def close(self):
|
||||
@@ -363,47 +423,29 @@ class VirtualBoxVM(BaseVM):
|
||||
yield from self.stop()
|
||||
|
||||
if self._linked_clone:
|
||||
hdd_table = []
|
||||
if os.path.exists(self.working_dir):
|
||||
hdd_files = yield from self._get_all_hdd_files()
|
||||
vm_info = yield from self._get_vm_info()
|
||||
for entry, value in vm_info.items():
|
||||
match = re.search("^([\s\w]+)\-(\d)\-(\d)$", entry)
|
||||
if match:
|
||||
controller = match.group(1)
|
||||
port = match.group(2)
|
||||
device = match.group(3)
|
||||
if value in hdd_files:
|
||||
log.info("VirtualBox VM '{name}' [{id}] detaching HDD {controller} {port} {device}".format(name=self.name,
|
||||
id=self.id,
|
||||
controller=controller,
|
||||
port=port,
|
||||
device=device))
|
||||
yield from self._storage_attach('--storagectl "{}" --port {} --device {} --type hdd --medium none'.format(controller,
|
||||
port,
|
||||
device))
|
||||
hdd_table.append(
|
||||
{
|
||||
"hdd": os.path.basename(value),
|
||||
"controller": controller,
|
||||
"port": port,
|
||||
"device": device,
|
||||
}
|
||||
)
|
||||
hdd_table = yield from self.save_linked_hdds_info()
|
||||
for hdd in hdd_table.copy():
|
||||
log.info("VirtualBox VM '{name}' [{id}] detaching HDD {controller} {port} {device}".format(name=self.name,
|
||||
id=self.id,
|
||||
controller=hdd["controller"],
|
||||
port=hdd["port"],
|
||||
device=hdd["device"]))
|
||||
try:
|
||||
yield from self._storage_attach('--storagectl "{}" --port {} --device {} --type hdd --medium none'.format(hdd["controller"],
|
||||
hdd["port"],
|
||||
hdd["device"]))
|
||||
except VirtualBoxError as e:
|
||||
log.warn("VirtualBox VM '{name}' [{id}] error detaching HDD {controller} {port} {device}: {error}".format(name=self.name,
|
||||
id=self.id,
|
||||
controller=hdd["controller"],
|
||||
port=hdd["port"],
|
||||
device=hdd["device"],
|
||||
error=e))
|
||||
continue
|
||||
|
||||
log.info("VirtualBox VM '{name}' [{id}] unregistering".format(name=self.name, id=self.id))
|
||||
yield from self.manager.execute("unregistervm", [self._name])
|
||||
|
||||
if hdd_table:
|
||||
try:
|
||||
hdd_info_file = os.path.join(self.working_dir, self._vmname, "hdd_info.json")
|
||||
with open(hdd_info_file, "w", encoding="utf-8") as f:
|
||||
json.dump(hdd_table, f, indent=4)
|
||||
except OSError as e:
|
||||
log.warning("VirtualBox VM '{name}' [{id}] could not write HHD info file: {error}".format(name=self.name,
|
||||
id=self.id,
|
||||
error=e.strerror))
|
||||
|
||||
log.info("VirtualBox VM '{name}' [{id}] closed".format(name=self.name, id=self.id))
|
||||
self._closed = True
|
||||
|
||||
|
||||
@@ -35,10 +35,10 @@ from pkg_resources import parse_version
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
from ..base_manager import BaseManager
|
||||
from .vmware_vm import VMwareVM
|
||||
from .vmware_error import VMwareError
|
||||
from .nio_vmnet import NIOVMNET
|
||||
from gns3server.modules.base_manager import BaseManager
|
||||
from gns3server.modules.vmware.vmware_vm import VMwareVM
|
||||
from gns3server.modules.vmware.vmware_error import VMwareError
|
||||
from gns3server.modules.vmware.nio_vmnet import NIOVMNET
|
||||
|
||||
|
||||
class VMware(BaseManager):
|
||||
@@ -108,7 +108,7 @@ class VMware(BaseManager):
|
||||
vmrun_path = shutil.which("vmrun")
|
||||
|
||||
if not vmrun_path:
|
||||
raise VMwareError("Could not find vmrun")
|
||||
raise VMwareError("Could not find VMware vmrun, please make sure it is installed")
|
||||
if not os.path.isfile(vmrun_path):
|
||||
raise VMwareError("vmrun {} is not accessible".format(vmrun_path))
|
||||
if not os.access(vmrun_path, os.X_OK):
|
||||
@@ -137,6 +137,50 @@ class VMware(BaseManager):
|
||||
version = match.group(1)
|
||||
return version
|
||||
|
||||
@asyncio.coroutine
|
||||
def _check_vmware_player_requirements(self, player_version):
|
||||
"""
|
||||
Check minimum requirements to use VMware Player.
|
||||
|
||||
VIX 1.13 was the release for Player 6.
|
||||
VIX 1.14 was the release for Player 7.
|
||||
VIX 1.15 was the release for Workstation Player 12.
|
||||
|
||||
:param player_version: VMware Player major version.
|
||||
"""
|
||||
|
||||
player_version = int(player_version)
|
||||
if player_version < 6:
|
||||
raise VMwareError("Using VMware Player requires version 6 or above")
|
||||
elif player_version == 6:
|
||||
yield from self.check_vmrun_version(minimum_required_version="1.13")
|
||||
elif player_version == 7:
|
||||
yield from self.check_vmrun_version(minimum_required_version="1.14")
|
||||
elif player_version >= 12:
|
||||
yield from self.check_vmrun_version(minimum_required_version="1.15")
|
||||
|
||||
@asyncio.coroutine
|
||||
def _check_vmware_workstation_requirements(self, ws_version):
|
||||
"""
|
||||
Check minimum requirements to use VMware Workstation.
|
||||
|
||||
VIX 1.13 was the release for Workstation 10.
|
||||
VIX 1.14 was the release for Workstation 11.
|
||||
VIX 1.15 was the release for Workstation Pro 12.
|
||||
|
||||
:param ws_version: VMware Workstation major version.
|
||||
"""
|
||||
|
||||
ws_version = int(ws_version)
|
||||
if ws_version < 10:
|
||||
raise VMwareError("Using VMware Workstation requires version 10 or above")
|
||||
elif ws_version == 10:
|
||||
yield from self.check_vmrun_version(minimum_required_version="1.13")
|
||||
elif ws_version == 11:
|
||||
yield from self.check_vmrun_version(minimum_required_version="1.14")
|
||||
elif ws_version >= 12:
|
||||
yield from self.check_vmrun_version(minimum_required_version="1.15")
|
||||
|
||||
@asyncio.coroutine
|
||||
def check_vmware_version(self):
|
||||
"""
|
||||
@@ -150,18 +194,17 @@ class VMware(BaseManager):
|
||||
player_version = self._find_vmware_version_registry(r"SOFTWARE\Wow6432Node\VMware, Inc.\VMware Player")
|
||||
if player_version:
|
||||
log.debug("VMware Player version {} detected".format(player_version))
|
||||
if int(player_version) < 6:
|
||||
raise VMwareError("Using VMware Player requires version 6 or above")
|
||||
yield from self._check_vmware_player_requirements(player_version)
|
||||
else:
|
||||
log.warning("Could not find VMware version")
|
||||
else:
|
||||
log.debug("VMware Workstation version {} detected".format(ws_version))
|
||||
if int(ws_version) < 10:
|
||||
raise VMwareError("Using VMware Workstation requires version 10 or above")
|
||||
return
|
||||
yield from self._check_vmware_workstation_requirements(ws_version)
|
||||
else:
|
||||
if sys.platform.startswith("darwin"):
|
||||
return # FIXME: no version checking on Mac OS X
|
||||
if not os.path.isdir("/Applications/VMware Fusion.app"):
|
||||
raise VMwareError("VMware Fusion is not installed in the standard location /Applications/VMware Fusion.app")
|
||||
return # FIXME: no version checking on Mac OS X but we support all versions of fusion
|
||||
|
||||
vmware_path = VMware._get_linux_vmware_binary()
|
||||
if vmware_path is None:
|
||||
@@ -172,16 +215,16 @@ class VMware(BaseManager):
|
||||
match = re.search("VMware Workstation ([0-9]+)\.", output)
|
||||
version = None
|
||||
if match:
|
||||
# VMware Workstation has been detected
|
||||
version = match.group(1)
|
||||
log.debug("VMware Workstation version {} detected".format(version))
|
||||
if int(version) < 10:
|
||||
raise VMwareError("Using VMware Workstation requires version 10 or above")
|
||||
yield from self._check_vmware_workstation_requirements(version)
|
||||
match = re.search("VMware Player ([0-9]+)\.", output)
|
||||
if match:
|
||||
# VMware Player has been detected
|
||||
version = match.group(1)
|
||||
log.debug("VMware Player version {} detected".format(version))
|
||||
if int(version) < 6:
|
||||
raise VMwareError("Using VMware Player requires version 6 or above")
|
||||
yield from self._check_vmware_player_requirements(version)
|
||||
if version is None:
|
||||
log.warning("Could not find VMware version. Output of VMware: {}".format(output))
|
||||
raise VMwareError("Could not find VMware version. Output of VMware: {}".format(output))
|
||||
@@ -350,7 +393,17 @@ class VMware(BaseManager):
|
||||
return stdout_data.decode("utf-8", errors="ignore").splitlines()
|
||||
|
||||
@asyncio.coroutine
|
||||
def check_vmrun_version(self):
|
||||
def check_vmrun_version(self, minimum_required_version="1.13"):
|
||||
"""
|
||||
Checks the vmrun version.
|
||||
|
||||
VMware VIX library version must be at least >= 1.13 by default
|
||||
VIX 1.13 was the release for VMware Fusion 6, Workstation 10, and Player 6.
|
||||
VIX 1.14 was the release for VMware Fusion 7, Workstation 11 and Player 7.
|
||||
VIX 1.15 was the release for VMware Fusion 8, Workstation Pro 12 and Workstation Player 12.
|
||||
|
||||
:param required_version: required vmrun version number
|
||||
"""
|
||||
|
||||
with (yield from self._execute_lock):
|
||||
vmrun_path = self.vmrun_path
|
||||
@@ -364,9 +417,9 @@ class VMware(BaseManager):
|
||||
if match:
|
||||
version = match.group(1)
|
||||
log.debug("VMware vmrun version {} detected".format(version))
|
||||
if parse_version(version) < parse_version("1.13"):
|
||||
# VMware VIX library version must be at least >= 1.13
|
||||
raise VMwareError("VMware vmrun executable version must be >= version 1.13")
|
||||
if parse_version(version) < parse_version(minimum_required_version):
|
||||
|
||||
raise VMwareError("VMware vmrun executable version must be >= version {}".format(minimum_required_version))
|
||||
if version is None:
|
||||
log.warning("Could not find VMware vmrun version. Output: {}".format(output))
|
||||
raise VMwareError("Could not find VMware vmrun version. Output: {}".format(output))
|
||||
@@ -592,8 +645,11 @@ class VMware(BaseManager):
|
||||
"""
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
from win32com.shell import shell, shellcon
|
||||
documents_folder = shell.SHGetSpecialFolderPath(None, shellcon.CSIDL_PERSONAL)
|
||||
import ctypes
|
||||
import ctypes.wintypes
|
||||
path = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH)
|
||||
ctypes.windll.shell32.SHGetFolderPathW(None, 5, None, 0, path)
|
||||
documents_folder = path.value
|
||||
windows_type = sys.getwindowsversion().product_type
|
||||
if windows_type == 2 or windows_type == 3:
|
||||
return '{}\My Virtual Machines'.format(documents_folder)
|
||||
@@ -614,26 +670,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 != "player":
|
||||
# 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():
|
||||
@@ -644,3 +713,10 @@ class VMware(BaseManager):
|
||||
if path is None:
|
||||
path = shutil.which("vmplayer")
|
||||
return path
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
loop = asyncio.get_event_loop()
|
||||
vmware = VMware.instance()
|
||||
print("=> Check version")
|
||||
loop.run_until_complete(asyncio.async(vmware.check_vmware_version()))
|
||||
@@ -26,7 +26,7 @@ import asyncio
|
||||
import tempfile
|
||||
|
||||
from gns3server.utils.telnet_server import TelnetServer
|
||||
from gns3server.utils.interfaces import get_windows_interfaces
|
||||
from gns3server.utils.interfaces import interfaces, get_windows_interfaces
|
||||
from gns3server.utils.asyncio import wait_for_file_creation, wait_for_named_pipe_creation
|
||||
from collections import OrderedDict
|
||||
from .vmware_error import VMwareError
|
||||
@@ -144,6 +144,8 @@ class VMwareVM(BaseVM):
|
||||
|
||||
yield from self.manager.check_vmrun_version()
|
||||
if self._linked_clone and not os.path.exists(os.path.join(self.working_dir, os.path.basename(self._vmx_path))):
|
||||
if self.manager.host_type == "player":
|
||||
raise VMwareError("Linked clones are not supported by VMware Player")
|
||||
# create the base snapshot for linked clones
|
||||
base_snapshot_name = "GNS3 Linked Base for clones"
|
||||
vmsd_path = os.path.splitext(self._vmx_path)[0] + ".vmsd"
|
||||
@@ -318,20 +320,29 @@ 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
|
||||
source_mac = None
|
||||
for interface in windows_interfaces:
|
||||
if "netcard" in interface and vmnet_interface in interface["netcard"]:
|
||||
npf = interface["id"]
|
||||
source_mac = interface["mac_address"]
|
||||
elif vmnet_interface in interface["name"]:
|
||||
npf = interface["id"]
|
||||
source_mac = interface["mac_address"]
|
||||
if npf:
|
||||
yield from self._ubridge_hypervisor.send('bridge add_nio_ethernet {name} "{interface}"'.format(name=vnet,
|
||||
interface=npf))
|
||||
else:
|
||||
raise VMwareError("Could not find NPF id for VMnet interface {}".format(vmnet_interface))
|
||||
|
||||
# TODO: should provide that as an option
|
||||
#if source_mac:
|
||||
# yield from self._ubridge_hypervisor.send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=vnet,
|
||||
# mac=source_mac))
|
||||
|
||||
elif sys.platform.startswith("darwin"):
|
||||
yield from self._ubridge_hypervisor.send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=vnet,
|
||||
interface=vmnet_interface))
|
||||
@@ -351,6 +362,14 @@ class VMwareVM(BaseVM):
|
||||
|
||||
yield from self._ubridge_hypervisor.send('bridge start {name}'.format(name=vnet))
|
||||
|
||||
# TODO: this only work when using PCAP (NIO Ethernet)
|
||||
# source_mac = None
|
||||
# for interface in interfaces():
|
||||
# if interface["name"] == vmnet_interface:
|
||||
# source_mac = interface["mac_address"]
|
||||
# if source_mac:
|
||||
# yield from self._ubridge_hypervisor.send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=vnet, mac=source_mac))
|
||||
|
||||
@asyncio.coroutine
|
||||
def _delete_ubridge_connection(self, adapter_number):
|
||||
"""
|
||||
@@ -437,21 +456,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
|
||||
@@ -471,11 +494,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
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
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))
|
||||
@@ -23,7 +23,7 @@ import struct
|
||||
import psutil
|
||||
|
||||
if psutil.version_info < (3, 0, 0):
|
||||
raise Exception("psutil version should >= 3.0.0. If you are under ubuntu/debian install gns3 via apt instead of pip")
|
||||
raise Exception("psutil version should >= 3.0.0. If you are under Ubuntu/Debian install gns3 via apt instead of pip")
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -59,6 +59,7 @@ def _get_windows_interfaces_from_registry():
|
||||
interfaces.append({"id": npf_interface,
|
||||
"name": name,
|
||||
"ip_address": ip_address,
|
||||
"mac_address": "", # TODO: find MAC address in registry
|
||||
"netcard": netcard})
|
||||
winreg.CloseKey(hkeyinterface)
|
||||
winreg.CloseKey(hkeycon)
|
||||
@@ -99,6 +100,7 @@ def get_windows_interfaces():
|
||||
interfaces.append({"id": npf_interface,
|
||||
"name": adapter.NetConnectionID,
|
||||
"ip_address": ip_address,
|
||||
"mac_address": adapter.MACAddress,
|
||||
"netcard": adapter.name})
|
||||
except (AttributeError, pywintypes.com_error):
|
||||
log.warn("Could not use the COM service to retrieve interface info, trying using the registry...")
|
||||
@@ -148,14 +150,17 @@ def interfaces():
|
||||
if not sys.platform.startswith("win"):
|
||||
for interface in sorted(psutil.net_if_addrs().keys()):
|
||||
ip_address = ""
|
||||
mac_address = ""
|
||||
for addr in psutil.net_if_addrs()[interface]:
|
||||
# get the first available IPv4 address only
|
||||
if addr.family == socket.AF_INET:
|
||||
ip_address = addr.address
|
||||
break
|
||||
if addr.family == psutil.AF_LINK:
|
||||
mac_address = addr.address
|
||||
results.append({"id": interface,
|
||||
"name": interface,
|
||||
"ip_address": ip_address})
|
||||
"ip_address": ip_address,
|
||||
"mac_address": mac_address})
|
||||
else:
|
||||
try:
|
||||
results = get_windows_interfaces()
|
||||
|
||||
@@ -23,5 +23,5 @@
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
|
||||
__version__ = "1.4.2"
|
||||
__version_info__ = (1, 4, 2, 0)
|
||||
__version__ = "1.4.6"
|
||||
__version_info__ = (1, 4, 6, 0)
|
||||
@@ -0,0 +1,338 @@
|
||||
#!/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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#
|
||||
# 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 "--with-iou: Install IOU" >&2
|
||||
echo "--with-i386-repository: Add i386 repositories require by IOU if they are not available on the system. Warning this will replace your source.list in order to use official ubuntu mirror" >&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
|
||||
USE_IOU=0
|
||||
I386_REPO=0
|
||||
|
||||
TEMP=`getopt -o h --long with-openvpn,with-iou,with-i386-repository,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
|
||||
;;
|
||||
--with-iou)
|
||||
USE_IOU=1
|
||||
shift
|
||||
;;
|
||||
--with-i386-repository)
|
||||
I386_REPO=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 <<EOFLIST > /etc/apt/sources.list.d/gns3.list
|
||||
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
|
||||
EOFLIST
|
||||
|
||||
if [ $I386_REPO == 1 ]
|
||||
then
|
||||
cat <<EOFLIST2 >> /etc/apt/sources.list
|
||||
###### Ubuntu Main Repos
|
||||
deb http://archive.ubuntu.com/ubuntu/ trusty main universe multiverse
|
||||
deb-src http://archive.ubuntu.com/ubuntu/ trusty main universe multiverse
|
||||
|
||||
###### Ubuntu Update Repos
|
||||
deb http://archive.ubuntu.com/ubuntu/ trusty-security main universe multiverse
|
||||
deb http://archive.ubuntu.com/ubuntu/ trusty-updates main universe multiverse
|
||||
deb-src http://archive.ubuntu.com/ubuntu/ trusty-security main universe multiverse
|
||||
deb-src http://archive.ubuntu.com/ubuntu/ trusty-updates main universe multiverse
|
||||
EOFLIST2
|
||||
fi
|
||||
|
||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A2E3EF7B
|
||||
|
||||
log "Update system packages"
|
||||
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
|
||||
|
||||
if [ $USE_IOU == 1 ]
|
||||
then
|
||||
log "IOU setup"
|
||||
dpkg --add-architecture i386
|
||||
apt-get update
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
log "Add gns3 to the kvm group"
|
||||
usermod -aG kvm gns3
|
||||
|
||||
log "Setup GNS3 server"
|
||||
|
||||
mkdir -p /etc/gns3
|
||||
cat <<EOFC > /etc/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
|
||||
EOFC
|
||||
|
||||
chown -R gns3:gns3 /etc/gns3
|
||||
chmod -R 700 /etc/gns3
|
||||
|
||||
cat <<EOFI > /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
|
||||
EOFI
|
||||
|
||||
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 <<EOFSERVER > /etc/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
|
||||
EOFSERVER
|
||||
|
||||
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 <<EOFMOTD > /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"
|
||||
EOFMOTD
|
||||
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 <<EOFCLIENT > /root/client.ovpn
|
||||
client
|
||||
nobind
|
||||
comp-lzo
|
||||
dev tun
|
||||
<key>
|
||||
`cat /etc/openvpn/key.pem`
|
||||
</key>
|
||||
<cert>
|
||||
`cat /etc/openvpn/cert.pem`
|
||||
</cert>
|
||||
<ca>
|
||||
`cat /etc/openvpn/cert.pem`
|
||||
</ca>
|
||||
<dh>
|
||||
`cat /etc/openvpn/dh.pem`
|
||||
</dh>
|
||||
<connection>
|
||||
remote $MY_IP_ADDR 1194 udp
|
||||
</connection>
|
||||
EOFCLIENT
|
||||
|
||||
cat <<EOFUDP > /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
|
||||
EOFUDP
|
||||
|
||||
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 <<EOFNGINX > /etc/nginx/sites-available/openvpn
|
||||
server {
|
||||
listen 8003;
|
||||
root /usr/share/nginx/openvpn;
|
||||
}
|
||||
EOFNGINX
|
||||
|
||||
[ -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 after rebooting the server"
|
||||
|
||||
fi
|
||||
+13
-4
@@ -81,16 +81,25 @@ def _get_unused_port():
|
||||
def server(request, loop, port_manager, monkeypatch):
|
||||
"""A GNS3 server"""
|
||||
|
||||
port = _get_unused_port()
|
||||
host = "localhost"
|
||||
app = web.Application()
|
||||
for method, route, handler in Route.get_routes():
|
||||
app.router.add_route(method, route, handler)
|
||||
for module in MODULES:
|
||||
instance = module.instance()
|
||||
instance.port_manager = port_manager
|
||||
srv = loop.create_server(app.make_handler(), host, port)
|
||||
srv = loop.run_until_complete(srv)
|
||||
|
||||
host = "localhost"
|
||||
|
||||
# We try multiple time. Because on Travis test can fail when because the port is taken by someone else
|
||||
for i in range(0, 5):
|
||||
port = _get_unused_port()
|
||||
try:
|
||||
srv = loop.create_server(app.make_handler(), host, port)
|
||||
srv = loop.run_until_complete(srv)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
break
|
||||
|
||||
def tear_down():
|
||||
for module in MODULES:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
+9
-1
@@ -16,10 +16,18 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
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"
|
||||
@@ -14,4 +14,4 @@ exclude = tests/*
|
||||
|
||||
[pytest]
|
||||
norecursedirs = .tox
|
||||
timeout = 5
|
||||
timeout = 15
|
||||
@@ -166,6 +166,8 @@ def vmnet_windows(args, vmnet_range_start, vmnet_range_end):
|
||||
continue
|
||||
print("Adding vmnet{}...".format(vmnet_number))
|
||||
os.system('"{}" -- add adapter vmnet{}'.format(vnetlib_path, vmnet_number))
|
||||
os.system("net stop npf")
|
||||
os.system("net start npf")
|
||||
|
||||
|
||||
def vmnet_unix(args, vmnet_range_start, vmnet_range_end):
|
||||
|
||||
Reference in new issue
Block a user