mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 17:28:08 +00:00
Merge branch '2.1' into embed_shell
This commit is contained in:
commit
e5bc7c7a66
3
.gitignore
vendored
3
.gitignore
vendored
@ -53,3 +53,6 @@ docs/_build
|
||||
vpcs.hist
|
||||
startup.vpcs
|
||||
.gns3_shell_history
|
||||
|
||||
# Virtualenv
|
||||
env
|
11
CHANGELOG
11
CHANGELOG
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()):
|
||||
|
@ -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 + "}":
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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":
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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()))
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user