Method for reloading a topology (not bind to an api handler)

Ref https://github.com/GNS3/gns3-gui/issues/1243
pull/638/head
Julien Duponchelle 8 years ago
parent 3aea16c527
commit 742243e9df
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8

@ -26,6 +26,7 @@ from .project import Project
from .compute import Compute from .compute import Compute
from .notification import Notification from .notification import Notification
from ..version import __version__ from ..version import __version__
from .topology import load_topology
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -185,6 +186,29 @@ class Controller:
def remove_project(self, project): def remove_project(self, project):
del self._projects[project.id] del self._projects[project.id]
@asyncio.coroutine
def load_project(self, path):
"""
Load a project from a .gns3
:param path: Path of the .gns3
"""
topo_data = load_topology(path)
topology = topo_data.pop("topology")
topo_data.pop("version")
topo_data.pop("revision")
topo_data.pop("type")
project = yield from self.add_project(path=os.path.dirname(path), **topo_data)
for compute in topology["computes"]:
yield from self.add_compute(**compute)
for node in topology["nodes"]:
compute = self.get_compute(node.pop("compute_id"))
name = node.pop("name")
node_id = node.pop("node_id")
yield from project.add_node(compute, name, node_id, **node)
@property @property
def projects(self): def projects(self):
""" """

@ -15,8 +15,12 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
import aiohttp
from ..version import __version__ from ..version import __version__
GNS3_FILE_FORMAT_REVISION = 5
def project_to_topology(project): def project_to_topology(project):
""" """
@ -31,7 +35,7 @@ def project_to_topology(project):
"computes": [] "computes": []
}, },
"type": "topology", "type": "topology",
"revision": 5, "revision": GNS3_FILE_FORMAT_REVISION,
"version": __version__ "version": __version__
} }
@ -44,6 +48,20 @@ def project_to_topology(project):
for compute in computes: for compute in computes:
if hasattr(compute, "__json__"): if hasattr(compute, "__json__"):
data["topology"]["computes"].append(compute.__json__()) data["topology"]["computes"].append(compute.__json__())
print(data)
#TODO: check JSON schema #TODO: check JSON schema
return data return data
def load_topology(path):
"""
Open a topology file, patch it for last GNS3 release and return it
"""
try:
with open(path) as f:
topo = json.load(f)
except OSError as e:
raise aiohttp.web.HTTPConflict(text="Could not load topology {}: {}".format(path, str(e)))
#TODO: Check JSON schema
if topo["revision"] < GNS3_FILE_FORMAT_REVISION:
raise aiohttp.web.HTTPConflict(text="Old GNS3 project are not yet supported")
return topo

