mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 17:28:08 +00:00
Merge branch '1.5' into 2.0
This commit is contained in:
commit
da6cb13338
15
CHANGELOG
15
CHANGELOG
@ -1,5 +1,20 @@
|
||||
# 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
|
||||
|
||||
* Fix distribution on PyPi
|
||||
|
@ -34,6 +34,7 @@ from gns3server.utils.get_resource import get_resource
|
||||
|
||||
from gns3server.ubridge.ubridge_error import UbridgeError, UbridgeNamespaceError
|
||||
from ..base_node import BaseNode
|
||||
|
||||
from ..adapters.ethernet_adapter import EthernetAdapter
|
||||
from ..nios.nio_udp import NIOUDP
|
||||
from .docker_error import (
|
||||
|
@ -602,8 +602,8 @@ class Dynamips(BaseManager):
|
||||
elif 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)
|
||||
# An empty startup config crash dynamips
|
||||
else:
|
||||
elif os.path.isfile(default_startup_config_path) and os.path.getsize(default_startup_config_path) == 0:
|
||||
# An empty startup-config may crash Dynamips
|
||||
startup_config_path = self._create_config(vm, default_startup_config_path, "!\n")
|
||||
yield from vm.set_configs(startup_config_path)
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
Represents a Dynamips hypervisor and starts/stops the associated Dynamips process.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import asyncio
|
||||
@ -117,6 +118,12 @@ class Hypervisor(DynamipsHypervisor):
|
||||
"""
|
||||
|
||||
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:
|
||||
log.info("Starting Dynamips: {}".format(self._command))
|
||||
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,
|
||||
stdout=fd,
|
||||
stderr=subprocess.STDOUT,
|
||||
cwd=self._working_dir)
|
||||
cwd=self._working_dir,
|
||||
env=env)
|
||||
log.info("Dynamips process started PID={}".format(self._process.pid))
|
||||
self._started = True
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
|
@ -272,7 +272,10 @@ class Router(BaseNode):
|
||||
|
||||
status = yield from self.get_status()
|
||||
if status != "inactive":
|
||||
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"
|
||||
log.info('Router "{name}" [{id}] has been stopped'.format(name=self._name, id=self._id))
|
||||
yield from self.save_configs()
|
||||
@ -338,8 +341,8 @@ class Router(BaseNode):
|
||||
try:
|
||||
yield from self.stop()
|
||||
yield from self._hypervisor.send('vm delete "{}"'.format(self._name))
|
||||
except DynamipsError:
|
||||
pass
|
||||
except DynamipsError as e:
|
||||
log.warn("Could not stop and delete {}: {}".format(self._name, e))
|
||||
yield from self.hypervisor.stop()
|
||||
|
||||
if self._auto_delete_disks:
|
||||
@ -1533,7 +1536,6 @@ class Router(BaseNode):
|
||||
if startup_config_base64:
|
||||
if not self.startup_config:
|
||||
self._startup_config = os.path.join("configs", "i{}_startup-config.cfg".format(self._dynamips_id))
|
||||
|
||||
try:
|
||||
config = base64.b64decode(startup_config_base64).decode("utf-8", errors="replace")
|
||||
config = "!\n" + config.replace("\r", "")
|
||||
@ -1544,13 +1546,11 @@ class Router(BaseNode):
|
||||
except (binascii.Error, OSError) as 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:
|
||||
self._private_config = os.path.join("configs", "i{}_private-config.cfg".format(self._dynamips_id))
|
||||
|
||||
try:
|
||||
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)
|
||||
with open(config_path, "wb") as f:
|
||||
log.info("saving private-config to {}".format(self.private_config))
|
||||
|
@ -108,7 +108,6 @@ class IOUVM(BaseNode):
|
||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||
|
||||
yield from self.stop()
|
||||
self.save_configs()
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
@ -683,6 +682,7 @@ class IOUVM(BaseNode):
|
||||
self._iouyap_process = None
|
||||
|
||||
self._started = False
|
||||
self.save_configs()
|
||||
|
||||
def _terminate_process_iouyap(self):
|
||||
"""
|
||||
@ -1099,7 +1099,7 @@ class IOUVM(BaseNode):
|
||||
if private_config is None:
|
||||
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):
|
||||
return
|
||||
|
||||
@ -1206,18 +1206,16 @@ class IOUVM(BaseNode):
|
||||
config_path = os.path.join(self.working_dir, "startup-config.cfg")
|
||||
try:
|
||||
config = startup_config_content.decode("utf-8", errors="replace")
|
||||
config = "!\n" + config.replace("\r", "")
|
||||
with open(config_path, "wb") as f:
|
||||
log.info("saving startup-config to {}".format(config_path))
|
||||
f.write(config.encode("utf-8"))
|
||||
except (binascii.Error, OSError) as 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")
|
||||
try:
|
||||
config = private_config_content.decode("utf-8", errors="replace")
|
||||
config = "!\n" + config.replace("\r", "")
|
||||
with open(config_path, "wb") as f:
|
||||
log.info("saving private-config to {}".format(config_path))
|
||||
f.write(config.encode("utf-8"))
|
||||
|
@ -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(["-i", "1"]) # option to start only one VPC instance
|
||||
command.extend(["-F"]) # option to avoid the daemonization of VPCS
|
||||
if self._vpcs_version > parse_version("0.8"):
|
||||
command.extend(["-R"]) # disable relay feature of VPCS (starting with VPCS 0.8)
|
||||
if self._vpcs_version >= parse_version("0.8b"):
|
||||
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)
|
||||
if nio:
|
||||
|
@ -19,6 +19,7 @@
|
||||
Represents a uBridge hypervisor and starts/stops the associated uBridge process.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import asyncio
|
||||
@ -140,6 +141,12 @@ class Hypervisor(UBridgeHypervisor):
|
||||
"""
|
||||
|
||||
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:
|
||||
command = self._build_command()
|
||||
log.info("starting ubridge: {}".format(command))
|
||||
@ -149,7 +156,8 @@ class Hypervisor(UBridgeHypervisor):
|
||||
self._process = yield from asyncio.create_subprocess_exec(*command,
|
||||
stdout=fd,
|
||||
stderr=subprocess.STDOUT,
|
||||
cwd=self._working_dir)
|
||||
cwd=self._working_dir,
|
||||
env=env)
|
||||
|
||||
log.info("ubridge started PID={}".format(self._process.pid))
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
|
@ -138,6 +138,21 @@ def is_interface_up(interface):
|
||||
# TODO: Windows & OSX support
|
||||
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():
|
||||
"""
|
||||
@ -163,19 +178,8 @@ def interfaces():
|
||||
"mac_address": mac_address})
|
||||
else:
|
||||
try:
|
||||
import pywintypes
|
||||
import win32service
|
||||
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]))
|
||||
|
||||
if not _check_windows_service("npf") and not _check_windows_service("npcap"):
|
||||
raise aiohttp.web.HTTPInternalServerError("The NPF or Npcap is not installed or running")
|
||||
results = get_windows_interfaces()
|
||||
except ImportError:
|
||||
message = "pywin32 module is not installed, please install it on the server to get the available interface names"
|
||||
|
@ -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("net stop 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):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user