diff --git a/gns3server/controller/base_gns3_vm.py b/gns3server/controller/base_gns3_vm.py index 4d86ac9b..458c99e4 100644 --- a/gns3server/controller/base_gns3_vm.py +++ b/gns3server/controller/base_gns3_vm.py @@ -15,10 +15,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +from .gns3_vm_error import GNS3VMError + import os import sys import json import asyncio +import psutil import logging log = logging.getLogger(__name__) @@ -43,6 +46,16 @@ class BaseGNS3VM: else: config_path = os.path.join(os.path.expanduser("~"), ".config", "GNS3") self._config_file = os.path.join(config_path, "gns3_vm.conf") + + # limit the number of vCPUs to the number of physical cores (hyper thread CPUs are excluded) + # because this is likely to degrade performances. + self._vcpus = psutil.cpu_count(logical=False) + # we want to allocate half of the available physical memory + ram = int(psutil.virtual_memory().total / (1024 * 1024) / 2) + # value must be a multiple of 4 (VMware requirement) + ram -= ram % 4 + self._ram = ram + self.load() def __json__(self): diff --git a/gns3server/controller/vmware_gns3_vm.py b/gns3server/controller/vmware_gns3_vm.py index b32cd591..c9e71b1c 100644 --- a/gns3server/controller/vmware_gns3_vm.py +++ b/gns3server/controller/vmware_gns3_vm.py @@ -18,6 +18,7 @@ import os import logging import asyncio +import psutil from gns3server.compute.vmware import ( VMware, @@ -56,6 +57,18 @@ class VMwareGNS3VM(BaseGNS3VM): :param ram: amount of RAM """ + available_ram = int(psutil.virtual_memory().available / (1024 * 1024)) + if ram > available_ram: + raise GNS3VMError("You have allocated too much memory for the GNS3 VM! (available memory is {} MB)".format(available_ram)) + + # memory must be a multiple of 4 (VMware requirement) + if ram % 4 != 0: + raise GNS3VMError("Allocated memory for the GNS3 VM must be a multiple of 4".format(available_ram)) + + available_vcpus = psutil.cpu_count(logical=False) + if vcpus > available_vcpus: + raise GNS3VMError("You have allocated too many vCPUs for the GNS3 VM! (max available is {} vCPUs)".format(available_vcpus)) + try: pairs = VMware.parse_vmware_file(self._vmx_path) pairs["numvcpus"] = str(vcpus) @@ -91,8 +104,8 @@ class VMwareGNS3VM(BaseGNS3VM): if not os.path.exists(self._vmx_path): raise GNS3VMError("VMware VMX file {} doesn't exist".format(self._vmx_path)) - # set the number of vCPUs and amount of RAM # FIXME - # yield from self._set_vcpus_ram(self.vcpus, self.ram) + # set the number of vCPUs and amount of RAM + yield from self._set_vcpus_ram(self.vcpus, self.ram) # start the VM args = [self._vmx_path] diff --git a/gns3server/web/route.py b/gns3server/web/route.py index e956ed59..ddd8297f 100644 --- a/gns3server/web/route.py +++ b/gns3server/web/route.py @@ -31,6 +31,7 @@ log = logging.getLogger(__name__) from ..compute.error import NodeError, ImageMissingError from ..controller.controller_error import ControllerError from ..ubridge.ubridge_error import UbridgeError +from ..controller.gns3_vm_error import GNS3VMError from .response import Response from ..crash_report import CrashReport from ..config import Config @@ -205,7 +206,7 @@ class Route(object): response = Response(request=request, route=route) response.set_status(e.status) response.json({"message": e.text, "status": e.status}) - except (ControllerError) as e: + except (ControllerError, GNS3VMError) as e: log.error("Controller error detected: {type}".format(type=type(e)), exc_info=1) response = Response(request=request, route=route) response.set_status(409)