mirror of
https://github.com/GNS3/gns3-server.git
synced 2025-01-18 23:43:48 +02:00
Fix VMware support on macOS BigSur
This commit is contained in:
parent
bfd30f3547
commit
c892cf371b
@ -362,12 +362,12 @@ class Cloud(BaseNode):
|
||||
"""
|
||||
|
||||
# Wireless adapters are not well supported by the libpcap on OSX
|
||||
if (await self._is_wifi_adapter_osx(port_info["interface"])):
|
||||
if await self._is_wifi_adapter_osx(port_info["interface"]):
|
||||
raise NodeError("Connecting to a Wireless adapter is not supported on Mac OS")
|
||||
if port_info["interface"].startswith("vmnet"):
|
||||
# Use a special NIO to connect to VMware vmnet interfaces on OSX (libpcap doesn't support them)
|
||||
await self._ubridge_send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=bridge_name,
|
||||
interface=port_info["interface"]))
|
||||
interface=port_info["interface"]))
|
||||
return
|
||||
if not gns3server.utils.interfaces.has_netmask(port_info["interface"]):
|
||||
raise NodeError("Interface {} has no netmask, interface down?".format(port_info["interface"]))
|
||||
|
@ -27,6 +27,7 @@ import asyncio
|
||||
import subprocess
|
||||
import logging
|
||||
import codecs
|
||||
import ipaddress
|
||||
|
||||
from collections import OrderedDict
|
||||
from gns3server.utils.interfaces import interfaces
|
||||
@ -51,6 +52,7 @@ class VMware(BaseManager):
|
||||
self._vmrun_path = None
|
||||
self._host_type = None
|
||||
self._vmnets = []
|
||||
self._vmnets_info = {}
|
||||
self._vmnet_start_range = 2
|
||||
if sys.platform.startswith("win"):
|
||||
self._vmnet_end_range = 19
|
||||
@ -273,7 +275,7 @@ class VMware(BaseManager):
|
||||
else:
|
||||
# location on Linux
|
||||
vmware_networking_file = "/etc/vmware/networking"
|
||||
vmnet_interfaces = []
|
||||
vmnet_interfaces = {}
|
||||
try:
|
||||
with open(vmware_networking_file, "r", encoding="utf-8") as f:
|
||||
for line in f.read().splitlines():
|
||||
@ -281,7 +283,20 @@ class VMware(BaseManager):
|
||||
if match:
|
||||
vmnet = "vmnet{}".format(match.group(1))
|
||||
if vmnet not in ("vmnet0", "vmnet1", "vmnet8"):
|
||||
vmnet_interfaces.append(vmnet)
|
||||
vmnet_interfaces[vmnet] = {}
|
||||
with open(vmware_networking_file, "r", encoding="utf-8") as f:
|
||||
for line in f.read().splitlines():
|
||||
match = re.search(r"VNET_([0-9]+)_HOSTONLY_SUBNET\s+(.*)", line)
|
||||
if match:
|
||||
vmnet = "vmnet{}".format(match.group(1))
|
||||
if vmnet in vmnet_interfaces.keys():
|
||||
vmnet_interfaces[vmnet]["subnet"] = match.group(2)
|
||||
match = re.search(r"VNET_([0-9]+)_HOSTONLY_NETMASK\s+(.*)", line)
|
||||
if match:
|
||||
vmnet = "vmnet{}".format(match.group(1))
|
||||
if vmnet in vmnet_interfaces.keys():
|
||||
vmnet_interfaces[vmnet]["netmask"] = match.group(2)
|
||||
|
||||
except OSError as e:
|
||||
raise VMwareError("Cannot open {}: {}".format(vmware_networking_file, e))
|
||||
return vmnet_interfaces
|
||||
@ -324,6 +339,25 @@ class VMware(BaseManager):
|
||||
raise VMwareError("No VMnet interface available between vmnet{} and vmnet{}. Go to preferences VMware / Network / Configure to add more interfaces.".format(self._vmnet_start_range, self._vmnet_end_range))
|
||||
return self._vmnets.pop(0)
|
||||
|
||||
def find_bridge_interface(self, vmnet_interface):
|
||||
"""
|
||||
Find the bridge interface that is used for the vmnet interface in VMware.
|
||||
"""
|
||||
|
||||
if vmnet_interface in self._vmnets_info.keys():
|
||||
subnet = self._vmnets_info[vmnet_interface].get("subnet", None)
|
||||
netmask = self._vmnets_info[vmnet_interface].get("netmask", None)
|
||||
if subnet and netmask:
|
||||
for interface in interfaces():
|
||||
try:
|
||||
network = ipaddress.ip_network(f"{subnet}/{netmask}")
|
||||
ip = ipaddress.ip_address(interface["ip_address"])
|
||||
except ValueError:
|
||||
continue
|
||||
if ip in network:
|
||||
return interface["name"]
|
||||
return None
|
||||
|
||||
def refresh_vmnet_list(self, ubridge=True):
|
||||
|
||||
if ubridge:
|
||||
@ -332,6 +366,8 @@ class VMware(BaseManager):
|
||||
else:
|
||||
vmnet_interfaces = self._get_vmnet_interfaces()
|
||||
|
||||
self._vmnets_info = vmnet_interfaces.copy()
|
||||
vmnet_interfaces = list(vmnet_interfaces.keys())
|
||||
# remove vmnets already in use
|
||||
for vmware_vm in self._nodes.values():
|
||||
for used_vmnet in vmware_vm.vmnets:
|
||||
@ -734,5 +770,4 @@ class VMware(BaseManager):
|
||||
if __name__ == '__main__':
|
||||
loop = asyncio.get_event_loop()
|
||||
vmware = VMware.instance()
|
||||
print("=> Check version")
|
||||
loop.run_until_complete(asyncio.ensure_future(vmware.check_vmware_version()))
|
||||
|
@ -23,9 +23,11 @@ import sys
|
||||
import os
|
||||
import asyncio
|
||||
import tempfile
|
||||
import platform
|
||||
|
||||
from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer
|
||||
from gns3server.utils.asyncio.serial import asyncio_open_serial
|
||||
from gns3server.utils import parse_version
|
||||
from gns3server.utils.asyncio import locking
|
||||
from collections import OrderedDict
|
||||
from .vmware_error import VMwareError
|
||||
@ -252,8 +254,13 @@ class VMwareVM(BaseNode):
|
||||
if self._get_vmx_setting(connected):
|
||||
del self._vmx_pairs[connected]
|
||||
|
||||
use_ubridge = True
|
||||
# use alternative method to find vmnet interfaces on macOS >= 11.0 (BigSur)
|
||||
# because "bridge" interfaces are used instead and they are only created on the VM starts
|
||||
if sys.platform.startswith("darwin") and parse_version(platform.mac_ver()[0]) >= parse_version("11.0.0"):
|
||||
use_ubridge = False
|
||||
self.manager.refresh_vmnet_list(ubridge=use_ubridge)
|
||||
# then configure VMware network adapters
|
||||
self.manager.refresh_vmnet_list()
|
||||
for adapter_number in range(0, self._adapters):
|
||||
|
||||
custom_adapter = self._get_custom_adapter_settings(adapter_number)
|
||||
@ -333,8 +340,17 @@ class VMwareVM(BaseNode):
|
||||
vmnet_interface = os.path.basename(self._vmx_pairs[vnet])
|
||||
|
||||
if sys.platform.startswith("darwin"):
|
||||
# special case on OSX, we cannot bind VMnet interfaces using the libpcap
|
||||
await self._ubridge_send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=vnet, interface=vmnet_interface))
|
||||
if parse_version(platform.mac_ver()[0]) >= parse_version("11.0.0"):
|
||||
# a bridge interface (bridge100, bridge101 etc.) is used instead of a vmnet interface
|
||||
# on macOS >= 11.0 (Big Sur)
|
||||
vmnet_interface = self.manager.find_bridge_interface(vmnet_interface)
|
||||
if not vmnet_interface:
|
||||
raise VMwareError(f"fCould not find bridge interface linked with {vmnet_interface}")
|
||||
block_host_traffic = self.manager.config.get_section_config("VMware").getboolean("block_host_traffic", False)
|
||||
await self._add_ubridge_ethernet_connection(vnet, vmnet_interface, block_host_traffic)
|
||||
else:
|
||||
# special case on macOS, we cannot bind VMnet interfaces using the libpcap
|
||||
await self._ubridge_send('bridge add_nio_fusion_vmnet {name} "{interface}"'.format(name=vnet, interface=vmnet_interface))
|
||||
else:
|
||||
block_host_traffic = self.manager.config.get_section_config("VMware").getboolean("block_host_traffic", False)
|
||||
await self._add_ubridge_ethernet_connection(vnet, vmnet_interface, block_host_traffic)
|
||||
@ -426,7 +442,7 @@ class VMwareVM(BaseNode):
|
||||
if self.status == "started":
|
||||
return
|
||||
|
||||
if (await self.is_running()):
|
||||
if await self.is_running():
|
||||
raise VMwareError("The VM is already running in VMware")
|
||||
|
||||
ubridge_path = self.ubridge_path
|
||||
@ -476,7 +492,7 @@ class VMwareVM(BaseNode):
|
||||
await self._stop_ubridge()
|
||||
|
||||
try:
|
||||
if (await self.is_running()):
|
||||
if await self.is_running():
|
||||
if self.on_close == "save_vm_state":
|
||||
await self._control_vm("suspend")
|
||||
elif self.on_close == "shutdown_signal":
|
||||
@ -728,7 +744,7 @@ class VMwareVM(BaseNode):
|
||||
# check for the connection type
|
||||
connection_type = "ethernet{}.connectiontype".format(adapter_number)
|
||||
if not self._use_any_adapter and connection_type in self._vmx_pairs and self._vmx_pairs[connection_type] in ("nat", "bridged", "hostonly"):
|
||||
if (await self.is_running()):
|
||||
if await self.is_running():
|
||||
raise VMwareError("Attachment '{attachment}' is configured on network adapter {adapter_number}. "
|
||||
"Please stop VMware VM '{name}' to link to this adapter and allow GNS3 to change the attachment type.".format(attachment=self._vmx_pairs[connection_type],
|
||||
adapter_number=adapter_number,
|
||||
|
Loading…
Reference in New Issue
Block a user