1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-28 11:18:11 +00:00

Merge pull request #1133 from GNS3/appliances_dir

Add an appliance templates directory
This commit is contained in:
Jeremy Grossmann 2017-07-19 22:10:13 -07:00 committed by GitHub
commit 27f733736e
6 changed files with 54 additions and 20 deletions

View File

@ -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

View File

@ -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):
""" """

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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