1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-24 17:28:08 +00:00

Includes uBridge stdout in case of error.

This commit is contained in:
grossmj 2016-05-30 22:07:37 -06:00
parent d42366a75a
commit f0e0988d6a
3 changed files with 61 additions and 72 deletions

View File

@ -26,6 +26,7 @@ import platform
from ..utils.asyncio import wait_run_in_executor from ..utils.asyncio import wait_run_in_executor
from ..ubridge.hypervisor import Hypervisor from ..ubridge.hypervisor import Hypervisor
from ..ubridge.ubridge_error import UbridgeError
from .node_error import NodeError from .node_error import NodeError
@ -425,7 +426,10 @@ class BaseNode:
if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running():
raise NodeError("Cannot send command '{}': uBridge is not running".format(command)) raise NodeError("Cannot send command '{}': uBridge is not running".format(command))
yield from self._ubridge_hypervisor.send(command) try:
yield from self._ubridge_hypervisor.send(command)
except UbridgeError as e:
raise UbridgeError("{}: {}".format(e, self._ubridge_hypervisor.read_stdout()))
@asyncio.coroutine @asyncio.coroutine
def _start_ubridge(self): def _start_ubridge(self):
@ -439,7 +443,6 @@ class BaseNode:
server_config = self._manager.config.get_section_config("Server") server_config = self._manager.config.get_section_config("Server")
server_host = server_config.get("host") server_host = server_config.get("host")
self._ubridge_hypervisor = Hypervisor(self._project, self.ubridge_path, self.working_dir, server_host) self._ubridge_hypervisor = Hypervisor(self._project, self.ubridge_path, self.working_dir, server_host)
log.info("Starting new uBridge hypervisor {}:{}".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port)) log.info("Starting new uBridge hypervisor {}:{}".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port))
yield from self._ubridge_hypervisor.start() yield from self._ubridge_hypervisor.start()
log.info("Hypervisor {}:{} has successfully started".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port)) log.info("Hypervisor {}:{} has successfully started".format(self._ubridge_hypervisor.host, self._ubridge_hypervisor.port))

View File

