1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-12 19:38:57 +00:00

Start GNS3 VM with the controller

Ref https://github.com/GNS3/gns3-gui/issues/1254
This commit is contained in:
Julien Duponchelle 2016-08-25 11:49:06 +02:00
parent 21b99ad9f9
commit fc8b4c3216
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8
5 changed files with 170 additions and 6 deletions

View File

@ -62,6 +62,7 @@ class Controller:
@asyncio.coroutine
def start(self):
log.info("Start controller")
yield from self.load()
server_config = Config.instance().get_section_config("Server")
self._computes["local"] = Compute(compute_id="local",
controller=self,
@ -70,7 +71,16 @@ class Controller:
port=server_config.getint("port", 3080),
user=server_config.get("user", ""),
password=server_config.get("password", ""))
yield from self.load()
if self.gns3vm.enable:
yield from self.gns3vm.start()
self._computes["vm"] = Compute(compute_id="vm",
name="GNS3 VM",
controller=self,
protocol=self.gns3vm.protocol,
host=self.gns3vm.ip_address,
port=self.gns3vm.port,
user=self.gns3vm.user,
password=self.gns3vm.password)
@asyncio.coroutine
def stop(self):

View File

@ -21,6 +21,9 @@ import asyncio
from .vmware_gns3_vm import VMwareGNS3VM
from .virtualbox_gns3_vm import VirtualBoxGNS3VM
import logging
log = logging.getLogger(__name__)
class GNS3VM:
"""
@ -62,6 +65,61 @@ class GNS3VM:
virtualbox_informations
]
def _current_engine(self):
return self._get_engine(self._settings["engine"])
@property
def ip_address(self):
"""
Returns the GNS3 VM IP address.
:returns: VM IP address
"""
return self._current_engine().ip_address
@property
def user(self):
"""
Returns the GNS3 VM user.
:returns: VM user
"""
return self._current_engine().user
@property
def password(self):
"""
Returns the GNS3 VM password.
:returns: VM password
"""
return self._current_engine().password
@property
def port(self):
"""
Returns the GNS3 VM port.
:returns: VM port
"""
return self._current_engine().port
@property
def protocol(self):
"""
Returns the GNS3 VM protocol.
:returns: VM protocol
"""
return self._current_engine().protocol
@property
def enable(self):
"""
The GNSVM is activated
"""
return self._settings["enable"]
@property
def settings(self):
return self._settings
@ -99,3 +157,15 @@ class GNS3VM:
for vm in (yield from engine.list()):
vms.append({"vmname": vm["vmname"]})
return vms
@asyncio.coroutine
def start(self):
"""
Start the GNS3 VM
"""
engine = self._current_engine()
if not engine.running:
log.info("Start the GNS3 VM")
engine.vmname = self._settings["vmname"]
yield from engine.start()

View File

@ -33,15 +33,21 @@ class BaseGNS3VM:
self._headless = False
self._vcpus = 1
self._ram = 1024
self._user = ""
self.password = ""
self._protocol = "http"
self._running = False
# 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)
#ram = int(psutil.virtual_memory().total / (1024 * 1024) / 2)
# value must be a multiple of 4 (VMware requirement)
ram -= ram % 4
#ram -= ram % 4
ram = 2048
self._ram = ram
@property
@ -64,6 +70,60 @@ class BaseGNS3VM:
self._vmname = new_name
@property
def protocol(self):
"""
Get the GNS3 VM protocol
:returns: Protocol as string
"""
return self._protocol
@protocol.setter
def protocol(self, val):
"""
Sets the GNS3 VM protocol
:param val: new VM protocol
"""
self._protocol = val
@property
def user(self):
"""
Get the GNS3 VM user
:returns: User as string
"""
return self._user
@user.setter
def user(self, val):
"""
Sets the GNS3 VM user
:param val: new VM user
"""
self._user = val
@property
def password(self):
"""
Get the GNS3 VM password
:returns: Password as string
"""
return self._password
@password.setter
def password(self, val):
"""
Sets the GNS3 VM password
:param val: new VM password
"""
self._password = val
@property
def port(self):
"""

View File

@ -59,9 +59,10 @@ class VMwareGNS3VM(BaseGNS3VM):
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))
raise GNS3VMError("You have allocated too much memory ({} MB) for the GNS3 VM! (available memory is {} MB)".format(ram, 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))
@ -100,12 +101,12 @@ class VMwareGNS3VM(BaseGNS3VM):
# check we have a valid VMX file path
if not self._vmx_path:
raise GNS3VMError("GNS3 VM is not configured")
raise GNS3VMError("VMWare VM {} not found".format(self.vmname))
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
yield from self._set_vcpus_ram(self.vcpus, self.ram)
#yield from self._set_vcpus_ram(self.vcpus, self.ram)
# start the VM
args = [self._vmx_path]

View File

@ -19,6 +19,7 @@ import os
import uuid
import json
import pytest
import socket
import aiohttp
from unittest.mock import MagicMock
from tests.utils import AsyncioMagicMock, asyncio_patch
@ -252,6 +253,28 @@ def test_getProject(controller, async_run):
assert controller.get_project("dsdssd")
def test_start(controller, async_run):
async_run(controller.start())
assert len(controller.computes) == 1 # Local compute is created
assert controller.computes["local"].name == socket.gethostname()
def test_start_vm(controller, async_run):
"""
Start the controller with a GNS3 VM
"""
controller.gns3vm.settings = {
"enable": True,
"engine": "vmware"
}
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start") as mock:
async_run(controller.start())
assert mock.called
assert len(controller.computes) == 2 # Local compute and vm are created
assert "local" in controller.computes
assert "vm" in controller.computes
def test_stop(controller, async_run):
c = async_run(controller.add_compute(compute_id="test1"))
c._connected = True