1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-15 12:59:06 +00:00

Support update link on controller

Ref https://github.com/GNS3/gns3-gui/issues/1300
This commit is contained in:
Julien Duponchelle 2016-07-01 17:38:32 +02:00
parent 71d4c0a13a
commit fea1e3ba61
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8
5 changed files with 179 additions and 12 deletions

View File

@ -43,18 +43,38 @@ class Link:
self._streaming_pcap = None
@asyncio.coroutine
def add_node(self, node, adapter_number, port_number):
def add_node(self, node, adapter_number, port_number, label=None):
"""
Add a node to the link
"""
if label is None:
label = {
"x": -10,
"y": -10,
"text": "{}/{}".format(adapter_number, port_number),
"style": "font-size: 10; font-style: Verdana"
}
self._nodes.append({
"node": node,
"adapter_number": adapter_number,
"port_number": port_number
"port_number": port_number,
"label": label
})
if len(self._nodes) == 2:
self._project.controller.notification.emit("link.created", self.__json__())
self._project.dump()
@asyncio.coroutine
def update_node(self, node, adapter_number, port_number, label=None):
for port in self._nodes:
if port["node"] == node:
if label:
port["label"] = label
self._project.controller.notification.emit("link.updated", self.__json__())
self._project.dump()
@asyncio.coroutine
@ -166,7 +186,8 @@ class Link:
res.append({
"node_id": side["node"].id,
"adapter_number": side["adapter_number"],
"port_number": side["port_number"]
"port_number": side["port_number"],
"label": side["label"]
})
if topology_dump:
return {

View File

@ -66,11 +66,38 @@ class LinkHandler:
for node in request.json["nodes"]:
yield from link.add_node(project.get_node(node["node_id"]),
node.get("adapter_number", 0),
node.get("port_number", 0))
node.get("port_number", 0),
label=node.get("label"))
yield from link.create()
response.set_status(201)
response.json(link)
@Route.put(
r"/projects/{project_id}/links/{link_id}",
parameters={
"project_id": "Project UUID",
"link_id": "Link UUID"
},
status_codes={
201: "Link updated",
400: "Invalid request"
},
description="Update a link instance",
input=LINK_OBJECT_SCHEMA,
output=LINK_OBJECT_SCHEMA)
def update(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
link = project.get_link(request.match_info["link_id"])
for node in request.json["nodes"]:
yield from link.update_node(project.get_node(node["node_id"]),
node.get("adapter_number", 0),
node.get("port_number", 0),
label=node.get("label"))
response.set_status(201)
response.json(link)
@Route.post(
r"/projects/{project_id}/links/{link_id}/start_capture",
parameters={

View File

@ -15,6 +15,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .label import LABEL_OBJECT_SCHEMA
LINK_OBJECT_SCHEMA = {
"$schema": "http://json-schema.org/draft-04/schema#",
@ -55,7 +57,8 @@ LINK_OBJECT_SCHEMA = {
"port_number": {
"description": "Port number",
"type": "integer"
}
},
"label": LABEL_OBJECT_SCHEMA
},
"required": ["node_id", "adapter_number", "port_number"],
"additionalProperties": False

View File

@ -50,20 +50,53 @@ def link(async_run, project, compute):
return link
def test_addNode(async_run, project, compute):
def test_add_node(async_run, project, compute):
node1 = Node(project, compute, "node1")
link = Link(project)
link._project.controller.notification.emit = MagicMock()
project.dump = AsyncioMagicMock()
async_run(link.add_node(node1, 0, 4))
assert link._nodes == [
{
"node": node1,
"adapter_number": 0,
"port_number": 4
"port_number": 4,
'label': {
'y': -10,
'text': '0/4',
'x': -10,
'style': 'font-size: 10; font-style: Verdana'
}
}
]
assert project.dump.called
assert not link._project.controller.notification.emit.called
# We call link.created only when both side are created
node2 = Node(project, compute, "node2")
async_run(link.add_node(node2, 0, 4))
link._project.controller.notification.emit.assert_called_with("link.created", link.__json__())
def test_update_node(async_run, project, compute):
node1 = Node(project, compute, "node1")
link = Link(project)
async_run(link.add_node(node1, 0, 4))
label = {
'y': -42,
'text': '0/4',
'x': -10,
'style': 'font-size: 10; font-style: Verdana'
}
project.dump = AsyncioMagicMock()
link._project.controller.notification.emit = MagicMock()
async_run(link.update_node(node1, 0, 4, label=label))
assert link._nodes[0]["label"]["y"] == -42
assert project.dump.called
link._project.controller.notification.emit.assert_called_with("link.updated", link.__json__())
def test_json(async_run, project, compute):
@ -80,12 +113,24 @@ def test_json(async_run, project, compute):
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 4
"port_number": 4,
'label': {
'y': -10,
'text': '0/4',
'x': -10,
'style': 'font-size: 10; font-style: Verdana'
}
},
{
"node_id": node2.id,
"adapter_number": 1,
"port_number": 3
"port_number": 3,
'label': {
'y': -10,
'text': '1/3',
'x': -10,
'style': 'font-size: 10; font-style: Verdana'
}
}
],
"capturing": False,
@ -98,12 +143,24 @@ def test_json(async_run, project, compute):
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 4
"port_number": 4,
'label': {
'y': -10,
'text': '0/4',
'x': -10,
'style': 'font-size: 10; font-style: Verdana'
}
},
{
"node_id": node2.id,
"adapter_number": 1,
"port_number": 3
"port_number": 3,
'label': {
'y': -10,
'text': '1/3',
'x': -10,
'style': 'font-size: 10; font-style: Verdana'
}
}
]
}

View File

@ -62,7 +62,12 @@ def test_create_link(http_controller, tmpdir, project, compute, async_run):
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3
"port_number": 3,
"label": {
"text": "Text",
"x": 42,
"y": 0
}
},
{
"node_id": node2.id,
@ -75,6 +80,60 @@ def test_create_link(http_controller, tmpdir, project, compute, async_run):
assert response.status == 201
assert response.json["link_id"] is not None
assert len(response.json["nodes"]) == 2
assert response.json["nodes"][0]["label"]["x"] == 42
def test_update_link(http_controller, tmpdir, project, compute, async_run):
response = MagicMock()
response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response)
node1 = async_run(project.add_node(compute, "node1", None))
node2 = async_run(project.add_node(compute, "node2", None))
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = http_controller.post("/projects/{}/links".format(project.id), {
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Text",
"x": 42,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
]
})
link_id = response.json["link_id"]
assert response.json["nodes"][0]["label"]["x"] == 42
response = http_controller.put("/projects/{}/links/{}".format(project.id, link_id), {
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Hello",
"x": 64,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
]
})
assert response.status == 201
assert response.json["nodes"][0]["label"]["x"] == 64
def test_list_link(http_controller, tmpdir, project, compute, async_run):