@ -348,7 +348,7 @@ class DockerVM(BaseNode):
except UbridgeNamespaceError: except UbridgeNamespaceError:
yield from self.stop() yield from self.stop()
# The container can crash soon after the start this mean we can not move the interface to the container namespace # The container can crash soon after the start, this means we can not move the interface to the container namespace
logdata = yield from self._get_log() logdata = yield from self._get_log()
for line in logdata.split('\n'): for line in logdata.split('\n'):
log.error(line) log.error(line)
@ -363,7 +363,10 @@ class DockerVM(BaseNode):
yield from self._start_aux() yield from self._start_aux()
self.status = "started" self.status = "started"
log.info("Docker container '{name}' [{image}] started listen for {console_type} on {console}".format(name=self._name, image=self._image, console=self.console, console_type=self.console_type)) log.info("Docker container '{name}' [{image}] started listen for {console_type} on {console}".format(name=self._name,
image=self._image,
console=self.console,
console_type=self.console_type))
@asyncio.coroutine @asyncio.coroutine
def _start_aux(self): def _start_aux(self):
@ -499,9 +502,7 @@ class DockerVM(BaseNode):
try: try:
yield from self._clean_servers() yield from self._clean_servers()
yield from self._stop_ubridge()
if self._ubridge_hypervisor and self._ubridge_hypervisor.is_running():
yield from self._ubridge_hypervisor.stop()
state = yield from self._get_container_state() state = yield from self._get_container_state()
if state == "paused": if state == "paused":
@ -584,8 +585,8 @@ class DockerVM(BaseNode):
try: try:
adapter = self._ethernet_adapters[adapter_number] adapter = self._ethernet_adapters[adapter_number]
except IndexError: except IndexError:
raise DockerError( raise DockerError("Adapter {adapter_number} doesn't exist on Docker container '{name}'".format(name=self.name,
"Adapter {adapter_number} doesn't exist on Docker container '{name}'".format(name=self.name, adapter_number=adapter_number)) adapter_number=adapter_number))
for index in range(128): for index in range(128):
if "veth-gns3-ext{}".format(index) not in psutil.net_if_addrs(): if "veth-gns3-ext{}".format(index) not in psutil.net_if_addrs():
@ -594,41 +595,33 @@ class DockerVM(BaseNode):
adapter.guest_ifc = "veth-gns3-int{}".format(str(index)) adapter.guest_ifc = "veth-gns3-int{}".format(str(index))
break break
if not hasattr(adapter, "ifc"): if not hasattr(adapter, "ifc"):
raise DockerError( raise DockerError("Adapter {adapter_number} couldn't allocate interface on Docker container '{name}'. Too many Docker interfaces already exists".format(name=self.name,
"Adapter {adapter_number} couldn't allocate interface on Docker container '{name}'. Too many Docker interfaces already exists".format( adapter_number=adapter_number))
name=self.name, adapter_number=adapter_number))
yield from self._ubridge_hypervisor.send( yield from self._ubridge_send('docker create_veth {hostif} {guestif}'.format(guestif=adapter.guest_ifc, hostif=adapter.host_ifc))
'docker create_veth {hostif} {guestif}'.format(
guestif=adapter.guest_ifc, hostif=adapter.host_ifc))
log.debug("Move container %s adapter %s to namespace %s", self.name, adapter.guest_ifc, namespace) log.debug("Move container %s adapter %s to namespace %s", self.name, adapter.guest_ifc, namespace)
try: try:
yield from self._ubridge_hypervisor.send( yield from self._ubridge_send('docker move_to_ns {ifc} {ns} eth{adapter}'.format(ifc=adapter.guest_ifc,
'docker move_to_ns {ifc} {ns} eth{adapter}'.format( ns=namespace,
ifc=adapter.guest_ifc, ns=namespace, adapter=adapter_number)) adapter=adapter_number))
except UbridgeError as e: except UbridgeError as e:
raise UbridgeNamespaceError(e) raise UbridgeNamespaceError(e)
if isinstance(nio, NIOUDP): if isinstance(nio, NIOUDP):
yield from self._ubridge_hypervisor.send( yield from self._ubridge_send('bridge create bridge{}'.format(adapter_number))
'bridge create bridge{}'.format(adapter_number)) yield from self._ubridge_send('bridge add_nio_linux_raw bridge{adapter} {ifc}'.format(ifc=adapter.host_ifc, adapter=adapter_number))
yield from self._ubridge_hypervisor.send(
'bridge add_nio_linux_raw bridge{adapter} {ifc}'.format(
ifc=adapter.host_ifc, adapter=adapter_number))
yield from self._ubridge_hypervisor.send( yield from self._ubridge_send('bridge add_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format(adapter=adapter_number,
'bridge add_nio_udp bridge{adapter} {lport} {rhost} {rport}'.format( lport=nio.lport,
adapter=adapter_number, lport=nio.lport, rhost=nio.rhost, rhost=nio.rhost,
rport=nio.rport)) rport=nio.rport))
if nio.capturing: if nio.capturing:
yield from self._ubridge_hypervisor.send( yield from self._ubridge_send('bridge start_capture bridge{adapter} "{pcap_file}"'.format(adapter=adapter_number,
'bridge start_capture bridge{adapter} "{pcap_file}"'.format( pcap_file=nio.pcap_output_file))
adapter=adapter_number, pcap_file=nio.pcap_output_file))
yield from self._ubridge_hypervisor.send( yield from self._ubridge_send('bridge start bridge{adapter}'.format(adapter=adapter_number))
'bridge start bridge{adapter}'.format(adapter=adapter_number))
def _delete_ubridge_connection(self, adapter_number): def _delete_ubridge_connection(self, adapter_number):
"""Deletes a connection in uBridge. """Deletes a connection in uBridge.
@ -641,12 +634,12 @@ class DockerVM(BaseNode):
adapter = self._ethernet_adapters[adapter_number] adapter = self._ethernet_adapters[adapter_number]
try: try:
yield from self._ubridge_hypervisor.send("bridge delete bridge{name}".format( yield from self._ubridge_send("bridge delete bridge{name}".format(
name=adapter_number)) name=adapter_number))
except UbridgeError as e: except UbridgeError as e:
log.debug(str(e)) log.debug(str(e))
try: try:
yield from self._ubridge_hypervisor.send('docker delete_veth {hostif}'.format(hostif=adapter.host_ifc)) yield from self._ubridge_send('docker delete_veth {hostif}'.format(hostif=adapter.host_ifc))
except UbridgeError as e: except UbridgeError as e:
log.debug(str(e)) log.debug(str(e))
@ -665,17 +658,14 @@ class DockerVM(BaseNode):
try: try:
adapter = self._ethernet_adapters[adapter_number] adapter = self._ethernet_adapters[adapter_number]
except IndexError: except IndexError:
raise DockerError( raise DockerError("Adapter {adapter_number} doesn't exist on Docker container '{name}'".format(name=self.name,
"Adapter {adapter_number} doesn't exist on Docker container '{name}'".format( adapter_number=adapter_number))
name=self.name, adapter_number=adapter_number))
adapter.add_nio(0, nio) adapter.add_nio(0, nio)
log.info( log.info("Docker container '{name}' [{id}]: {nio} added to adapter {adapter_number}".format(name=self.name,
"Docker container '{name}' [{id}]: {nio} added to adapter {adapter_number}".format( id=self._id,
name=self.name, nio=nio,
id=self._id, adapter_number=adapter_number))
nio=nio,
adapter_number=adapter_number))
@asyncio.coroutine @asyncio.coroutine
def adapter_remove_nio_binding(self, adapter_number): def adapter_remove_nio_binding(self, adapter_number):
@ -689,17 +679,16 @@ class DockerVM(BaseNode):
try: try:
adapter = self._ethernet_adapters[adapter_number] adapter = self._ethernet_adapters[adapter_number]
except IndexError: except IndexError:
raise DockerError( raise DockerError("Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format(name=self.name,
"Adapter {adapter_number} doesn't exist on Docker VM '{name}'".format( adapter_number=adapter_number))
name=self.name, adapter_number=adapter_number))
adapter.remove_nio(0) adapter.remove_nio(0)
yield from self._delete_ubridge_connection(adapter_number) yield from self._delete_ubridge_connection(adapter_number)
log.info( log.info("Docker VM '{name}' [{id}]: {nio} removed from adapter {adapter_number}".format(name=self.name,
"Docker VM '{name}' [{id}]: {nio} removed from adapter {adapter_number}".format( id=self.id,
name=self.name, id=self.id, nio=adapter.host_ifc, nio=adapter.host_ifc,
adapter_number=adapter_number)) adapter_number=adapter_number))
@property @property
def adapters(self): def adapters(self):
@ -724,11 +713,9 @@ class DockerVM(BaseNode):
for adapter_number in range(0, adapters): for adapter_number in range(0, adapters):
self._ethernet_adapters.append(EthernetAdapter()) self._ethernet_adapters.append(EthernetAdapter())
log.info( log.info('Docker container "{name}" [{id}]: number of Ethernet adapters changed to {adapters}'.format(name=self._name,
'Docker container "{name}" [{id}]: number of Ethernet adapters changed to {adapters}'.format( id=self._id,
name=self._name, adapters=adapters))
id=self._id,
adapters=adapters))
@asyncio.coroutine @asyncio.coroutine
def pull_image(self, image): def pull_image(self, image):
@ -768,7 +755,7 @@ class DockerVM(BaseNode):
adapter = "bridge{}".format(adapter_number) adapter = "bridge{}".format(adapter_number)
if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running():
raise DockerError("Cannot start the packet capture: uBridge is not running") raise DockerError("Cannot start the packet capture: uBridge is not running")
yield from self._ubridge_hypervisor.send('bridge start_capture {name} "{output_file}"'.format(name=adapter, output_file=output_file)) yield from self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name=adapter, output_file=output_file))
@asyncio.coroutine @asyncio.coroutine
def _stop_ubridge_capture(self, adapter_number): def _stop_ubridge_capture(self, adapter_number):
@ -781,7 +768,7 @@ class DockerVM(BaseNode):
adapter = "bridge{}".format(adapter_number) adapter = "bridge{}".format(adapter_number)
if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running():
raise DockerError("Cannot stop the packet capture: uBridge is not running") raise DockerError("Cannot stop the packet capture: uBridge is not running")
yield from self._ubridge_hypervisor.send("bridge stop_capture {name}".format(name=adapter)) yield from self._ubridge_send("bridge stop_capture {name}".format(name=adapter))
@asyncio.coroutine @asyncio.coroutine
def start_capture(self, adapter_number, output_file): def start_capture(self, adapter_number, output_file):

