1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-25 01:38:08 +00:00

Merge branch '1.5' into 2.0

This commit is contained in:
Julien Duponchelle 2016-05-24 10:13:53 +02:00
commit da6cb13338
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8
10 changed files with 69 additions and 32 deletions

View File

@ -1,5 +1,20 @@
# Change Log # Change Log
## 1.5.0b1 23/05/2016
* Allow an IOS router to stop even the Dynamips hypervisor command fail to be sent. Ref #488.
* Extract private-config only when necessary (content is different than the default). Fixes #520.
* Fixes disabling the VPCS relay feature. Fixes #521.
* Fixes wrong exception in Docker VM implementation.
* Force Npcap DLL to be used first for Dynamips and uBridge (instead of the one from Winpcap if installed).
* Fixed startup-config is lost if you change any IOS router settings. Fixes #1233.
* Fixes check for NPF service and add check for NPCAP service on Windows.
* Fix ProcessLookupError X11VNC
* Force tag latest for docker image if no tag is specified
* Cleanup unbreakable space
* Do not raise error if vmrun.exe is named vmrun.EXE
* Load docker api only for Linux
## 1.5.0a2 10/05/2016 ## 1.5.0a2 10/05/2016
* Fix distribution on PyPi * Fix distribution on PyPi

View File

