async def test_add_node_from_template(controller): """ For a local server we send the project path """ compute = MagicMock() compute.id = "local" project = Project(controller=controller, name="Test") project.emit_notification = MagicMock() template = Template( str(uuid.uuid4()), { "compute_id": "local", "name": "Test", "template_type": "vpcs", "builtin": False, }) controller.template_manager.templates[template.id] = template controller._computes["local"] = compute response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = await project.add_node_from_template(template.id, x=23, y=12) compute.post.assert_any_call('/projects', data={ "name": project._name, "project_id": project._id, "path": project._path }) assert compute in project._project_created_on_compute project.emit_notification.assert_any_call("node.created", node.__json__())
def test_add_node_local(async_run, controller): """ For a local server we send the project path """ compute = MagicMock() compute.id = "local" project = Project(controller=controller, name="Test") controller._notification = MagicMock() response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) assert node.id in project._nodes compute.post.assert_any_call('/projects', data={ "name": project._name, "project_id": project._id, "path": project._path }) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={'node_id': node.id, 'startup_config': 'test.cfg', 'name': 'test'}, timeout=120) assert compute in project._project_created_on_compute controller.notification.emit.assert_any_call("node.created", node.__json__())
def test_delete_node(async_run, controller): """ For a local server we send the project path """ compute = MagicMock() project = Project(controller=controller, name="Test") project.emit_notification = MagicMock() response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = async_run( project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) assert node.id in project._nodes async_run(project.delete_node(node.id)) assert node.id not in project._nodes compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format( project.id, node.id)) project.emit_notification.assert_any_call("node.deleted", node.__json__())
def test_add_node_non_local(async_run, controller): """ For a non local server we do not send the project path """ compute = MagicMock() compute.id = "remote" project = Project(controller=controller, name="Test") controller._notification = MagicMock() response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"})) compute.post.assert_any_call('/projects', data={ "name": project._name, "project_id": project._id }) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={'node_id': node.id, 'startup_script': 'test.cfg', 'name': 'test'}, timeout=1200) assert compute in project._project_created_on_compute controller.notification.emit.assert_any_call("node.created", node.__json__())
def test_open_auto_start(async_run, controller): project = Project(controller=controller, name="Test", auto_start=True) assert project.status == "opened" async_run(project.close()) project.start_all = AsyncioMagicMock() async_run(project.open()) assert project.start_all.called
async def test_affect_uuid(): p = Project(name="Test") assert len(p.id) == 36 p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test 2") assert p.id == '00010203-0405-0607-0809-0a0b0c0d0e0f'
async def test_add_node_non_local(controller): """ For a non local server we do not send the project path """ compute = MagicMock() compute.id = "remote" project = Project(controller=controller, name="Test") project.emit_notification = MagicMock() response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"}) compute.post.assert_any_call('/projects', data={ "name": project._name, "project_id": project._id }) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={ 'node_id': node.id, 'startup_script': 'test.cfg', 'name': 'test' }, timeout=1200) assert compute in project._project_created_on_compute project.emit_notification.assert_any_call("node.created", node.__json__())
async def test_delete_node_delete_link(controller): """ Delete a node delete all the node connected """ compute = MagicMock() project = Project(controller=controller, name="Test") project.emit_notification = MagicMock() response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}) link = await project.add_link() await link.add_node(node, 0, 0) await project.delete_node(node.id) assert node.id not in project._nodes assert link.id not in project._links compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format( project.id, node.id)) project.emit_notification.assert_any_call("node.deleted", node.__json__()) project.emit_notification.assert_any_call("link.deleted", link.__json__())
def test_open(controller, tmpdir, demo_topology, async_run, http_server): simple_topology = { "auto_close": True, "auto_open": False, "auto_start": False, "scene_height": 500, "scene_width": 700, "name": "demo", "project_id": "3c1be6f9-b4ba-4737-b209-63c47c23359f", "revision": 5, "topology": { "computes": [], "drawings": [], "links": [], "nodes": [] }, "type": "topology", "version": "2.0.0" } with open(str(tmpdir / "demo.gns3"), "w+") as f: json.dump(simple_topology, f) project = Project( name="demo", project_id="64ba8408-afbf-4b66-9cdd-1fd854427478", path=str(tmpdir), controller=controller, filename="demo.gns3", status="closed") async_run(project.open()) assert project.status == "opened" assert project.name == "demo" assert project.scene_height == 500 assert project.scene_width == 700
async def test_json(): p = Project(name="Test") assert p.__json__() == { "name": "Test", "project_id": p.id, "path": p.path, "status": "opened", "filename": "Test.gns3", "auto_start": False, "auto_close": True, "auto_open": False, "scene_width": 2000, "scene_height": 1000, "zoom": 100, "show_grid": False, "show_interface_labels": False, "show_layers": False, "snap_to_grid": False, "grid_size": 75, "drawing_grid_size": 25, "supplier": None, "variables": None }
def test_update(controller, async_run): project = Project(controller=controller, name="Hello") project.emit_notification = MagicMock() assert project.name == "Hello" async_run(project.update(name="World")) assert project.name == "World" project.emit_notification.assert_any_call("project.updated", project.__json__())
def test_compute_httpQuery_project(compute, async_run): response = MagicMock() with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock: response.status = 200 project = Project(name="Test") async_run(compute.post("/projects", project)) mock.assert_called_with("POST", "https://example.com:84/v2/compute/projects", data=json.dumps(project.__json__()), headers={'content-type': 'application/json'}, auth=None, chunked=None, timeout=20)
def test_update(controller, async_run): project = Project(controller=controller, name="Hello") controller._notification = MagicMock() assert project.name == "Hello" async_run(project.update(name="World")) assert project.name == "World" controller.notification.emit.assert_any_call("project.updated", project.__json__())
def test_dump(): directory = Config.instance().get_section_config("Server").get("projects_path") with patch("gns3server.utils.path.get_default_project_directory", return_value=directory): p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test") p.dump() with open(os.path.join(directory, p.id, "Test.gns3")) as f: content = f.read() assert "00010203-0405-0607-0809-0a0b0c0d0e0f" in content
def test_dump(): directory = Config.instance().get_section_config("Server").get("projects_path") with patch("gns3server.utils.path.get_default_project_directory", return_value=directory): p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test") p.dump() with open(os.path.join(directory, p.id, "Test.gns3")) as f: content = f.read() assert "00010203-0405-0607-0809-0a0b0c0d0e0f" in content
def test_open_close(async_run, controller): project = Project(controller=controller, status="closed", name="Test") assert project.status == "closed" project.start_all = AsyncioMagicMock() async_run(project.open()) assert not project.start_all.called assert project.status == "opened" controller._notification = MagicMock() async_run(project.close()) assert project.status == "closed" controller.notification.emit.assert_any_call("project.closed", project.__json__())
async def test_dump(projects_dir): directory = projects_dir with patch("gns3server.utils.path.get_default_project_directory", return_value=directory): p = Project(project_id='00010203-0405-0607-0809-0a0b0c0d0e0f', name="Test") p.dump() with open(os.path.join(directory, p.id, "Test.gns3")) as f: content = f.read() assert "00010203-0405-0607-0809-0a0b0c0d0e0f" in content
async def test_update_on_compute(controller): variables = [{"name": "TEST", "value": "VAL1"}] compute = MagicMock() compute.id = "local" project = Project(controller=controller, name="Test") project._project_created_on_compute = [compute] project.emit_notification = MagicMock() await project.update(variables=variables) compute.put.assert_any_call('/projects/{}'.format(project.id), {"variables": variables})
def test_project_to_topology(tmpdir, controller): variables = [{"name": "TEST1"}, {"name": "TEST2", "value": "value1"}] supplier = {'logo': 'logo.png', 'url': 'http://example.com'} project = Project(name="Test", controller=controller) compute = Compute("my_compute", controller) compute.http_query = MagicMock() project.variables = variables project.supplier = supplier topo = project_to_topology(project) assert topo["variables"] == variables assert topo["supplier"] == supplier
def test_add_node_from_appliance(async_run, controller): """ For a local server we send the project path """ compute = MagicMock() compute.id = "local" project = Project(controller=controller, name="Test") controller._notification = MagicMock() controller._appliances["fakeid"] = Appliance( "fakeid", { "server": "local", "name": "Test", "default_name_format": "{name}-{0}", "node_type": "vpcs", "properties": { "a": 1 } }) controller._computes["local"] = compute response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = async_run(project.add_node_from_appliance("fakeid", x=23, y=12)) compute.post.assert_any_call('/projects', data={ "name": project._name, "project_id": project._id, "path": project._path }) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={ 'node_id': node.id, 'name': 'Test-1', 'a': 1, }, timeout=1200) assert compute in project._project_created_on_compute controller.notification.emit.assert_any_call("node.created", node.__json__()) # Make sure we can call twice the node creation node = async_run(project.add_node_from_appliance("fakeid", x=13, y=12)) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={ 'node_id': node.id, 'name': 'Test-2', 'a': 1 }, timeout=1200)
def test_json(tmpdir): p = Project(name="Test") assert p.__json__() == { "name": "Test", "project_id": p.id, "path": p.path, "status": "opened", "filename": "Test.gns3", "auto_start": False, "auto_close": True, "auto_open": False, "scene_width": 2000, "scene_height": 1000 }
async def test_open_close(controller): project = Project(controller=controller, name="Test") assert project.status == "opened" await project.close() project.start_all = AsyncioMagicMock() await project.open() assert not project.start_all.called assert project.status == "opened" project.emit_notification = MagicMock() await project.close() assert project.status == "closed" project.emit_notification.assert_any_call("project.closed", project.__json__())
def test_add_node_from_appliance(async_run, controller): """ For a local server we send the project path """ compute = MagicMock() compute.id = "local" project = Project(controller=controller, name="Test") controller._notification = MagicMock() controller._appliances["fakeid"] = Appliance("fakeid", { "server": "local", "name": "Test", "default_name_format": "{name}-{0}", "node_type": "vpcs", "properties": { "a": 1 } }) controller._computes["local"] = compute response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = async_run(project.add_node_from_appliance("fakeid", x=23, y=12)) compute.post.assert_any_call('/projects', data={ "name": project._name, "project_id": project._id, "path": project._path }) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={'node_id': node.id, 'name': 'Test-1', 'a': 1, }, timeout=1200) assert compute in project._project_created_on_compute controller.notification.emit.assert_any_call("node.created", node.__json__()) # Make sure we can call twice the node creation node = async_run(project.add_node_from_appliance("fakeid", x=13, y=12)) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={'node_id': node.id, 'name': 'Test-2', 'a': 1 }, timeout=1200)
async def test_basic_topology(controller): project = Project(name="Test", controller=controller) compute = Compute("my_compute", controller) compute.http_query = MagicMock() with asyncio_patch("gns3server.controller.node.Node.create"): node1 = await project.add_node(compute, "Node 1", str(uuid.uuid4()), node_type="qemu") node2 = await project.add_node(compute, "Node 2", str(uuid.uuid4()), node_type="qemu") link = await project.add_link() await link.add_node(node1, 0, 0) with asyncio_patch("gns3server.controller.udp_link.UDPLink.create"): await link.add_node(node2, 0, 0) drawing = await project.add_drawing(svg="<svg></svg>") topo = project_to_topology(project) assert len(topo["topology"]["nodes"]) == 2 assert node1.__json__(topology_dump=True) in topo["topology"]["nodes"] assert topo["topology"]["links"][0] == link.__json__(topology_dump=True) assert topo["topology"]["computes"][0] == compute.__json__( topology_dump=True) assert topo["topology"]["drawings"][0] == drawing.__json__( topology_dump=True)
def test_project_to_topology_empty(tmpdir): project = Project(name="Test") topo = project_to_topology(project) assert topo == { "project_id": project.id, "name": "Test", "auto_start": False, "auto_close": True, "auto_open": False, "scene_width": 2000, "scene_height": 1000, "revision": GNS3_FILE_FORMAT_REVISION, "zoom": 100, "show_grid": False, "show_interface_labels": False, "show_layers": False, "snap_to_grid": False, "grid_size": 75, "drawing_grid_size": 25, "topology": { "nodes": [], "links": [], "computes": [], "drawings": [] }, "type": "topology", "supplier": None, "variables": None, "version": __version__ }
def test_path_exist(tmpdir): """ Should raise an error when you try to owerwrite an existing project """ os.makedirs(str(tmpdir / "demo")) with pytest.raises(aiohttp.web.HTTPForbidden): p = Project(name="Test", path=str(tmpdir / "demo"))
def test_path(tmpdir): directory = Config.instance().get_section_config("Server").get("projects_path") with patch("gns3server.utils.path.get_default_project_directory", return_value=directory): p = Project(project_id=str(uuid4()), name="Test") assert p.path == os.path.join(directory, p.id) assert os.path.exists(os.path.join(directory, p.id))
async def test_path(projects_dir): directory = projects_dir with patch("gns3server.utils.path.get_default_project_directory", return_value=directory): p = Project(project_id=str(uuid4()), name="Test") assert p.path == os.path.join(directory, p.id) assert os.path.exists(os.path.join(directory, p.id))
def test_upload_missing_image(compute, controller, async_run, images_dir): project = Project(str(uuid.uuid4()), controller=controller) node = Node(project, compute, "demo", node_id=str(uuid.uuid4()), node_type="qemu", properties={"hda_disk_image": "linux.img"}) open(os.path.join(images_dir, "linux.img"), 'w+').close() assert async_run(node._upload_missing_image("qemu", "linux.img")) is True compute.post.assert_called_with("/qemu/images/linux.img", data=ANY, timeout=None)
def test_project_to_topology(tmpdir, controller): variables = [ {"name": "TEST1"}, {"name": "TEST2", "value": "value1"} ] supplier = { 'logo': 'logo.png', 'url': 'http://example.com' } project = Project(name="Test", controller=controller) compute = Compute("my_compute", controller) compute.http_query = MagicMock() project.variables = variables project.supplier = supplier topo = project_to_topology(project) assert topo["variables"] == variables assert topo["supplier"] == supplier
def test_json(tmpdir): p = Project(name="Test") assert p.__json__() == { "name": "Test", "project_id": p.id, "path": p.path, "status": "opened", "filename": "Test.gns3", "auto_start": False, "auto_close": True, "auto_open": False, "scene_width": 2000, "scene_height": 1000, "zoom": 100, "show_grid": False, "show_interface_labels": False, "show_layers": False, "snap_to_grid": False }
def test_json(tmpdir): p = Project(name="Test") assert p.__json__() == { "name": "Test", "project_id": p.id, "path": p.path, "status": "opened", "filename": "Test.gns3", "auto_start": False, "auto_close": True, "auto_open": False, "scene_width": 2000, "scene_height": 1000, "zoom": 100, "show_grid": False, "show_interface_labels": False, "show_layers": False, "snap_to_grid": False }
def test_delete_node(async_run, controller): """ For a local server we send the project path """ compute = MagicMock() project = Project(controller=controller, name="Test") controller._notification = MagicMock() response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) assert node.id in project._nodes async_run(project.delete_node(node.id)) assert node.id not in project._nodes compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format(project.id, node.id)) controller.notification.emit.assert_any_call("node.deleted", node.__json__())
def test_create_iou_on_multiple_node(async_run, controller): """ Due to mac address collision you can't create an IOU node on two different server """ compute = MagicMock() compute.id = "remote" compute2 = MagicMock() compute2.id = "remote2" project = Project(controller=controller, name="Test") response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node1 = async_run(project.add_node(compute, "test", None, node_type="iou")) with pytest.raises(aiohttp.web_exceptions.HTTPConflict): async_run(project.add_node(compute2, "test2", None, node_type="iou"))
def test_list_nodes(async_run, controller): compute = MagicMock() project = Project(controller=controller, name="Test") response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) vm = async_run( project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) assert len(project.nodes) == 1 assert isinstance(project.nodes, dict) async_run(project.close()) assert len(project.nodes) == 1 assert isinstance(project.nodes, dict)
def test_get_node(async_run, controller): compute = MagicMock() project = Project(controller=controller, name="Test") response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) vm = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) assert project.get_node(vm.id) == vm with pytest.raises(aiohttp.web_exceptions.HTTPNotFound): project.get_node("test") # Raise an error if the project is not opened async_run(project.close()) with pytest.raises(aiohttp.web.HTTPForbidden): project.get_node(vm.id)
def test_basic_topology(tmpdir, async_run, controller): project = Project(name="Test", controller=controller) compute = Compute("my_compute", controller) compute.http_query = MagicMock() with asyncio_patch("gns3server.controller.node.Node.create"): node1 = async_run(project.add_node(compute, "Node 1", str(uuid.uuid4()), node_type="qemu")) node2 = async_run(project.add_node(compute, "Node 2", str(uuid.uuid4()), node_type="qemu")) link = async_run(project.add_link()) async_run(link.add_node(node1, 0, 0)) with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock_udp_create: async_run(link.add_node(node2, 0, 0)) drawing = async_run(project.add_drawing(svg="<svg></svg>")) topo = project_to_topology(project) assert len(topo["topology"]["nodes"]) == 2 assert node1.__json__(topology_dump=True) in topo["topology"]["nodes"] assert topo["topology"]["links"][0] == link.__json__(topology_dump=True) assert topo["topology"]["computes"][0] == compute.__json__(topology_dump=True) assert topo["topology"]["drawings"][0] == drawing.__json__(topology_dump=True)
async def test_delete_locked_node(controller): """ For a local server we send the project path """ compute = MagicMock() project = Project(controller=controller, name="Test") project.emit_notification = MagicMock() response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = await project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}) assert node.id in project._nodes node.locked = True with pytest.raises(aiohttp.web_exceptions.HTTPConflict): await project.delete_node(node.id)
def test_eq(compute, project, node, controller): assert node == Node(project, compute, "demo1", node_id=node.id, node_type="qemu") assert node != "a" assert node != Node( project, compute, "demo2", node_id=str(uuid.uuid4()), node_type="qemu") assert node != Node(Project(str(uuid.uuid4()), controller=controller), compute, "demo3", node_id=node.id, node_type="qemu")
def test_open(controller, tmpdir, demo_topology, async_run, http_server): simple_topology = { "auto_close": True, "auto_open": False, "auto_start": False, "scene_height": 500, "scene_width": 700, "name": "demo", "project_id": "3c1be6f9-b4ba-4737-b209-63c47c23359f", "revision": 5, "topology": { "computes": [], "drawings": [], "links": [], "nodes": [] }, "type": "topology", "version": "2.0.0" } with open(str(tmpdir / "demo.gns3"), "w+") as f: json.dump(simple_topology, f) project = Project(name="demo", project_id="64ba8408-afbf-4b66-9cdd-1fd854427478", path=str(tmpdir), controller=controller, filename="demo.gns3", status="closed") async_run(project.open()) assert project.status == "opened" assert project.name == "demo" assert project.scene_height == 500 assert project.scene_width == 700
def test_delete_node_delete_link(async_run, controller): """ Delete a node delete all the node connected """ compute = MagicMock() project = Project(controller=controller, name="Test") controller._notification = MagicMock() response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) link = async_run(project.add_link()) async_run(link.add_node(node, 0, 0)) async_run(project.delete_node(node.id)) assert node.id not in project._nodes assert link.id not in project._links compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format(project.id, node.id)) controller.notification.emit.assert_any_call("node.deleted", node.__json__()) controller.notification.emit.assert_any_call("link.deleted", link.__json__())
def test_get_node(async_run, controller): compute = MagicMock() project = Project(controller=controller, name="Test") response = MagicMock() response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) vm = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) assert project.get_node(vm.id) == vm with pytest.raises(aiohttp.web_exceptions.HTTPNotFound): project.get_node("test") # Raise an error if the project is not opened async_run(project.close()) with pytest.raises(aiohttp.web.HTTPForbidden): project.get_node(vm.id)
def project(controller): p = Project(controller=controller, name="Test") p.dump = MagicMock() return p
def test_changing_path_with_quote_not_allowed(tmpdir): with pytest.raises(aiohttp.web.HTTPForbidden): p = Project(project_id=str(uuid4()), name="Test") p.path = str(tmpdir / "project\"53")
def test_open_auto_start(async_run, controller): project = Project(controller=controller, status="closed", name="Test", auto_start=True) project.start_all = AsyncioMagicMock() async_run(project.open()) assert project.start_all.called