1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-13 20:08:55 +00:00

Merge branch '2.1' into embed_shell

This commit is contained in:
Julien Duponchelle 2017-06-19 11:10:24 +02:00
commit e5bc7c7a66
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8
17 changed files with 98 additions and 15 deletions

3
.gitignore vendored
View File

@ -53,3 +53,6 @@ docs/_build
vpcs.hist
startup.vpcs
.gns3_shell_history
# Virtualenv
env

View File

@ -1,5 +1,16 @@
# Change Log
## 2.0.3 13/06/2017
* Fixes #1068 - handle zipfile encoding issues at project duplication
* Fix: #1066 - Catching parsing errors at linked vbox file
* Ignoring virtualenv directory at gitignore
* Escaping VPCS name in regex #1067
* Fix racecondition when listing interface
* Fix Qemu disk creation with unicode characters not supported by local filesystem #1058 (#1063)
* Fix when config file doesn't have computes section (#1062)
* Check aiohttp version
## 2.0.2 30/05/2017
* Set correct permission on ubridge when doing a remote installation

View File

@ -22,7 +22,7 @@ master
master is the next stable release, you can test it in your day to day activities.
Bug fixes or small improvements pull requests go here.
1.x (1.4 for example)
2.x (2.1 for example)
********
Next major release

View File

@ -247,8 +247,13 @@ class Qemu(BaseManager):
directory = self.get_images_directory()
os.makedirs(directory, exist_ok=True)
path = os.path.join(directory, os.path.basename(path))
if os.path.exists(path):
raise QemuError("Could not create disk image {} already exist".format(path))
try:
if os.path.exists(path):
raise QemuError("Could not create disk image {} already exist".format(path))
except UnicodeEncodeError:
raise QemuError("Could not create disk image {}, "
"path contains characters not supported by filesystem".format(path))
command = [qemu_img, "create", "-f", img_format]
for option in sorted(options.keys()):

View File

@ -209,7 +209,12 @@ class VirtualBoxVM(BaseNode):
Fix the VM uuid in the case of linked clone
"""
if os.path.exists(self._linked_vbox_file()):
tree = ET.parse(self._linked_vbox_file())
try:
tree = ET.parse(self._linked_vbox_file())
except ET.ParseError:
raise VirtualBoxError("Cannot modify VirtualBox linked nodes file. "
"File {} is corrupted.".format(self._linked_vbox_file()))
machine = tree.getroot().find("{http://www.virtualbox.org/}Machine")
if machine is not None and machine.get("uuid") != "{" + self.id + "}":

View File

@ -169,7 +169,8 @@ class VPCSVM(BaseNode):
if self.script_file:
content = self.startup_script
content = content.replace(self._name, new_name)
content = re.sub(r"^set pcname .+$", "set pcname " + new_name, content, flags=re.MULTILINE)
escaped_name = re.escape(new_name)
content = re.sub(r"^set pcname .+$", "set pcname " + escaped_name, content, flags=re.MULTILINE)
self.startup_script = content
super(VPCSVM, VPCSVM).name.__set__(self, new_name)

View File

@ -154,7 +154,7 @@ class Controller:
password=server_config.get("password", ""),
force=True)
except aiohttp.web_exceptions.HTTPConflict as e:
log.fatal("Can't acces to the local server, make sure anything else is not running on the same port")
log.fatal("Can't access to the local server, make sure anything else is not running on the same port")
sys.exit(1)
for c in computes:
try:
@ -249,7 +249,7 @@ class Controller:
self.gns3vm.settings = data["gns3vm"]
self.load_appliances()
return data["computes"]
return data.get("computes", [])
@asyncio.coroutine
def load_projects(self):

View File

@ -42,8 +42,8 @@ class Appliance:
# Version of the gui before 2.1 use linked_base
# and the server linked_clone
if "linked_base" in data:
self._data["linked_clone"] = data.pop("linked_base")
if "linked_base" in self._data:
self._data["linked_clone"] = self._data.pop("linked_base")
if data["node_type"] == "iou" and "image" in data:
del self._data["image"]
self._builtin = builtin

View File

@ -738,7 +738,7 @@ class Project:
f.write(data)
with open(os.path.join(tmpdir, "project.gns3p"), "rb") as f:
project = yield from import_project(self._controller, str(uuid.uuid4()), f, location=location, name=name, keep_compute_id=True)
except OSError as e:
except (OSError, UnicodeEncodeError) as e:
raise aiohttp.web.HTTPConflict(text="Can not duplicate project: {}".format(str(e)))
if previous_status == "closed":

View File

@ -57,7 +57,7 @@ class CrashReport:
Report crash to a third party service
"""
DSN = "sync+https://67b93949a78d4ef5978388cc4b8906f9:271ee1dd01db4a39b919097f452cb6c5@sentry.io/38482"
DSN = "sync+https://9b15627f2ddf4e21a9880536354bfcb5:b31dee5d3abf4c74844895432193d0ac@sentry.io/38482"
if hasattr(sys, "frozen"):
cacert = get_resource("cacert.pem")
if cacert is not None and os.path.isfile(cacert):