@ -21,7 +21,7 @@ import json
import pytest import pytest
import aiohttp import aiohttp
from unittest.mock import MagicMock from unittest.mock import MagicMock
from tests.utils import AsyncioMagicMock
from gns3server.controller import Controller from gns3server.controller import Controller
from gns3server.controller.compute import Compute from gns3server.controller.compute import Compute
@ -184,3 +184,71 @@ def test_close(controller, async_run):
c._connected = True c._connected = True
async_run(controller.close()) async_run(controller.close())
assert c.connected is False assert c.connected is False
def test_load_project(controller, async_run, tmpdir):
data = {
"name": "Test",
"project_id": "c8d07a5a-134f-4c3f-8599-e35eac85eb17",
"revision": 5,
"type": "topology",
"version": "2.0.0dev1",
"topology": {
"computes": [
{
"compute_id": "my_remote",
"host": "127.0.0.1",
"name": "My remote",
"port": 3080,
"protocol": "http",
}
],
"links": [
{
"capturing": True,
"link_id": "c44331d2-2da4-490d-9aad-7f5c126ae271",
"nodes": [
{"node_id": "c067b922-7f77-4680-ac00-0226c6583598", "adapter_number": 0, "port_number": 0},
{"node_id": "50d66d7b-0dd7-4e9f-b720-6eb621ae6543", "adapter_number": 0, "port_number": 0},
],
}
],
"nodes": [
{
"compute_id": "my_remote",
"name": "PC2",
"node_id": "c067b922-7f77-4680-ac00-0226c6583598",
"node_type": "vpcs",
"properties": {
"startup_script": "set pcname PC2\n",
"startup_script_path": "startup.vpc"
},
},
{
"compute_id": "my_remote",
"name": "PC1",
"node_id": "50d66d7b-0dd7-4e9f-b720-6eb621ae6543",
"node_type": "vpcs",
"properties": {
"startup_script": "set pcname PC1\n",
"startup_script_path": "startup.vpc"
},
}
]
}
}
with open(str(tmpdir / "test.gns3"), "w+") as f:
json.dump(data, f)
controller.add_compute = AsyncioMagicMock()
mock_project = MagicMock()
controller.add_project = AsyncioMagicMock(return_value=mock_project)
controller._computes["my_remote"] = MagicMock()
async_run(controller.load_project(str(tmpdir / "test.gns3")))
controller.add_compute.assert_called_with(compute_id='my_remote', host='127.0.0.1', name='My remote', port=3080, protocol='http')
controller.add_project.assert_called_with(name='Test', project_id='c8d07a5a-134f-4c3f-8599-e35eac85eb17', path=str(tmpdir))
mock_project.add_node.assert_any_call(controller._computes["my_remote"], 'PC1', '50d66d7b-0dd7-4e9f-b720-6eb621ae6543', node_type='vpcs', properties={'startup_script': 'set pcname PC1\n', 'startup_script_path': 'startup.vpc'})
mock_project.add_node.assert_any_call(controller._computes["my_remote"], 'PC2', 'c067b922-7f77-4680-ac00-0226c6583598', node_type='vpcs', properties={'startup_script': 'set pcname PC2\n', 'startup_script_path': 'startup.vpc'})

@ -15,12 +15,15 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
import pytest
import aiohttp
from unittest.mock import MagicMock from unittest.mock import MagicMock
from tests.utils import asyncio_patch from tests.utils import asyncio_patch
from gns3server.controller.project import Project from gns3server.controller.project import Project
from gns3server.controller.compute import Compute from gns3server.controller.compute import Compute
from gns3server.controller.topology import project_to_topology from gns3server.controller.topology import project_to_topology, load_topology
from gns3server.version import __version__ from gns3server.version import __version__
@ -60,3 +63,45 @@ def test_basic_topology(tmpdir, async_run, controller):
assert topo["topology"]["links"][0] == link.__json__() assert topo["topology"]["links"][0] == link.__json__()
assert topo["topology"]["computes"][0] == compute.__json__() assert topo["topology"]["computes"][0] == compute.__json__()
def test_load_topology(tmpdir):
data = {
"project_id": "69f26504-7aa3-48aa-9f29-798d44841211",
"name": "Test",
"revision": 5,
"topology": {
"nodes": [],
"links": [],
"computes": []
},
"type": "topology",
"version": __version__}
path = str(tmpdir / "test.gns3")
with open(path, "w+") as f:
json.dump(data, f)
topo = load_topology(path)
assert topo == data
def test_load_topology_file_error(tmpdir):
path = str(tmpdir / "test.gns3")
with pytest.raises(aiohttp.web.HTTPConflict):
topo = load_topology(path)
def test_load_old_topology(tmpdir):
data = {
"project_id": "69f26504-7aa3-48aa-9f29-798d44841211",
"name": "Test",
"revision": 4,
"topology": {
},
"type": "topology",
"version": __version__}
path = str(tmpdir / "test.gns3")
with open(path, "w+") as f:
json.dump(data, f)
with pytest.raises(aiohttp.web.HTTPConflict):
topo = load_topology(path)

Loading…
Cancel
Save