mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-25 00:08:11 +00:00
Add an appliance templates directory
Fix https://github.com/GNS3/gns3-gui/issues/2133
This commit is contained in:
parent
ac10ba370a
commit
7d123f334f
@ -11,9 +11,13 @@ certkey=/home/gns3/.config/GNS3/ssl/server.key
|
|||||||
|
|
||||||
; Path where devices images are stored
|
; Path where devices images are stored
|
||||||
images_path = /home/gns3/GNS3/images
|
images_path = /home/gns3/GNS3/images
|
||||||
|
|
||||||
; Path where user projects are stored
|
; Path where user projects are stored
|
||||||
projects_path = /home/gns3/GNS3/projects
|
projects_path = /home/gns3/GNS3/projects
|
||||||
|
|
||||||
|
; Path where user appliances are stored
|
||||||
|
appliances_path = /home/gns3/GNS3/appliances
|
||||||
|
|
||||||
; Option to automatically send crash reports to the GNS3 team
|
; Option to automatically send crash reports to the GNS3 team
|
||||||
report_errors = True
|
report_errors = True
|
||||||
|
|
||||||
|
@ -66,13 +66,17 @@ class Controller:
|
|||||||
|
|
||||||
def load_appliances(self):
|
def load_appliances(self):
|
||||||
self._appliance_templates = {}
|
self._appliance_templates = {}
|
||||||
for file in os.listdir(get_resource('appliances')):
|
for directory, builtin in (
|
||||||
path = os.path.join(get_resource('appliances'), file)
|
(get_resource('appliances'), True,), (self.appliances_path(), False,)
|
||||||
appliance_id = uuid.uuid3(uuid.NAMESPACE_URL, path) # Generate the UUID from path to avoid change between reboots
|
):
|
||||||
with open(path, 'r', encoding='utf-8') as f:
|
if os.path.isdir(directory):
|
||||||
appliance = ApplianceTemplate(appliance_id, json.load(f))
|
for file in os.listdir(directory):
|
||||||
if appliance.status != 'broken':
|
path = os.path.join(directory, file)
|
||||||
self._appliance_templates[appliance.id] = appliance
|
appliance_id = uuid.uuid3(uuid.NAMESPACE_URL, path) # Generate the UUID from path to avoid change between reboots
|
||||||
|
with open(path, 'r', encoding='utf-8') as f:
|
||||||
|
appliance = ApplianceTemplate(appliance_id, json.load(f), builtin=builtin)
|
||||||
|
if appliance.status != 'broken':
|
||||||
|
self._appliance_templates[appliance.id] = appliance
|
||||||
|
|
||||||
self._appliances = {}
|
self._appliances = {}
|
||||||
vms = []
|
vms = []
|
||||||
@ -304,6 +308,15 @@ class Controller:
|
|||||||
os.makedirs(images_path, exist_ok=True)
|
os.makedirs(images_path, exist_ok=True)
|
||||||
return images_path
|
return images_path
|
||||||
|
|
||||||
|
def appliances_path(self):
|
||||||
|
"""
|
||||||
|
Get the image storage directory
|
||||||
|
"""
|
||||||
|
server_config = Config.instance().get_section_config("Server")
|
||||||
|
appliances_path = os.path.expanduser(server_config.get("appliances_path", "~/GNS3/projects"))
|
||||||
|
os.makedirs(appliances_path, exist_ok=True)
|
||||||
|
return appliances_path
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _import_gns3_gui_conf(self):
|
def _import_gns3_gui_conf(self):
|
||||||
"""
|
"""
|
||||||
|
@ -21,7 +21,7 @@ import uuid
|
|||||||
|
|
||||||
class ApplianceTemplate:
|
class ApplianceTemplate:
|
||||||
|
|
||||||
def __init__(self, appliance_id, data):
|
def __init__(self, appliance_id, data, builtin=True):
|
||||||
if appliance_id is None:
|
if appliance_id is None:
|
||||||
self._id = str(uuid.uuid4())
|
self._id = str(uuid.uuid4())
|
||||||
elif isinstance(appliance_id, uuid.UUID):
|
elif isinstance(appliance_id, uuid.UUID):
|
||||||
@ -29,6 +29,7 @@ class ApplianceTemplate:
|
|||||||
else:
|
else:
|
||||||
self._id = appliance_id
|
self._id = appliance_id
|
||||||
self._data = data.copy()
|
self._data = data.copy()
|
||||||
|
self._builtin = builtin
|
||||||
if "appliance_id" in self._data:
|
if "appliance_id" in self._data:
|
||||||
del self._data["appliance_id"]
|
del self._data["appliance_id"]
|
||||||
|
|
||||||
@ -44,4 +45,6 @@ class ApplianceTemplate:
|
|||||||
"""
|
"""
|
||||||
Appliance data (a hash)
|
Appliance data (a hash)
|
||||||
"""
|
"""
|
||||||
return copy.deepcopy(self._data)
|
data = copy.deepcopy(self._data)
|
||||||
|
data["builtin"] = self._builtin
|
||||||
|
return data
|
||||||
|
@ -206,6 +206,8 @@ host = 0.0.0.0
|
|||||||
port = 3080
|
port = 3080
|
||||||
images_path = /opt/gns3/images
|
images_path = /opt/gns3/images
|
||||||
projects_path = /opt/gns3/projects
|
projects_path = /opt/gns3/projects
|
||||||
|
appliances_path = /opt/gns3/appliances
|
||||||
|
configs_path = /opt/gns3/configs
|
||||||
report_errors = True
|
report_errors = True
|
||||||
|
|
||||||
[Qemu]
|
[Qemu]
|
||||||
|
@ -205,6 +205,7 @@ def run_around_tests(monkeypatch, port_manager, controller, config):
|
|||||||
config.set("Server", "projects_path", os.path.join(tmppath, 'projects'))
|
config.set("Server", "projects_path", os.path.join(tmppath, 'projects'))
|
||||||
config.set("Server", "symbols_path", os.path.join(tmppath, 'symbols'))
|
config.set("Server", "symbols_path", os.path.join(tmppath, 'symbols'))
|
||||||
config.set("Server", "images_path", os.path.join(tmppath, 'images'))
|
config.set("Server", "images_path", os.path.join(tmppath, 'images'))
|
||||||
|
config.set("Server", "appliances_path", os.path.join(tmppath, 'appliances'))
|
||||||
config.set("Server", "ubridge_path", os.path.join(tmppath, 'bin', 'ubridge'))
|
config.set("Server", "ubridge_path", os.path.join(tmppath, 'bin', 'ubridge'))
|
||||||
config.set("Server", "auth", False)
|
config.set("Server", "auth", False)
|
||||||
|
|
||||||
@ -227,7 +228,7 @@ def run_around_tests(monkeypatch, port_manager, controller, config):
|
|||||||
# An helper should not raise Exception
|
# An helper should not raise Exception
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(tmppath)
|
shutil.rmtree(tmppath)
|
||||||
except:
|
except BaseException:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import json
|
|||||||
import pytest
|
import pytest
|
||||||
import socket
|
import socket
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock, patch
|
||||||
from tests.utils import AsyncioMagicMock, asyncio_patch
|
from tests.utils import AsyncioMagicMock, asyncio_patch
|
||||||
|
|
||||||
from gns3server.controller.compute import Compute
|
from gns3server.controller.compute import Compute
|
||||||
@ -460,12 +460,6 @@ def test_get_free_project_name(controller, async_run):
|
|||||||
assert controller.get_free_project_name("Hello") == "Hello"
|
assert controller.get_free_project_name("Hello") == "Hello"
|
||||||
|
|
||||||
|
|
||||||
def test_appliance_templates(controller):
|
|
||||||
assert len(controller.appliance_templates) > 0
|
|
||||||
for appliance in controller.appliance_templates.values():
|
|
||||||
assert appliance.__json__()["status"] != "broken"
|
|
||||||
|
|
||||||
|
|
||||||
def test_load_base_files(controller, config, tmpdir):
|
def test_load_base_files(controller, config, tmpdir):
|
||||||
config.set_section_config("Server", {"configs_path": str(tmpdir)})
|
config.set_section_config("Server", {"configs_path": str(tmpdir)})
|
||||||
|
|
||||||
@ -480,10 +474,28 @@ def test_load_base_files(controller, config, tmpdir):
|
|||||||
assert f.read() == 'test'
|
assert f.read() == 'test'
|
||||||
|
|
||||||
|
|
||||||
def test_appliance_templates(controller, async_run):
|
def test_appliance_templates(controller, async_run, tmpdir):
|
||||||
controller.load_appliances()
|
my_appliance = {
|
||||||
|
"name": "My Appliance",
|
||||||
|
"status": "stable"
|
||||||
|
}
|
||||||
|
with open(str(tmpdir / "my_appliance.gns3a"), 'w+') as f:
|
||||||
|
json.dump(my_appliance, f)
|
||||||
|
|
||||||
|
with patch("gns3server.config.Config.get_section_config", return_value={"appliances_path": str(tmpdir)}):
|
||||||
|
controller.load_appliances()
|
||||||
assert len(controller.appliance_templates) > 0
|
assert len(controller.appliance_templates) > 0
|
||||||
|
for appliance in controller.appliance_templates.values():
|
||||||
|
assert appliance.__json__()["status"] != "broken"
|
||||||
assert "Alpine Linux" in [c.__json__()["name"] for c in controller.appliance_templates.values()]
|
assert "Alpine Linux" in [c.__json__()["name"] for c in controller.appliance_templates.values()]
|
||||||
|
assert "My Appliance" in [c.__json__()["name"] for c in controller.appliance_templates.values()]
|
||||||
|
|
||||||
|
for c in controller.appliance_templates.values():
|
||||||
|
j = c.__json__()
|
||||||
|
if j["name"] == "Alpine Linux":
|
||||||
|
assert j["builtin"]
|
||||||
|
elif j["name"] == "My Appliance":
|
||||||
|
assert not j["builtin"]
|
||||||
|
|
||||||
|
|
||||||
def test_load_appliances(controller):
|
def test_load_appliances(controller):
|
||||||
@ -526,4 +538,3 @@ def test_autoidlepc(controller, async_run):
|
|||||||
async_run(controller.autoidlepc("local", "c7200", "test.bin"))
|
async_run(controller.autoidlepc("local", "c7200", "test.bin"))
|
||||||
assert node_mock.dynamips_auto_idlepc.called
|
assert node_mock.dynamips_auto_idlepc.called
|
||||||
assert len(controller.projects) == 0
|
assert len(controller.projects) == 0
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user