View File

@ -198,12 +198,13 @@ def interfaces():
results = []
if not sys.platform.startswith("win"):
for interface in sorted(psutil.net_if_addrs().keys()):
net_if_addrs = psutil.net_if_addrs()
for interface in sorted(net_if_addrs.keys()):
ip_address = ""
mac_address = ""
netmask = ""
interface_type = "ethernet"
for addr in psutil.net_if_addrs()[interface]:
for addr in net_if_addrs[interface]:
# get the first available IPv4 address only
if addr.family == socket.AF_INET:
ip_address = addr.address

View File

@ -178,6 +178,26 @@ def test_create_image_exist(loop, tmpdir, fake_qemu_img_binary):
assert not process.called
def test_create_image_with_not_supported_characters_by_filesystem(loop, tmpdir, fake_qemu_img_binary):
open(str(tmpdir / "hda.qcow2"), "w+").close()
options = {
"format": "raw",
"size": 100
}
# patching os.makedirs is necessary as it depends on already mocked os.path.exists
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process, \
patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)), \
patch("os.path.exists", side_effect=UnicodeEncodeError('error', u"", 1, 2, 'Emulated Unicode Err')),\
patch("os.makedirs"):
with pytest.raises(QemuError):
loop.run_until_complete(asyncio.async(Qemu.instance().create_disk(
fake_qemu_img_binary, "hda.qcow2", options)))
assert not process.called
def test_get_kvm_archs_kvm_ok(loop):
with patch("os.path.exists", return_value=True):
@ -185,7 +205,7 @@ def test_get_kvm_archs_kvm_ok(loop):
if platform.machine() == 'x86_64':
assert archs == ['x86_64', 'i386']
else:
assert archs == [ platform.machine() ]
assert archs == [platform.machine()]
with patch("os.path.exists", return_value=False):
archs = loop.run_until_complete(asyncio.async(Qemu.get_kvm_archs()))

View File

@ -113,3 +113,15 @@ def test_patch_vm_uuid(vm):
with open(vm._linked_vbox_file()) as f:
c = f.read()
assert "{" + vm.id + "}" in c
def test_patch_vm_uuid_with_corrupted_file(vm):
xml = """<?xml version="1.0"?>
<VirtualBox>
"""
os.makedirs(os.path.join(vm.working_dir, vm._vmname), exist_ok=True)
with open(vm._linked_vbox_file(), "w+") as f:
f.write(xml)
vm._linked_clone = True
with pytest.raises(VirtualBoxError):
vm._patch_vm_uuid()

View File

@ -251,6 +251,12 @@ def test_update_startup_script_h(vm):
assert f.read() == "set pcname pc1\n"
def test_update_startup_script_with_escaping_characters_in_name(vm):
vm.startup_script = "set pcname initial-name\n"
vm.name = "test\\"
assert vm.startup_script == "set pcname test\\\n"
def test_get_startup_script(vm):
content = "echo GNS3 VPCS\nip 192.168.1.2"
vm.startup_script = content

View File

@ -62,6 +62,16 @@ def test_load_controller_settings(controller, controller_config_path, async_run)
assert controller.gns3vm.settings["vmname"] == "Test VM"
def test_load_controller_settings_with_no_computes_section(controller, controller_config_path, async_run):
controller.save()
with open(controller_config_path) as f:
data = json.load(f)
del data['computes']
with open(controller_config_path, "w+") as f:
json.dump(data, f)
assert len(async_run(controller._load_controller_settings())) == 0
def test_import_computes_1_x(controller, controller_config_path, async_run):
"""
At first start the server should import the

View File

@ -20,6 +20,7 @@ import os
import sys
import pytest
import aiohttp
import zipstream
from unittest.mock import MagicMock
from tests.utils import AsyncioMagicMock, asyncio_patch
from unittest.mock import patch
@ -473,6 +474,15 @@ def test_duplicate(project, async_run, controller):
assert list(new_project.nodes.values())[1].compute.id == "remote"
def test_duplicate_with_zipfile_encoding_issues(project, async_run, controller):
zf = zipstream.ZipFile()
zf.writestr('test\udcc3', "data")
with asyncio_patch('gns3server.controller.project.export_project', return_value=zf):
with pytest.raises(aiohttp.web.HTTPConflict):
async_run(project.duplicate(name="Hello"))
def test_snapshots(project):
"""
List the snapshots

View File

@ -46,4 +46,3 @@ def test_put_gns3vm(http_controller):
def test_get_gns3vm(http_controller):
response = http_controller.get('/gns3vm', example=True)
assert response.status == 200
print(response.json)