@ -34,6 +34,7 @@ from gns3server.utils.get_resource import get_resource
from gns3server.ubridge.ubridge_error import UbridgeError, UbridgeNamespaceError from gns3server.ubridge.ubridge_error import UbridgeError, UbridgeNamespaceError
from ..base_node import BaseNode from ..base_node import BaseNode
from ..adapters.ethernet_adapter import EthernetAdapter from ..adapters.ethernet_adapter import EthernetAdapter
from ..nios.nio_udp import NIOUDP from ..nios.nio_udp import NIOUDP
from .docker_error import ( from .docker_error import (

View File

@ -602,8 +602,8 @@ class Dynamips(BaseManager):
elif startup_config_content: elif startup_config_content:
startup_config_path = self._create_config(vm, default_startup_config_path, startup_config_content) startup_config_path = self._create_config(vm, default_startup_config_path, startup_config_content)
yield from vm.set_configs(startup_config_path) yield from vm.set_configs(startup_config_path)
# An empty startup config crash dynamips elif os.path.isfile(default_startup_config_path) and os.path.getsize(default_startup_config_path) == 0:
else: # An empty startup-config may crash Dynamips
startup_config_path = self._create_config(vm, default_startup_config_path, "!\n") startup_config_path = self._create_config(vm, default_startup_config_path, "!\n")
yield from vm.set_configs(startup_config_path) yield from vm.set_configs(startup_config_path)

View File

@ -19,6 +19,7 @@
Represents a Dynamips hypervisor and starts/stops the associated Dynamips process. Represents a Dynamips hypervisor and starts/stops the associated Dynamips process.
""" """
import sys
import os import os
import subprocess import subprocess
import asyncio import asyncio
@ -117,6 +118,12 @@ class Hypervisor(DynamipsHypervisor):
""" """
self._command = self._build_command() self._command = self._build_command()
env = os.environ.copy()
if sys.platform.startswith("win"):
# add the Npcap directory to $PATH to force Dynamips to use npcap DLL instead of Winpcap (if installed)
system_root = os.path.join(os.path.expandvars("%SystemRoot%"), "System32", "Npcap")
if os.path.isdir(system_root):
env["PATH"] = system_root + ';' + env["PATH"]
try: try:
log.info("Starting Dynamips: {}".format(self._command)) log.info("Starting Dynamips: {}".format(self._command))
self._stdout_file = os.path.join(self.working_dir, "dynamips_i{}_stdout.txt".format(self._id)) self._stdout_file = os.path.join(self.working_dir, "dynamips_i{}_stdout.txt".format(self._id))
@ -125,7 +132,8 @@ class Hypervisor(DynamipsHypervisor):
self._process = yield from asyncio.create_subprocess_exec(*self._command, self._process = yield from asyncio.create_subprocess_exec(*self._command,
stdout=fd, stdout=fd,
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
cwd=self._working_dir) cwd=self._working_dir,
env=env)
log.info("Dynamips process started PID={}".format(self._process.pid)) log.info("Dynamips process started PID={}".format(self._process.pid))
self._started = True self._started = True
except (OSError, subprocess.SubprocessError) as e: except (OSError, subprocess.SubprocessError) as e:

View File

@ -272,7 +272,10 @@ class Router(BaseNode):
status = yield from self.get_status() status = yield from self.get_status()
if status != "inactive": if status != "inactive":
yield from self._hypervisor.send('vm stop "{name}"'.format(name=self._name)) try:
yield from self._hypervisor.send('vm stop "{name}"'.format(name=self._name))
except DynamipsError as e:
log.warn("Could not stop {}: {}".format(self._name, e))
self.status = "stopped" self.status = "stopped"
log.info('Router "{name}" [{id}] has been stopped'.format(name=self._name, id=self._id)) log.info('Router "{name}" [{id}] has been stopped'.format(name=self._name, id=self._id))
yield from self.save_configs() yield from self.save_configs()
@ -338,8 +341,8 @@ class Router(BaseNode):
try: try:
yield from self.stop() yield from self.stop()
yield from self._hypervisor.send('vm delete "{}"'.format(self._name)) yield from self._hypervisor.send('vm delete "{}"'.format(self._name))
except DynamipsError: except DynamipsError as e:
pass log.warn("Could not stop and delete {}: {}".format(self._name, e))
yield from self.hypervisor.stop() yield from self.hypervisor.stop()
if self._auto_delete_disks: if self._auto_delete_disks:
@ -1533,7 +1536,6 @@ class Router(BaseNode):
if startup_config_base64: if startup_config_base64:
if not self.startup_config: if not self.startup_config:
self._startup_config = os.path.join("configs", "i{}_startup-config.cfg".format(self._dynamips_id)) self._startup_config = os.path.join("configs", "i{}_startup-config.cfg".format(self._dynamips_id))
try: try:
config = base64.b64decode(startup_config_base64).decode("utf-8", errors="replace") config = base64.b64decode(startup_config_base64).decode("utf-8", errors="replace")
config = "!\n" + config.replace("\r", "") config = "!\n" + config.replace("\r", "")
@ -1544,13 +1546,11 @@ class Router(BaseNode):
except (binascii.Error, OSError) as e: except (binascii.Error, OSError) as e:
raise DynamipsError("Could not save the startup configuration {}: {}".format(config_path, e)) raise DynamipsError("Could not save the startup configuration {}: {}".format(config_path, e))
if private_config_base64: if private_config_base64 and base64.b64decode(private_config_base64) != b'\nkerberos password \nend\n':
if not self.private_config: if not self.private_config:
self._private_config = os.path.join("configs", "i{}_private-config.cfg".format(self._dynamips_id)) self._private_config = os.path.join("configs", "i{}_private-config.cfg".format(self._dynamips_id))
try: try:
config = base64.b64decode(private_config_base64).decode("utf-8", errors="replace") config = base64.b64decode(private_config_base64).decode("utf-8", errors="replace")
config = "!\n" + config.replace("\r", "")
config_path = os.path.join(module_workdir, self.private_config) config_path = os.path.join(module_workdir, self.private_config)
with open(config_path, "wb") as f: with open(config_path, "wb") as f:
log.info("saving private-config to {}".format(self.private_config)) log.info("saving private-config to {}".format(self.private_config))

View File

@ -108,7 +108,6 @@ class IOUVM(BaseNode):
self.manager.port_manager.release_udp_port(nio.lport, self._project) self.manager.port_manager.release_udp_port(nio.lport, self._project)
yield from self.stop() yield from self.stop()
self.save_configs()
@property @property
def path(self): def path(self):
@ -683,6 +682,7 @@ class IOUVM(BaseNode):
self._iouyap_process = None self._iouyap_process = None
self._started = False self._started = False
self.save_configs()
def _terminate_process_iouyap(self): def _terminate_process_iouyap(self):
""" """
@ -1099,7 +1099,7 @@ class IOUVM(BaseNode):
if private_config is None: if private_config is None:
private_config = '' private_config = ''
# We disallow erasing the startup config file # We disallow erasing the private config file
if len(private_config) == 0 and os.path.exists(private_config_path): if len(private_config) == 0 and os.path.exists(private_config_path):
return return
@ -1206,18 +1206,16 @@ class IOUVM(BaseNode):
config_path = os.path.join(self.working_dir, "startup-config.cfg") config_path = os.path.join(self.working_dir, "startup-config.cfg")
try: try:
config = startup_config_content.decode("utf-8", errors="replace") config = startup_config_content.decode("utf-8", errors="replace")
config = "!\n" + config.replace("\r", "")
with open(config_path, "wb") as f: with open(config_path, "wb") as f:
log.info("saving startup-config to {}".format(config_path)) log.info("saving startup-config to {}".format(config_path))
f.write(config.encode("utf-8")) f.write(config.encode("utf-8"))
except (binascii.Error, OSError) as e: except (binascii.Error, OSError) as e:
raise IOUError("Could not save the startup configuration {}: {}".format(config_path, e)) raise IOUError("Could not save the startup configuration {}: {}".format(config_path, e))
if private_config_content: if private_config_content and private_config_content != b'\nend\n':
config_path = os.path.join(self.working_dir, "private-config.cfg") config_path = os.path.join(self.working_dir, "private-config.cfg")
try: try:
config = private_config_content.decode("utf-8", errors="replace") config = private_config_content.decode("utf-8", errors="replace")
config = "!\n" + config.replace("\r", "")
with open(config_path, "wb") as f: with open(config_path, "wb") as f:
log.info("saving private-config to {}".format(config_path)) log.info("saving private-config to {}".format(config_path))
f.write(config.encode("utf-8")) f.write(config.encode("utf-8"))

View File

@ -420,8 +420,10 @@ class VPCSVM(BaseNode):
command.extend(["-m", str(self._manager.get_mac_id(self.id))]) # the unique ID is used to set the MAC address offset command.extend(["-m", str(self._manager.get_mac_id(self.id))]) # the unique ID is used to set the MAC address offset
command.extend(["-i", "1"]) # option to start only one VPC instance command.extend(["-i", "1"]) # option to start only one VPC instance
command.extend(["-F"]) # option to avoid the daemonization of VPCS command.extend(["-F"]) # option to avoid the daemonization of VPCS
if self._vpcs_version > parse_version("0.8"): if self._vpcs_version >= parse_version("0.8b"):
command.extend(["-R"]) # disable relay feature of VPCS (starting with VPCS 0.8) command.extend(["-R"]) # disable the relay feature of VPCS (starting with VPCS 0.8)
else:
log.warn("The VPCS relay feature could not be disabled because the VPCS version is below 0.8b")
nio = self._ethernet_adapter.get_nio(0) nio = self._ethernet_adapter.get_nio(0)
if nio: if nio:

View File

@ -19,6 +19,7 @@
Represents a uBridge hypervisor and starts/stops the associated uBridge process. Represents a uBridge hypervisor and starts/stops the associated uBridge process.
""" """
import sys
import os import os
import subprocess import subprocess
import asyncio import asyncio
@ -140,6 +141,12 @@ class Hypervisor(UBridgeHypervisor):
""" """
yield from self._check_ubridge_version() yield from self._check_ubridge_version()
env = os.environ.copy()
if sys.platform.startswith("win"):
# add the Npcap directory to $PATH to force Dynamips to use npcap DLL instead of Winpcap (if installed)
system_root = os.path.join(os.path.expandvars("%SystemRoot%"), "System32", "Npcap")
if os.path.isdir(system_root):
env["PATH"] = system_root + ';' + env["PATH"]
try: try:
command = self._build_command() command = self._build_command()
log.info("starting ubridge: {}".format(command)) log.info("starting ubridge: {}".format(command))
@ -149,7 +156,8 @@ class Hypervisor(UBridgeHypervisor):
self._process = yield from asyncio.create_subprocess_exec(*command, self._process = yield from asyncio.create_subprocess_exec(*command,
stdout=fd, stdout=fd,
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
cwd=self._working_dir) cwd=self._working_dir,
env=env)
log.info("ubridge started PID={}".format(self._process.pid)) log.info("ubridge started PID={}".format(self._process.pid))
except (OSError, subprocess.SubprocessError) as e: except (OSError, subprocess.SubprocessError) as e:

View File

@ -138,6 +138,21 @@ def is_interface_up(interface):
# TODO: Windows & OSX support # TODO: Windows & OSX support
return True return True
def _check_windows_service(service_name):
import pywintypes
import win32service
import win32serviceutil
try:
if win32serviceutil.QueryServiceStatus(service_name, None)[1] != win32service.SERVICE_RUNNING:
return False
except pywintypes.error as e:
if e.winerror == 1060:
return False
else:
raise aiohttp.web.HTTPInternalServerError(text="Could not check if the {} service is running: {}".format(service_name, e.strerror))
return True
def interfaces(): def interfaces():
""" """
@ -163,19 +178,8 @@ def interfaces():
"mac_address": mac_address}) "mac_address": mac_address})
else: else:
try: try:
import pywintypes if not _check_windows_service("npf") and not _check_windows_service("npcap"):
import win32service raise aiohttp.web.HTTPInternalServerError("The NPF or Npcap is not installed or running")
import win32serviceutil
try:
if win32serviceutil.QueryServiceStatus("npf", None)[1] != win32service.SERVICE_RUNNING:
raise aiohttp.web.HTTPInternalServerError(text="The NPF service is not running")
except pywintypes.error as e:
if e[0] == 1060:
raise aiohttp.web.HTTPInternalServerError(text="The NPF service is not installed")
else:
raise aiohttp.web.HTTPInternalServerError(text="Could not check if the NPF service is running: {}".format(e[2]))
results = get_windows_interfaces() results = get_windows_interfaces()
except ImportError: except ImportError:
message = "pywin32 module is not installed, please install it on the server to get the available interface names" message = "pywin32 module is not installed, please install it on the server to get the available interface names"

View File

@ -168,7 +168,8 @@ def vmnet_windows(args, vmnet_range_start, vmnet_range_end):
os.system('"{}" -- add adapter vmnet{}'.format(vnetlib_path, vmnet_number)) os.system('"{}" -- add adapter vmnet{}'.format(vnetlib_path, vmnet_number))
os.system("net stop npf") os.system("net stop npf")
os.system("net start npf") os.system("net start npf")
os.system("net stop npcap")
os.system("net start npcap")
def vmnet_unix(args, vmnet_range_start, vmnet_range_end): def vmnet_unix(args, vmnet_range_start, vmnet_range_end):
""" """