mirror of
https://github.com/GNS3/gns3-server
synced 2025-06-28 02:42:39 +00:00
Add new method to find the IP address of a VBox GNS3 VM + allow NAT Network
This commit is contained in:
parent
a5a663bc99
commit
a24d2e25ed
@ -247,6 +247,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def list(self):
|
async def list(self):
|
||||||
"""
|
"""
|
||||||
List all VirtualBox VMs
|
List all VirtualBox VMs
|
||||||
@ -267,8 +268,8 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
|
|
||||||
# get a NAT interface number
|
# get a NAT interface number
|
||||||
nat_interface_number = await self._look_for_interface("nat")
|
nat_interface_number = await self._look_for_interface("nat")
|
||||||
if nat_interface_number < 0:
|
if nat_interface_number < 0 and await self._look_for_interface("natnetwork") < 0:
|
||||||
raise GNS3VMError('VM "{}" must have a NAT interface configured in order to start'.format(self.vmname))
|
raise GNS3VMError('VM "{}" must have a NAT or NAT Network interface configured in order to start'.format(self.vmname))
|
||||||
|
|
||||||
if sys.platform.startswith("darwin") and parse_version(self._system_properties["API version"]) >= parse_version("7_0"):
|
if sys.platform.startswith("darwin") and parse_version(self._system_properties["API version"]) >= parse_version("7_0"):
|
||||||
# VirtualBox 7.0+ on macOS requires a host-only network interface
|
# VirtualBox 7.0+ on macOS requires a host-only network interface
|
||||||
@ -337,39 +338,68 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
elif vm_state == "paused":
|
elif vm_state == "paused":
|
||||||
args = [self._vmname, "resume"]
|
args = [self._vmname, "resume"]
|
||||||
await self._execute("controlvm", args)
|
await self._execute("controlvm", args)
|
||||||
ip_address = "127.0.0.1"
|
|
||||||
try:
|
|
||||||
# get a random port on localhost
|
|
||||||
with socket.socket() as s:
|
|
||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
s.bind((ip_address, 0))
|
|
||||||
api_port = s.getsockname()[1]
|
|
||||||
except OSError as e:
|
|
||||||
raise GNS3VMError("Error while getting random port: {}".format(e))
|
|
||||||
|
|
||||||
if await self._check_vbox_port_forwarding():
|
log.info("Retrieving IP address from GNS3 VM...")
|
||||||
# delete the GNS3VM NAT port forwarding rule if it exists
|
ip = await self._get_ip_from_guest_property()
|
||||||
log.info("Removing GNS3VM NAT port forwarding rule from interface {}".format(nat_interface_number))
|
if ip:
|
||||||
await self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number), "delete", "GNS3VM"])
|
self.ip_address = ip
|
||||||
|
else:
|
||||||
|
# if we can't get the IP address from the guest property, we try to get it from the GNS3 server (a NAT interface is required)
|
||||||
|
if nat_interface_number < 0:
|
||||||
|
raise GNS3VMError("Could not find guest IP address for {}".format(self.vmname))
|
||||||
|
log.warning("Could not find IP address from guest property, trying to get it from GNS3 server")
|
||||||
|
ip_address = "127.0.0.1"
|
||||||
|
try:
|
||||||
|
# get a random port on localhost
|
||||||
|
with socket.socket() as s:
|
||||||
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
s.bind((ip_address, 0))
|
||||||
|
api_port = s.getsockname()[1]
|
||||||
|
except OSError as e:
|
||||||
|
raise GNS3VMError("Error while getting random port: {}".format(e))
|
||||||
|
|
||||||
# add a GNS3VM NAT port forwarding rule to redirect 127.0.0.1 with random port to the port in the VM
|
if await self._check_vbox_port_forwarding():
|
||||||
log.info("Adding GNS3VM NAT port forwarding rule with port {} to interface {}".format(api_port, nat_interface_number))
|
# delete the GNS3VM NAT port forwarding rule if it exists
|
||||||
await self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number),
|
log.info("Removing GNS3VM NAT port forwarding rule from interface {}".format(nat_interface_number))
|
||||||
"GNS3VM,tcp,{},{},,{}".format(ip_address, api_port, self.port)])
|
await self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number), "delete", "GNS3VM"])
|
||||||
|
|
||||||
self.ip_address = await self._get_ip(interface_number, api_port)
|
# add a GNS3VM NAT port forwarding rule to redirect 127.0.0.1 with random port to the port in the VM
|
||||||
log.info("GNS3 VM has been started with IP {}".format(self.ip_address))
|
log.info("Adding GNS3VM NAT port forwarding rule with port {} to interface {}".format(api_port, nat_interface_number))
|
||||||
|
await self._execute("controlvm", [self._vmname, "natpf{}".format(nat_interface_number),
|
||||||
|
"GNS3VM,tcp,{},{},,{}".format(ip_address, api_port, self.port)])
|
||||||
|
|
||||||
|
self.ip_address = await self._get_ip_from_server(interface_number, api_port)
|
||||||
|
|
||||||
|
log.info("GNS3 VM has been started with IP '{}'".format(self.ip_address))
|
||||||
self.running = True
|
self.running = True
|
||||||
|
|
||||||
async def _get_ip(self, hostonly_interface_number, api_port):
|
async def _get_ip_from_guest_property(self):
|
||||||
"""
|
"""
|
||||||
Get the IP from VirtualBox.
|
Get the IP from VirtualBox by retrieving the guest property (Guest Additions must be installed).
|
||||||
|
"""
|
||||||
|
|
||||||
|
remaining_try = 180 # try for 3 minutes
|
||||||
|
while remaining_try > 0:
|
||||||
|
result = await self._execute("guestproperty", ["get", self._vmname, "/VirtualBox/GuestInfo/Net/0/V4/IP"])
|
||||||
|
for info in result.splitlines():
|
||||||
|
if ':' in info:
|
||||||
|
name, value = info.split(':', 1)
|
||||||
|
if name == "Value":
|
||||||
|
return value.strip()
|
||||||
|
remaining_try -= 1
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def _get_ip_from_server(self, hostonly_interface_number, api_port):
|
||||||
|
"""
|
||||||
|
Get the IP from VirtualBox by sending a request to the GNS3 server.
|
||||||
|
|
||||||
Due to VirtualBox limitation the only way is to send request each
|
Due to VirtualBox limitation the only way is to send request each
|
||||||
second to a GNS3 endpoint in order to get the list of the interfaces and
|
second to a GNS3 endpoint in order to get the list of the interfaces and
|
||||||
their IP and after that match it with VirtualBox host only.
|
their IP and after that match it with VirtualBox host only.
|
||||||
"""
|
"""
|
||||||
remaining_try = 300
|
|
||||||
|
remaining_try = 180 # try for 3 minutes
|
||||||
while remaining_try > 0:
|
while remaining_try > 0:
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
try:
|
try:
|
||||||
|
Loading…
Reference in New Issue
Block a user