mirror of
https://github.com/GNS3/gns3-server.git
synced 2025-01-31 05:13:49 +02:00
Allows VMware VMs to use vmnet interfaces for connections without using uBridge. Fixes #295.
This commit is contained in:
parent
476e033a78
commit
4efec03448
@ -268,7 +268,7 @@ class VMwareHandler:
|
|||||||
vmware_manager = VMware.instance()
|
vmware_manager = VMware.instance()
|
||||||
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
||||||
nio_type = request.json["type"]
|
nio_type = request.json["type"]
|
||||||
if nio_type != "nio_udp":
|
if nio_type not in ("nio_udp", "nio_vmnet"):
|
||||||
raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
|
raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
|
||||||
nio = vmware_manager.create_nio(None, request.json)
|
nio = vmware_manager.create_nio(None, request.json)
|
||||||
yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
|
yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
|
||||||
@ -296,3 +296,21 @@ class VMwareHandler:
|
|||||||
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
|
||||||
yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]))
|
yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]))
|
||||||
response.set_status(204)
|
response.set_status(204)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@Route.post(
|
||||||
|
r"/projects/{project_id}/vmware/interfaces/vmnet",
|
||||||
|
parameters={
|
||||||
|
"project_id": "The UUID of the project",
|
||||||
|
},
|
||||||
|
status_codes={
|
||||||
|
201: "VMnet interface allocated",
|
||||||
|
},
|
||||||
|
description="Allocate a VMware VMnet interface on the server")
|
||||||
|
def allocate_vmnet(request, response):
|
||||||
|
|
||||||
|
vmware_manager = VMware.instance()
|
||||||
|
vmware_manager.refresh_vmnet_list()
|
||||||
|
vmnet = vmware_manager.allocate_vmnet()
|
||||||
|
response.set_status(201)
|
||||||
|
response.json({"vmnet": vmnet})
|
||||||
|
@ -37,6 +37,7 @@ log = logging.getLogger(__name__)
|
|||||||
from ..base_manager import BaseManager
|
from ..base_manager import BaseManager
|
||||||
from .vmware_vm import VMwareVM
|
from .vmware_vm import VMwareVM
|
||||||
from .vmware_error import VMwareError
|
from .vmware_error import VMwareError
|
||||||
|
from .nio_vmnet import NIOVMNET
|
||||||
|
|
||||||
|
|
||||||
class VMware(BaseManager):
|
class VMware(BaseManager):
|
||||||
@ -230,7 +231,8 @@ class VMware(BaseManager):
|
|||||||
def allocate_vmnet(self):
|
def allocate_vmnet(self):
|
||||||
|
|
||||||
if not self._vmnets:
|
if not self._vmnets:
|
||||||
raise VMwareError("No more VMnet interfaces available")
|
raise VMwareError("No VMnet interface available between vmnet{} and vmnet{}".format(self._vmnet_start_range,
|
||||||
|
self._vmnet_end_range))
|
||||||
return self._vmnets.pop(0)
|
return self._vmnets.pop(0)
|
||||||
|
|
||||||
def refresh_vmnet_list(self):
|
def refresh_vmnet_list(self):
|
||||||
@ -251,6 +253,13 @@ class VMware(BaseManager):
|
|||||||
|
|
||||||
self._vmnets = vmnet_interfaces
|
self._vmnets = vmnet_interfaces
|
||||||
|
|
||||||
|
def create_nio(self, executable, nio_settings):
|
||||||
|
|
||||||
|
if nio_settings["type"] == "nio_vmnet":
|
||||||
|
return NIOVMNET(nio_settings["vmnet"])
|
||||||
|
else:
|
||||||
|
return super().create_nio(None, nio_settings)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def host_type(self):
|
def host_type(self):
|
||||||
"""
|
"""
|
||||||
@ -501,6 +510,7 @@ class VMware(BaseManager):
|
|||||||
|
|
||||||
inventory_path = self.get_vmware_inventory_path()
|
inventory_path = self.get_vmware_inventory_path()
|
||||||
if os.path.exists(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
|
||||||
return self._get_vms_from_inventory(inventory_path)
|
return self._get_vms_from_inventory(inventory_path)
|
||||||
else:
|
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.
|
||||||
|
53
gns3server/modules/vmware/nio_vmnet.py
Normal file
53
gns3server/modules/vmware/nio_vmnet.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Interface for VMnet NIOs.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ..nios.nio import NIO
|
||||||
|
|
||||||
|
|
||||||
|
class NIOVMNET(NIO):
|
||||||
|
|
||||||
|
"""
|
||||||
|
VMnet NIO.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, vmnet):
|
||||||
|
|
||||||
|
super().__init__()
|
||||||
|
self._vmnet = vmnet
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vmnet(self):
|
||||||
|
"""
|
||||||
|
Returns vmnet interface used by this NIO.
|
||||||
|
|
||||||
|
:returns: vmnet interface name
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._vmnet
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
return "NIO VMNET"
|
||||||
|
|
||||||
|
def __json__(self):
|
||||||
|
|
||||||
|
return {"type": "nio_vmnet",
|
||||||
|
"vmnet": self._vmnet}
|
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -33,6 +33,7 @@ from gns3server.utils.interfaces import get_windows_interfaces
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from .vmware_error import VMwareError
|
from .vmware_error import VMwareError
|
||||||
from ..nios.nio_udp import NIOUDP
|
from ..nios.nio_udp import NIOUDP
|
||||||
|
from .nio_vmnet import NIOVMNET
|
||||||
from ..adapters.ethernet_adapter import EthernetAdapter
|
from ..adapters.ethernet_adapter import EthernetAdapter
|
||||||
from ..base_vm import BaseVM
|
from ..base_vm import BaseVM
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ class VMwareVM(BaseVM):
|
|||||||
self._adapters = 0
|
self._adapters = 0
|
||||||
self._ethernet_adapters = {}
|
self._ethernet_adapters = {}
|
||||||
self._adapter_type = "e1000"
|
self._adapter_type = "e1000"
|
||||||
|
self._use_ubridge = True
|
||||||
self._use_any_adapter = False
|
self._use_any_adapter = False
|
||||||
|
|
||||||
if not os.path.exists(vmx_path):
|
if not os.path.exists(vmx_path):
|
||||||
@ -89,6 +91,7 @@ class VMwareVM(BaseVM):
|
|||||||
"enable_remote_console": self.enable_remote_console,
|
"enable_remote_console": self.enable_remote_console,
|
||||||
"adapters": self._adapters,
|
"adapters": self._adapters,
|
||||||
"adapter_type": self.adapter_type,
|
"adapter_type": self.adapter_type,
|
||||||
|
"use_ubridge": self.use_ubridge,
|
||||||
"use_any_adapter": self.use_any_adapter,
|
"use_any_adapter": self.use_any_adapter,
|
||||||
"vm_directory": self.working_dir}
|
"vm_directory": self.working_dir}
|
||||||
return json
|
return json
|
||||||
@ -107,6 +110,26 @@ class VMwareVM(BaseVM):
|
|||||||
log.debug("Control VM '{}' result: {}".format(subcommand, result))
|
log.debug("Control VM '{}' result: {}".format(subcommand, result))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def _read_vmx_file(self):
|
||||||
|
"""
|
||||||
|
Reads from the VMware VMX file corresponding to this VM.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._vmx_pairs = self.manager.parse_vmware_file(self._vmx_path)
|
||||||
|
except OSError as e:
|
||||||
|
raise VMwareError('Could not read VMware VMX file "{}": {}'.format(self._vmx_path, e))
|
||||||
|
|
||||||
|
def _write_vmx_file(self):
|
||||||
|
"""
|
||||||
|
Writes pairs to the VMware VMX file corresponding to this VM.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.manager.write_vmx_file(self._vmx_path, self._vmx_pairs)
|
||||||
|
except OSError as e:
|
||||||
|
raise VMwareError('Could not write VMware VMX file "{}": {}'.format(self._vmx_path, e))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create(self):
|
def create(self):
|
||||||
"""
|
"""
|
||||||
@ -190,41 +213,37 @@ class VMwareVM(BaseVM):
|
|||||||
Set up VMware networking.
|
Set up VMware networking.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# first do some sanity checks
|
# first some sanity checks
|
||||||
for adapter_number in range(0, self._adapters):
|
for adapter_number in range(0, self._adapters):
|
||||||
|
|
||||||
|
# we want the vmnet interface to be connected when starting the VM
|
||||||
connected = "ethernet{}.startConnected".format(adapter_number)
|
connected = "ethernet{}.startConnected".format(adapter_number)
|
||||||
if self._get_vmx_setting(connected):
|
if self._get_vmx_setting(connected):
|
||||||
del self._vmx_pairs[connected]
|
del self._vmx_pairs[connected]
|
||||||
|
|
||||||
# check if any vmnet interface managed by GNS3 is being used on existing VMware adapters
|
|
||||||
if self._get_vmx_setting("ethernet{}.present".format(adapter_number), "TRUE"):
|
|
||||||
connection_type = "ethernet{}.connectiontype".format(adapter_number)
|
|
||||||
if connection_type in self._vmx_pairs and self._vmx_pairs[connection_type] in ("hostonly", "custom"):
|
|
||||||
vnet = "ethernet{}.vnet".format(adapter_number)
|
|
||||||
if vnet in self._vmx_pairs:
|
|
||||||
vmnet = os.path.basename(self._vmx_pairs[vnet])
|
|
||||||
if self.manager.is_managed_vmnet(vmnet):
|
|
||||||
raise VMwareError("Network adapter {} is already associated with VMnet interface {} which is managed by GNS3, please remove".format(adapter_number, vmnet))
|
|
||||||
|
|
||||||
# check for adapter type
|
# check for adapter type
|
||||||
if self._adapter_type != "default":
|
if self._adapter_type != "default":
|
||||||
adapter_type = "ethernet{}.virtualdev".format(adapter_number)
|
adapter_type = "ethernet{}.virtualdev".format(adapter_number)
|
||||||
if adapter_type in self._vmx_pairs and self._vmx_pairs[adapter_type] != self._adapter_type:
|
if adapter_type in self._vmx_pairs and self._vmx_pairs[adapter_type] != self._adapter_type:
|
||||||
raise VMwareError("Network adapter {} is not of type {}, please fix or remove it".format(adapter_number, self._adapter_type))
|
raise VMwareError("Existing VMware network adapter {} is not of type {}, please fix or set adapter type to default in GNS3".format(adapter_number,
|
||||||
|
self._adapter_type))
|
||||||
|
|
||||||
# check if connected to an adapter configured for nat or bridge
|
# # check if any vmnet interface managed by GNS3 is being used on existing VMware adapters
|
||||||
if self._ethernet_adapters[adapter_number].get_nio(0) and not self._use_any_adapter:
|
# if self._get_vmx_setting("ethernet{}.present".format(adapter_number), "TRUE"):
|
||||||
if self._get_vmx_setting("ethernet{}.present".format(adapter_number), "TRUE"):
|
# connection_type = "ethernet{}.connectiontype".format(adapter_number)
|
||||||
# check for the connection type
|
# if connection_type in self._vmx_pairs and self._vmx_pairs[connection_type] in ("hostonly", "custom"):
|
||||||
connection_type = "ethernet{}.connectiontype".format(adapter_number)
|
# vnet = "ethernet{}.vnet".format(adapter_number)
|
||||||
if connection_type in self._vmx_pairs and self._vmx_pairs[connection_type] in ("nat", "bridged", "hostonly"):
|
# if vnet in self._vmx_pairs:
|
||||||
raise VMwareError("Attachment ({}) already configured on network adapter {}. "
|
# vmnet = os.path.basename(self._vmx_pairs[vnet])
|
||||||
"Please remove it or allow GNS3 to use any adapter.".format(self._vmx_pairs[connection_type],
|
# #nio = self._ethernet_adapters[adapter_number].get_nio(0)
|
||||||
adapter_number))
|
# if self.manager.is_managed_vmnet(vmnet):
|
||||||
|
# raise VMwareError("Network adapter {} is already associated with VMnet interface {} which is managed by GNS3, please remove".format(adapter_number, vmnet))
|
||||||
|
|
||||||
# now configure VMware network adapters
|
# then configure VMware network adapters
|
||||||
self.manager.refresh_vmnet_list()
|
self.manager.refresh_vmnet_list()
|
||||||
for adapter_number in range(0, self._adapters):
|
for adapter_number in range(0, self._adapters):
|
||||||
|
|
||||||
|
# add/update the interface
|
||||||
ethernet_adapter = {"ethernet{}.present".format(adapter_number): "TRUE",
|
ethernet_adapter = {"ethernet{}.present".format(adapter_number): "TRUE",
|
||||||
"ethernet{}.addresstype".format(adapter_number): "generated",
|
"ethernet{}.addresstype".format(adapter_number): "generated",
|
||||||
"ethernet{}.generatedaddressoffset".format(adapter_number): "0"}
|
"ethernet{}.generatedaddressoffset".format(adapter_number): "0"}
|
||||||
@ -235,17 +254,34 @@ class VMwareVM(BaseVM):
|
|||||||
connection_type = "ethernet{}.connectiontype".format(adapter_number)
|
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 not self._use_any_adapter and connection_type in self._vmx_pairs and self._vmx_pairs[connection_type] in ("nat", "bridged", "hostonly"):
|
||||||
continue
|
continue
|
||||||
|
self._vmx_pairs["ethernet{}.connectiontype".format(adapter_number)] = "custom"
|
||||||
|
|
||||||
|
if self._use_ubridge:
|
||||||
|
# make sure we have a vmnet per adapter if we use uBridge
|
||||||
|
allocate_vmnet = False
|
||||||
|
|
||||||
|
# first check if a vmnet is already assigned to the adapter
|
||||||
vnet = "ethernet{}.vnet".format(adapter_number)
|
vnet = "ethernet{}.vnet".format(adapter_number)
|
||||||
if vnet in self._vmx_pairs:
|
if vnet in self._vmx_pairs:
|
||||||
vmnet = os.path.basename(self._vmx_pairs[vnet])
|
vmnet = os.path.basename(self._vmx_pairs[vnet])
|
||||||
|
if vmnet in self.manager.is_managed_vmnet(vmnet):
|
||||||
|
# vmnet already managed, try to allocate a new one
|
||||||
|
allocate_vmnet = True
|
||||||
else:
|
else:
|
||||||
|
# otherwise allocate a new one
|
||||||
|
allocate_vmnet = True
|
||||||
|
|
||||||
|
if allocate_vmnet:
|
||||||
try:
|
try:
|
||||||
vmnet = self.manager.allocate_vmnet()
|
vmnet = self.manager.allocate_vmnet()
|
||||||
finally:
|
except:
|
||||||
|
# clear everything up in case of error (e.g. no enough vmnets)
|
||||||
self._vmnets.clear()
|
self._vmnets.clear()
|
||||||
|
raise
|
||||||
|
|
||||||
|
# mark the vmnet managed by us
|
||||||
|
if not vmnet in self._vmnets:
|
||||||
self._vmnets.append(vmnet)
|
self._vmnets.append(vmnet)
|
||||||
self._vmx_pairs["ethernet{}.connectiontype".format(adapter_number)] = "custom"
|
|
||||||
self._vmx_pairs["ethernet{}.vnet".format(adapter_number)] = vmnet
|
self._vmx_pairs["ethernet{}.vnet".format(adapter_number)] = vmnet
|
||||||
|
|
||||||
# disable remaining network adapters
|
# disable remaining network adapters
|
||||||
@ -350,11 +386,7 @@ class VMwareVM(BaseVM):
|
|||||||
:returns: boolean
|
:returns: boolean
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
self._read_vmx_file()
|
||||||
self._vmx_pairs = self.manager.parse_vmware_file(self._vmx_path)
|
|
||||||
except OSError as e:
|
|
||||||
raise VMwareError('Could not read VMware VMX file "{}": {}'.format(self._vmx_path, e))
|
|
||||||
|
|
||||||
if self._get_vmx_setting("vhv.enable", "TRUE"):
|
if self._get_vmx_setting("vhv.enable", "TRUE"):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -372,26 +404,20 @@ class VMwareVM(BaseVM):
|
|||||||
if not ubridge_path or not os.path.isfile(ubridge_path):
|
if not ubridge_path or not os.path.isfile(ubridge_path):
|
||||||
raise VMwareError("ubridge is necessary to start a VMware VM")
|
raise VMwareError("ubridge is necessary to start a VMware VM")
|
||||||
|
|
||||||
|
if self._use_ubridge:
|
||||||
yield from self._start_ubridge()
|
yield from self._start_ubridge()
|
||||||
|
|
||||||
try:
|
self._read_vmx_file()
|
||||||
self._vmx_pairs = self.manager.parse_vmware_file(self._vmx_path)
|
|
||||||
except OSError as e:
|
|
||||||
raise VMwareError('Could not read VMware VMX file "{}": {}'.format(self._vmx_path, e))
|
|
||||||
|
|
||||||
self._set_network_options()
|
self._set_network_options()
|
||||||
self._set_serial_console()
|
self._set_serial_console()
|
||||||
|
self._write_vmx_file()
|
||||||
try:
|
|
||||||
self.manager.write_vmx_file(self._vmx_path, self._vmx_pairs)
|
|
||||||
except OSError as e:
|
|
||||||
raise VMwareError('Could not write VMware VMX file "{}": {}'.format(self._vmx_path, e))
|
|
||||||
|
|
||||||
if self._headless:
|
if self._headless:
|
||||||
yield from self._control_vm("start", "nogui")
|
yield from self._control_vm("start", "nogui")
|
||||||
else:
|
else:
|
||||||
yield from self._control_vm("start")
|
yield from self._control_vm("start")
|
||||||
|
|
||||||
|
if self._use_ubridge:
|
||||||
for adapter_number in range(0, self._adapters):
|
for adapter_number in range(0, self._adapters):
|
||||||
nio = self._ethernet_adapters[adapter_number].get_nio(0)
|
nio = self._ethernet_adapters[adapter_number].get_nio(0)
|
||||||
if nio:
|
if nio:
|
||||||
@ -426,12 +452,10 @@ class VMwareVM(BaseVM):
|
|||||||
yield from self._control_vm("stop")
|
yield from self._control_vm("stop")
|
||||||
finally:
|
finally:
|
||||||
self._started = False
|
self._started = False
|
||||||
self._vmnets.clear()
|
|
||||||
try:
|
|
||||||
self._vmx_pairs = self.manager.parse_vmware_file(self._vmx_path)
|
|
||||||
except OSError as e:
|
|
||||||
raise VMwareError('Could not read VMware VMX file "{}": {}'.format(self._vmx_path, e))
|
|
||||||
|
|
||||||
|
self._read_vmx_file()
|
||||||
|
if self._use_ubridge:
|
||||||
|
self._vmnets.clear()
|
||||||
# remove the adapters managed by GNS3
|
# remove the adapters managed by GNS3
|
||||||
for adapter_number in range(0, self._adapters):
|
for adapter_number in range(0, self._adapters):
|
||||||
if self._get_vmx_setting("ethernet{}.vnet".format(adapter_number)) or \
|
if self._get_vmx_setting("ethernet{}.vnet".format(adapter_number)) or \
|
||||||
@ -451,11 +475,7 @@ class VMwareVM(BaseVM):
|
|||||||
if self._get_vmx_setting("ethernet{}.present".format(adapter_number), "TRUE"):
|
if self._get_vmx_setting("ethernet{}.present".format(adapter_number), "TRUE"):
|
||||||
log.debug("enabling remaining adapter {}".format(adapter_number))
|
log.debug("enabling remaining adapter {}".format(adapter_number))
|
||||||
self._vmx_pairs["ethernet{}.startconnected".format(adapter_number)] = "TRUE"
|
self._vmx_pairs["ethernet{}.startconnected".format(adapter_number)] = "TRUE"
|
||||||
|
self._write_vmx_file()
|
||||||
try:
|
|
||||||
self.manager.write_vmx_file(self._vmx_path, self._vmx_pairs)
|
|
||||||
except OSError as e:
|
|
||||||
raise VMwareError('Could not write VMware VMX file "{}": {}'.format(self._vmx_path, e))
|
|
||||||
|
|
||||||
log.info("VMware VM '{name}' [{id}] stopped".format(name=self.name, id=self.id))
|
log.info("VMware VM '{name}' [{id}] stopped".format(name=self.name, id=self.id))
|
||||||
|
|
||||||
@ -493,7 +513,7 @@ class VMwareVM(BaseVM):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def close(self):
|
def close(self):
|
||||||
"""
|
"""
|
||||||
Closes this VirtualBox VM.
|
Closes this VMware VM.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self._closed:
|
if self._closed:
|
||||||
@ -510,7 +530,8 @@ class VMwareVM(BaseVM):
|
|||||||
for nio in adapter.ports.values():
|
for nio in adapter.ports.values():
|
||||||
if nio and isinstance(nio, NIOUDP):
|
if nio and isinstance(nio, NIOUDP):
|
||||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||||
|
if nio and isinstance(nio, NIOVMNET) and nio.vmnet in self._vmnets:
|
||||||
|
self._vmnets.remove(nio.vmnet)
|
||||||
try:
|
try:
|
||||||
self.acpi_shutdown = False
|
self.acpi_shutdown = False
|
||||||
yield from self.stop()
|
yield from self.stop()
|
||||||
@ -697,6 +718,30 @@ class VMwareVM(BaseVM):
|
|||||||
id=self.id,
|
id=self.id,
|
||||||
adapter_type=adapter_type))
|
adapter_type=adapter_type))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def use_ubridge(self):
|
||||||
|
"""
|
||||||
|
Returns either GNS3 can use uBridge for network connections.
|
||||||
|
|
||||||
|
:returns: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._use_ubridge
|
||||||
|
|
||||||
|
@use_ubridge.setter
|
||||||
|
def use_ubridge(self, use_ubridge):
|
||||||
|
"""
|
||||||
|
Allows GNS3 to use uBridge for network connections.
|
||||||
|
|
||||||
|
:param use_ubridge: boolean
|
||||||
|
"""
|
||||||
|
|
||||||
|
if use_ubridge:
|
||||||
|
log.info("VMware VM '{name}' [{id}] will use uBridge for network connections".format(name=self.name, id=self.id))
|
||||||
|
else:
|
||||||
|
log.info("VMware VM '{name}' [{id}] will not use uBridge for network connections".format(name=self.name, id=self.id))
|
||||||
|
self._use_ubridge = use_ubridge
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def use_any_adapter(self):
|
def use_any_adapter(self):
|
||||||
"""
|
"""
|
||||||
@ -736,8 +781,25 @@ class VMwareVM(BaseVM):
|
|||||||
raise VMwareError("Adapter {adapter_number} doesn't exist on VMware VM '{name}'".format(name=self.name,
|
raise VMwareError("Adapter {adapter_number} doesn't exist on VMware VM '{name}'".format(name=self.name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
adapter.add_nio(0, nio)
|
self._read_vmx_file()
|
||||||
|
# check if trying to connect to a nat, bridged or host-only adapter
|
||||||
|
if self._ethernet_adapters[adapter_number].get_nio(0) and not self._use_any_adapter:
|
||||||
|
if self._get_vmx_setting("ethernet{}.present".format(adapter_number), "TRUE"):
|
||||||
|
# check for the connection type
|
||||||
|
connection_type = "ethernet{}.connectiontype".format(adapter_number)
|
||||||
|
if connection_type in self._vmx_pairs and self._vmx_pairs[connection_type] in ("nat", "bridged", "hostonly"):
|
||||||
|
raise VMwareError("Attachment ({}) already configured on network adapter {}. "
|
||||||
|
"Please remove it or allow GNS3 to use any adapter.".format(self._vmx_pairs[connection_type],
|
||||||
|
adapter_number))
|
||||||
|
|
||||||
|
if isinstance(nio, NIOVMNET):
|
||||||
if self._started:
|
if self._started:
|
||||||
|
raise VMwareError("Sorry, adding a link to a started VMware VM is not supported without uBridge enabled")
|
||||||
|
self._vmx_pairs["ethernet{}.vnet".format(adapter_number)] = nio.vmnet
|
||||||
|
self._write_vmx_file()
|
||||||
|
self._vmnets.append(nio.vmnet)
|
||||||
|
adapter.add_nio(0, nio)
|
||||||
|
if self._started and self._use_ubridge:
|
||||||
yield from self._add_ubridge_connection(nio, adapter_number)
|
yield from self._add_ubridge_connection(nio, adapter_number)
|
||||||
|
|
||||||
log.info("VMware VM '{name}' [{id}]: {nio} added to adapter {adapter_number}".format(name=self.name,
|
log.info("VMware VM '{name}' [{id}]: {nio} added to adapter {adapter_number}".format(name=self.name,
|
||||||
@ -765,8 +827,16 @@ class VMwareVM(BaseVM):
|
|||||||
nio = adapter.get_nio(0)
|
nio = adapter.get_nio(0)
|
||||||
if isinstance(nio, NIOUDP):
|
if isinstance(nio, NIOUDP):
|
||||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||||
|
if isinstance(nio, NIOVMNET):
|
||||||
|
self._read_vmx_file()
|
||||||
|
vnet = "ethernet{}.vnet".format(adapter_number)
|
||||||
|
if vnet in self._vmx_pairs:
|
||||||
|
del self._vmx_pairs[vnet]
|
||||||
|
self._write_vmx_file()
|
||||||
|
if nio.vmnet in self._vmnets:
|
||||||
|
self._vmnets.remove(nio.vmnet)
|
||||||
adapter.remove_nio(0)
|
adapter.remove_nio(0)
|
||||||
if self._started:
|
if self._started and self._use_ubridge:
|
||||||
yield from self._delete_ubridge_connection(adapter_number)
|
yield from self._delete_ubridge_connection(adapter_number)
|
||||||
|
|
||||||
log.info("VMware VM '{name}' [{id}]: {nio} removed from adapter {adapter_number}".format(name=self.name,
|
log.info("VMware VM '{name}' [{id}]: {nio} removed from adapter {adapter_number}".format(name=self.name,
|
||||||
|
@ -143,6 +143,21 @@ NIO_SCHEMA = {
|
|||||||
"required": ["type", "control_file", "local_file"],
|
"required": ["type", "control_file", "local_file"],
|
||||||
"additionalProperties": False
|
"additionalProperties": False
|
||||||
},
|
},
|
||||||
|
"VMNET": {
|
||||||
|
"description": "VMNET Network Input/Output",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": ["nio_vmnet"]
|
||||||
|
},
|
||||||
|
"vmnet": {
|
||||||
|
"description": "VMnet interface name e.g. vmnet12",
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["type", "vmnet"],
|
||||||
|
"additionalProperties": False
|
||||||
|
},
|
||||||
"NULL": {
|
"NULL": {
|
||||||
"description": "NULL Network Input/Output",
|
"description": "NULL Network Input/Output",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -162,6 +177,7 @@ NIO_SCHEMA = {
|
|||||||
{"$ref": "#/definitions/TAP"},
|
{"$ref": "#/definitions/TAP"},
|
||||||
{"$ref": "#/definitions/UNIX"},
|
{"$ref": "#/definitions/UNIX"},
|
||||||
{"$ref": "#/definitions/VDE"},
|
{"$ref": "#/definitions/VDE"},
|
||||||
|
{"$ref": "#/definitions/VMNET"},
|
||||||
{"$ref": "#/definitions/NULL"},
|
{"$ref": "#/definitions/NULL"},
|
||||||
],
|
],
|
||||||
"additionalProperties": True,
|
"additionalProperties": True,
|
||||||
|
@ -71,6 +71,10 @@ VMWARE_CREATE_SCHEMA = {
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
},
|
},
|
||||||
|
"use_ubridge": {
|
||||||
|
"description": "use uBridge for network connections",
|
||||||
|
"type": "boolean",
|
||||||
|
},
|
||||||
"use_any_adapter": {
|
"use_any_adapter": {
|
||||||
"description": "allow GNS3 to use any VMware adapter",
|
"description": "allow GNS3 to use any VMware adapter",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@ -124,6 +128,10 @@ VMWARE_UPDATE_SCHEMA = {
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
},
|
},
|
||||||
|
"use_ubridge": {
|
||||||
|
"description": "use uBridge for network connections",
|
||||||
|
"type": "boolean",
|
||||||
|
},
|
||||||
"use_any_adapter": {
|
"use_any_adapter": {
|
||||||
"description": "allow GNS3 to use any VMware adapter",
|
"description": "allow GNS3 to use any VMware adapter",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@ -188,6 +196,10 @@ VMWARE_OBJECT_SCHEMA = {
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
},
|
},
|
||||||
|
"use_ubridge": {
|
||||||
|
"description": "use uBridge for network connections",
|
||||||
|
"type": "boolean",
|
||||||
|
},
|
||||||
"use_any_adapter": {
|
"use_any_adapter": {
|
||||||
"description": "allow GNS3 to use any VMware adapter",
|
"description": "allow GNS3 to use any VMware adapter",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
Loading…
Reference in New Issue
Block a user