Merge branch '2.1' into 2.2

# Conflicts:
#	gns3server/compute/docker/docker_vm.py
#	gns3server/controller/compute.py
#	gns3server/controller/gns3vm/__init__.py
#	gns3server/controller/link.py
#	gns3server/controller/project.py
#	gns3server/handlers/api/controller/project_handler.py
#	gns3server/handlers/api/controller/server_handler.py
#	gns3server/utils/asyncio/__init__.py
#	gns3server/utils/asyncio/telnet_server.py
#	gns3server/version.py
#	gns3server/web/web_server.py
#	tests/compute/qemu/test_qemu_vm.py
This commit is contained in:
grossmj committed 2018-08-29 15:57:54 +07:00
commit 33e8710495
43 files changed
+362 -193

No files matched your search

+18 -10
View File
@@ -21,7 +21,7 @@ import asyncio
import aiohttp
import ipaddress
from ...utils.asyncio import locked_coroutine, asyncio_ensure_future
from ...utils.asyncio import locking, asyncio_ensure_future
from .vmware_gns3_vm import VMwareGNS3VM
from .virtualbox_gns3_vm import VirtualBoxGNS3VM
from .hyperv_gns3_vm import HyperVGNS3VM
@@ -278,13 +278,15 @@ class GNS3VM:
except GNS3VMError as e:
# User will receive the error later when they will try to use the node
try:
yield from self._controller.add_compute(compute_id="vm",
name="GNS3 VM ({})".format(self.current_engine().vmname),
host=None,
force=True)
compute = yield from self._controller.add_compute(compute_id="vm",
name="GNS3 VM ({})".format(self.current_engine().vmname),
host=None,
force=True)
compute.set_last_error(str(e))
except aiohttp.web.HTTPConflict:
pass
log.error("Can't start the GNS3 VM: %s", str(e))
log.error("Cannot start the GNS3 VM: {}".format(e))
@asyncio.coroutine
def exit_vm(self):
@@ -298,7 +300,8 @@ class GNS3VM:
except GNS3VMError as e:
log.warning(str(e))
@locked_coroutine
@locking
@asyncio.coroutine
def start(self):
"""
Start the GNS3 VM
@@ -323,8 +326,9 @@ class GNS3VM:
yield from engine.start()
except Exception as e:
yield from self._controller.delete_compute("vm")
log.error("Can't start the GNS3 VM: {}".format(str(e)))
log.error("Cannot start the GNS3 VM: {}".format(str(e)))
yield from compute.update(name="GNS3 VM ({})".format(engine.vmname))
compute.set_last_error(str(e))
raise e
yield from compute.connect() # we can connect now that the VM has started
yield from compute.update(name="GNS3 VM ({})".format(engine.vmname),
@@ -370,8 +374,11 @@ class GNS3VM:
self._controller.notification.controller_emit("log.warning", {"message": msg})
except ComputeError as e:
log.warning("Could not check the VM is in the same subnet as the local server: {}".format(e))
except aiohttp.web.HTTPConflict as e:
log.warning("Could not check the VM is in the same subnet as the local server: {}".format(e.text))
@locked_coroutine
@locking
@asyncio.coroutine
def _suspend(self):
"""
Suspend the GNS3 VM
@@ -383,7 +390,8 @@ class GNS3VM:
log.info("Suspend the GNS3 VM")
yield from engine.suspend()
@locked_coroutine
@locking
@asyncio.coroutine
def _stop(self):
"""
Stop the GNS3 VM
@@ -15,6 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import aiohttp
import logging
import asyncio
@@ -107,7 +108,6 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
Check if the DHCP server associated with a vboxnet is enabled.
:param vboxnet: vboxnet name
:returns: boolean
"""
@@ -125,6 +125,41 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
return True
return False
@asyncio.coroutine
def _check_vboxnet_exists(self, vboxnet):
"""
Check if the vboxnet interface exists
:param vboxnet: vboxnet name
:returns: boolean
"""
properties = yield from self._execute("list", ["hostonlyifs"])
for prop in properties.splitlines():
try:
name, value = prop.split(':', 1)
except ValueError:
continue
if name.strip() == "Name" and value.strip() == vboxnet:
return True
return False
@asyncio.coroutine
def _find_first_available_vboxnet(self):
"""
Find the first available vboxnet.
"""
properties = yield from self._execute("list", ["hostonlyifs"])
for prop in properties.splitlines():
try:
name, value = prop.split(':', 1)
except ValueError:
continue
if name.strip() == "Name":
return value.strip()
return None
@asyncio.coroutine
def _check_vbox_port_forwarding(self):
"""
@@ -158,18 +193,32 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
# get a NAT interface number
nat_interface_number = yield from self._look_for_interface("nat")
if nat_interface_number < 0:
raise GNS3VMError("The GNS3 VM: {} must have a NAT interface configured in order to start".format(self.vmname))
raise GNS3VMError('VM "{}" must have a NAT interface configured in order to start'.format(self.vmname))
hostonly_interface_number = yield from self._look_for_interface("hostonly")
if hostonly_interface_number < 0:
raise GNS3VMError("The GNS3 VM: {} must have a host only interface configured in order to start".format(self.vmname))
raise GNS3VMError('VM "{}" must have a host-only interface configured in order to start'.format(self.vmname))
vboxnet = yield from self._look_for_vboxnet(hostonly_interface_number)
if vboxnet is None:
raise GNS3VMError("VirtualBox host-only network could not be found for interface {} on GNS3 VM".format(hostonly_interface_number))
raise GNS3VMError('A VirtualBox host-only network could not be found on network adapter {} for "{}"'.format(hostonly_interface_number, self._vmname))
if not (yield from self._check_vboxnet_exists(vboxnet)):
if sys.platform.startswith("win") and vboxnet == "vboxnet0":
# The GNS3 VM is configured with vboxnet0 by default which is not available
# on Windows. Try to patch this with the first available vboxnet we find.
first_available_vboxnet = yield from self._find_first_available_vboxnet()
if first_available_vboxnet is None:
raise GNS3VMError('Please add a VirtualBox host-only network with DHCP enabled and attached it to network adapter {} for "{}"'.format(hostonly_interface_number, self._vmname))
yield from self.set_hostonly_network(hostonly_interface_number, first_available_vboxnet)
vboxnet = first_available_vboxnet
else:
raise GNS3VMError('VirtualBox host-only network "{}" does not exist, please make the sure the network adapter {} configuration is valid for "{}"'.format(vboxnet,
hostonly_interface_number,
self._vmname))
if not (yield from self._check_dhcp_server(vboxnet)):
raise GNS3VMError("DHCP must be enabled on VirtualBox host-only network: {} for GNS3 VM".format(vboxnet))
raise GNS3VMError('DHCP must be enabled on VirtualBox host-only network "{}"'.format(vboxnet))
vm_state = yield from self._get_state()
log.info('"{}" state is {}'.format(self._vmname, vm_state))
@@ -311,3 +360,17 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
yield from self._execute("modifyvm", [self._vmname, "--memory", str(ram)], timeout=3)
log.info("GNS3 VM RAM amount set to {}".format(ram))
@asyncio.coroutine
def set_hostonly_network(self, adapter_number, hostonly_network_name):
"""
Set a VirtualBox host-only network on a network adapter for the GNS3 VM.
:param adapter_number: network adapter number
:param hostonly_network_name: name of the VirtualBox host-only network
"""
yield from self._execute("modifyvm", [self._vmname, "--hostonlyadapter{}".format(adapter_number), hostonly_network_name], timeout=3)
log.info('VirtualBox host-only network "{}" set on network adapter {} for "{}"'.format(hostonly_network_name,
adapter_number,
self._vmname))