View File

@ -304,10 +304,10 @@ class VMwareVM(BaseNode):
vnet = "ethernet{}.vnet".format(adapter_number) vnet = "ethernet{}.vnet".format(adapter_number)
if vnet not in self._vmx_pairs: if vnet not in self._vmx_pairs:
raise VMwareError("vnet {} not in VMX file".format(vnet)) raise VMwareError("vnet {} not in VMX file".format(vnet))
yield from self._ubridge_hypervisor.send("bridge create {name}".format(name=vnet)) yield from self._ubridge_send("bridge create {name}".format(name=vnet))
vmnet_interface = os.path.basename(self._vmx_pairs[vnet]) vmnet_interface = os.path.basename(self._vmx_pairs[vnet])
if sys.platform.startswith("linux"): if sys.platform.startswith("linux"):
yield from self._ubridge_hypervisor.send('bridge add_nio_linux_raw {name} "{interface}"'.format(name=vnet, yield from self._ubridge_send('bridge add_nio_linux_raw {name} "{interface}"'.format(name=vnet,
interface=vmnet_interface)) interface=vmnet_interface))
elif sys.platform.startswith("win"): elif sys.platform.startswith("win"):
windows_interfaces = interfaces() windows_interfaces = interfaces()
@ -321,36 +321,36 @@ class VMwareVM(BaseNode):
npf = interface["id"] npf = interface["id"]
source_mac = interface["mac_address"] source_mac = interface["mac_address"]
if npf: if npf:
yield from self._ubridge_hypervisor.send('bridge add_nio_ethernet {name} "{interface}"'.format(name=vnet, yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=vnet,
interface=npf)) interface=npf))
else: else:
raise VMwareError("Could not find NPF id for VMnet interface {}".format(vmnet_interface)) raise VMwareError("Could not find NPF id for VMnet interface {}".format(vmnet_interface))
if block_host_traffic: if block_host_traffic:
if source_mac: if source_mac:
yield from self._ubridge_hypervisor.send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=vnet, yield from self._ubridge_send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=vnet,
mac=source_mac)) mac=source_mac))
else: else:
log.warn("Could not block host network traffic on {} (no MAC address found)".format(vmnet_interface)) log.warn("Could not block host network traffic on {} (no MAC address found)".format(vmnet_interface))
elif sys.platform.startswith("darwin"): elif sys.platform.startswith("darwin"):
yield from self._ubridge_hypervisor.send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=vnet, yield from self._ubridge_send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=vnet,
interface=vmnet_interface)) interface=vmnet_interface))
else: else:
yield from self._ubridge_hypervisor.send('bridge add_nio_ethernet {name} "{interface}"'.format(name=vnet, yield from self._ubridge_send('bridge add_nio_ethernet {name} "{interface}"'.format(name=vnet,
interface=vmnet_interface)) interface=vmnet_interface))
if isinstance(nio, NIOUDP): if isinstance(nio, NIOUDP):
yield from self._ubridge_hypervisor.send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=vnet, yield from self._ubridge_send('bridge add_nio_udp {name} {lport} {rhost} {rport}'.format(name=vnet,
lport=nio.lport, lport=nio.lport,
rhost=nio.rhost, rhost=nio.rhost,
rport=nio.rport)) rport=nio.rport))
if nio.capturing: if nio.capturing:
yield from self._ubridge_hypervisor.send('bridge start_capture {name} "{pcap_file}"'.format(name=vnet, yield from self._ubridge_send('bridge start_capture {name} "{pcap_file}"'.format(name=vnet,
pcap_file=nio.pcap_output_file)) pcap_file=nio.pcap_output_file))
yield from self._ubridge_hypervisor.send('bridge start {name}'.format(name=vnet)) yield from self._ubridge_send('bridge start {name}'.format(name=vnet))
# TODO: this only work when using PCAP (NIO Ethernet): current default on Linux is NIO RAW LINUX # TODO: this only work when using PCAP (NIO Ethernet): current default on Linux is NIO RAW LINUX
# source_mac = None # source_mac = None
@ -358,7 +358,7 @@ class VMwareVM(BaseNode):
# if interface["name"] == vmnet_interface: # if interface["name"] == vmnet_interface:
# source_mac = interface["mac_address"] # source_mac = interface["mac_address"]
# if source_mac: # if source_mac:
# yield from self._ubridge_hypervisor.send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=vnet, mac=source_mac)) # yield from self._ubridge_send('bridge set_pcap_filter {name} "not ether src {mac}"'.format(name=vnet, mac=source_mac))
@asyncio.coroutine @asyncio.coroutine
def _delete_ubridge_connection(self, adapter_number): def _delete_ubridge_connection(self, adapter_number):
@ -371,7 +371,7 @@ class VMwareVM(BaseNode):
vnet = "ethernet{}.vnet".format(adapter_number) vnet = "ethernet{}.vnet".format(adapter_number)
if vnet not in self._vmx_pairs: if vnet not in self._vmx_pairs:
raise VMwareError("vnet {} not in VMX file".format(vnet)) raise VMwareError("vnet {} not in VMX file".format(vnet))
yield from self._ubridge_hypervisor.send("bridge delete {name}".format(name=vnet)) yield from self._ubridge_send("bridge delete {name}".format(name=vnet))
@asyncio.coroutine @asyncio.coroutine
def _start_ubridge_capture(self, adapter_number, output_file): def _start_ubridge_capture(self, adapter_number, output_file):
@ -387,7 +387,7 @@ class VMwareVM(BaseNode):
raise VMwareError("vnet {} not in VMX file".format(vnet)) raise VMwareError("vnet {} not in VMX file".format(vnet))
if not self._ubridge_hypervisor: if not self._ubridge_hypervisor:
raise VMwareError("Cannot start the packet capture: uBridge is not running") raise VMwareError("Cannot start the packet capture: uBridge is not running")
yield from self._ubridge_hypervisor.send('bridge start_capture {name} "{output_file}"'.format(name=vnet, yield from self._ubridge_send('bridge start_capture {name} "{output_file}"'.format(name=vnet,
output_file=output_file)) output_file=output_file))
@asyncio.coroutine @asyncio.coroutine
@ -403,7 +403,7 @@ class VMwareVM(BaseNode):
raise VMwareError("vnet {} not in VMX file".format(vnet)) raise VMwareError("vnet {} not in VMX file".format(vnet))
if not self._ubridge_hypervisor: if not self._ubridge_hypervisor:
raise VMwareError("Cannot stop the packet capture: uBridge is not running") raise VMwareError("Cannot stop the packet capture: uBridge is not running")
yield from self._ubridge_hypervisor.send("bridge stop_capture {name}".format(name=vnet)) yield from self._ubridge_send("bridge stop_capture {name}".format(name=vnet))
def check_hw_virtualization(self): def check_hw_virtualization(self):
""" """
@ -481,8 +481,7 @@ class VMwareVM(BaseNode):
self._hw_virtualization = False self._hw_virtualization = False
self._stop_remote_console() self._stop_remote_console()
if self._ubridge_hypervisor and self._ubridge_hypervisor.is_running(): yield from self._stop_ubridge()
yield from self._ubridge_hypervisor.stop()
try: try:
if (yield from self.is_running()): if (yield from self.is_running()):