mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-12 09:55:54 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26fc8236c9 | ||
|
|
4216c5d2ed | ||
|
|
afa4ba9b55 | ||
|
|
7980ae9ab1 | ||
|
|
3495035dbf | ||
|
|
a2d4c2427d | ||
|
|
0dae4b6930 | ||
|
|
947a732bfb | ||
|
|
d88c5648de | ||
|
|
94fbd3fac9 | ||
|
|
07eab6e766 | ||
|
|
a2833cf276 | ||
|
|
079715bc18 | ||
|
|
5a32d8a779 | ||
|
|
9f1705a4f1 | ||
|
|
02650fa490 | ||
|
|
fff3e1474f | ||
|
|
d9de1718b7 | ||
|
|
78891ae00e | ||
|
|
b344def887 | ||
|
|
a1bc815f63 | ||
|
|
668cc3f0a5 |
No files matched your search
@@ -1,5 +1,25 @@
|
||||
# Change Log
|
||||
|
||||
## 1.3.7 22/06/2015
|
||||
|
||||
* Prevent install on Python 2
|
||||
|
||||
## 1.3.6 16/06/2015
|
||||
|
||||
* Fix an issue with 1.4dev compatibility
|
||||
|
||||
## 1.3.5 16/06/15
|
||||
|
||||
* Ignore invalid characters when reading the output of a process
|
||||
* Turn on / off authentication
|
||||
* Ensure no colored output on Windows
|
||||
* Do not stop saving IOS router configs when there is an exception while a project is committed.
|
||||
* Create a private config file if expected
|
||||
* Distribute our own version of netifaces working with python 3
|
||||
* Fix crash if a private config exist in IOS but no private config file
|
||||
* Basic Auth support
|
||||
* Fix crash when virtualbox list of VMS return an empty line
|
||||
|
||||
## 1.3.4 02/06/15
|
||||
|
||||
* Drop useless dependencie dateutil
|
||||
|
||||
@@ -51,7 +51,7 @@ class CrashReport:
|
||||
Report crash to a third party service
|
||||
"""
|
||||
|
||||
DSN = "sync+https://9e6f04df72c74b6894a6dcd2928d069e:2035d1beb1654136b170f1e91f05ee51@app.getsentry.com/38482"
|
||||
DSN = "sync+https://3d569add80c74d4faecf90836bcdc1b5:3b5aa0c47c1847bc8d019b5e52ebdd1a@app.getsentry.com/38482"
|
||||
if hasattr(sys, "frozen"):
|
||||
cacert = os.path.join(os.getcwd(), "cacert.pem")
|
||||
if os.path.isfile(cacert):
|
||||
|
||||
@@ -210,7 +210,11 @@ class Dynamips(BaseManager):
|
||||
# save the configs when the project is committed
|
||||
for vm in self._vms.copy().values():
|
||||
if vm.project.id == project.id:
|
||||
yield from vm.save_configs()
|
||||
try:
|
||||
yield from vm.save_configs()
|
||||
except DynamipsError as e:
|
||||
log.warning(e)
|
||||
continue
|
||||
|
||||
@property
|
||||
def dynamips_path(self):
|
||||
|
||||
@@ -1499,6 +1499,9 @@ class Router(BaseVM):
|
||||
module_workdir = self.project.module_working_directory(self.manager.module_name.lower())
|
||||
startup_config_base64, private_config_base64 = yield from self.extract_config()
|
||||
if startup_config_base64:
|
||||
if not self.startup_config:
|
||||
self._startup_config = os.path.join("configs", "i{}_startup-config.cfg".format(self._dynamips_id))
|
||||
|
||||
try:
|
||||
config = base64.b64decode(startup_config_base64).decode("utf-8", errors="replace")
|
||||
config = "!\n" + config.replace("\r", "")
|
||||
@@ -1510,6 +1513,9 @@ class Router(BaseVM):
|
||||
raise DynamipsError("Could not save the startup configuration {}: {}".format(config_path, e))
|
||||
|
||||
if private_config_base64:
|
||||
if not self.private_config:
|
||||
self._private_config = os.path.join("configs", "i{}_private-config.cfg".format(self._dynamips_id))
|
||||
|
||||
try:
|
||||
config = base64.b64decode(private_config_base64).decode("utf-8", errors="replace")
|
||||
config = "!\n" + config.replace("\r", "")
|
||||
|
||||
@@ -168,7 +168,7 @@ class VirtualBox(BaseManager):
|
||||
vms = []
|
||||
result = yield from self.execute("list", ["vms"])
|
||||
for line in result:
|
||||
if line[0] != '"' or line[-1:] != "}":
|
||||
if len(line) == 0 or line[0] != '"' or line[-1:] != "}":
|
||||
continue # Broken output (perhaps a carriage return in VM name
|
||||
vmname, _ = line.rsplit(' ', 1)
|
||||
vmname = vmname.strip('"')
|
||||
|
||||
@@ -51,7 +51,10 @@ def subprocess_check_output(*args, cwd=None, env=None):
|
||||
output = yield from proc.stdout.read()
|
||||
if output is None:
|
||||
return ""
|
||||
return output.decode("utf-8")
|
||||
# If we received garbage we ignore invalid characters
|
||||
# it should happend only when user try to use another binary
|
||||
# and the code of VPCS, dynamips... Will detect it's not the correct binary
|
||||
return output.decode("utf-8", errors="ignore")
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
|
||||
@@ -23,5 +23,5 @@
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
|
||||
__version__ = "1.3.4"
|
||||
__version_info__ = (1, 3, 4, 0)
|
||||
__version__ = "1.3.7"
|
||||
__version_info__ = (1, 3, 7, 0)
|
||||
@@ -34,7 +34,7 @@ class ColouredFormatter(logging.Formatter):
|
||||
|
||||
message = super().format(record)
|
||||
|
||||
if not colour:
|
||||
if not colour or sys.platform.startswith("win"):
|
||||
return message.replace("#RESET#", "")
|
||||
|
||||
level_no = record.levelno
|
||||
@@ -90,7 +90,7 @@ class WinStreamHandler(logging.StreamHandler):
|
||||
|
||||
stream = self.stream
|
||||
try:
|
||||
msg = self.formatter.format(record, stream.isatty())
|
||||
msg = self.formatter.format(record, stream.isatty())
|
||||
stream.write(msg.encode(stream.encoding, errors="replace").decode(stream.encoding))
|
||||
stream.write(self.terminator)
|
||||
self.flush()
|
||||
|
||||
+32
-1
@@ -83,6 +83,31 @@ class Route(object):
|
||||
def delete(cls, path, *args, **kw):
|
||||
return cls._route('DELETE', path, *args, **kw)
|
||||
|
||||
@classmethod
|
||||
def authenticate(cls, request, route, server_config):
|
||||
"""
|
||||
Ask user for authentication
|
||||
|
||||
:returns: Response if you need to auth the user otherwise None
|
||||
"""
|
||||
if not server_config.getboolean("auth", False):
|
||||
return
|
||||
|
||||
user = server_config.get("user", "").strip()
|
||||
password = server_config.get("password", "").strip()
|
||||
|
||||
if len(user) == 0:
|
||||
return
|
||||
|
||||
if "AUTHORIZATION" in request.headers:
|
||||
if request.headers["AUTHORIZATION"] == aiohttp.helpers.BasicAuth(user, password).encode():
|
||||
return
|
||||
|
||||
response = Response(request=request, route=route)
|
||||
response.set_status(401)
|
||||
response.headers["WWW-Authenticate"] = 'Basic realm="GNS3 server"'
|
||||
return response
|
||||
|
||||
@classmethod
|
||||
def _route(cls, method, path, *args, **kw):
|
||||
# This block is executed only the first time
|
||||
@@ -118,6 +143,13 @@ class Route(object):
|
||||
def control_schema(request):
|
||||
# This block is executed at each method call
|
||||
|
||||
server_config = Config.instance().get_section_config("Server")
|
||||
|
||||
# Authenticate
|
||||
response = cls.authenticate(request, route, server_config)
|
||||
if response:
|
||||
return response
|
||||
|
||||
# Non API call
|
||||
if api_version is None:
|
||||
response = Response(request=request, route=route, output_schema=output_schema)
|
||||
@@ -127,7 +159,6 @@ class Route(object):
|
||||
# API call
|
||||
try:
|
||||
request = yield from parse_request(request, input_schema)
|
||||
server_config = Config.instance().get_section_config("Server")
|
||||
record_file = server_config.get("record")
|
||||
if record_file:
|
||||
try:
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
netifaces==0.10.4
|
||||
gns3-netifaces==0.10.4.1
|
||||
jsonschema==2.4.0
|
||||
aiohttp==0.14.4
|
||||
Jinja2==2.7.3
|
||||
|
||||
@@ -19,6 +19,10 @@ import sys
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools.command.test import test as TestCommand
|
||||
|
||||
# we only support Python 3 version >= 3.3
|
||||
if sys.version_info < (3, 3):
|
||||
raise SystemExit("Python 3.3 or higher is required")
|
||||
|
||||
|
||||
class PyTest(TestCommand):
|
||||
|
||||
@@ -34,12 +38,14 @@ class PyTest(TestCommand):
|
||||
sys.exit(errcode)
|
||||
|
||||
|
||||
dependencies = ["aiohttp>=0.14.4",
|
||||
"jsonschema>=2.4.0",
|
||||
"Jinja2>=2.7.3",
|
||||
"raven>=5.2.0"]
|
||||
dependencies = [
|
||||
# "gns3-netifaces>=0.10.4.1",
|
||||
"aiohttp>=0.14.4",
|
||||
"jsonschema>=2.4.0",
|
||||
"Jinja2>=2.7.3",
|
||||
"raven>=5.2.0"]
|
||||
|
||||
#if not sys.platform.startswith("win"):
|
||||
# if not sys.platform.startswith("win"):
|
||||
# dependencies.append("netifaces==0.10.4")
|
||||
|
||||
if sys.version_info == (3, 3):
|
||||
|
||||
@@ -136,6 +136,7 @@ def run_around_tests(monkeypatch):
|
||||
config = Config.instance()
|
||||
config.clear()
|
||||
config.set("Server", "project_directory", tmppath)
|
||||
config.set("Server", "auth", False)
|
||||
|
||||
# Prevent exectuions of the VM if we forgot to mock something
|
||||
config.set("VirtualBox", "vboxmanage_path", tmppath)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
import aiohttp
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
from gns3server.config import Config
|
||||
|
||||
def test_index_upload(server):
|
||||
response = server.get('/upload', api_version=None)
|
||||
@@ -37,8 +37,8 @@ def test_upload(server, tmpdir):
|
||||
body.add_field("type", "QEMU")
|
||||
body.add_field("file", open(str(tmpdir / "test"), "rb"), content_type="application/iou", filename="test2")
|
||||
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"images_path": str(tmpdir)}):
|
||||
response = server.post('/upload', api_version=None, body=body, raw=True)
|
||||
Config.instance().set("Server", "images_path", str(tmpdir))
|
||||
response = server.post('/upload', api_version=None, body=body, raw=True)
|
||||
|
||||
with open(str(tmpdir / "QEMU" / "test2")) as f:
|
||||
assert f.read() == "TEST"
|
||||
|
||||
@@ -75,9 +75,9 @@ def test_get_list(manager, loop):
|
||||
vm_list = ['"Windows 8.1" {27b4d095-ff5f-4ac4-bb9d-5f2c7861c1f1}',
|
||||
'"Carriage',
|
||||
'Return" {27b4d095-ff5f-4ac4-bb9d-5f2c7861c1f1}',
|
||||
'',
|
||||
'"<inaccessible>" {42b4d095-ff5f-4ac4-bb9d-5f2c7861c1f1}',
|
||||
'"Linux Microcore 4.7.1" {ccd8c50b-c172-457d-99fa-dd69371ede0e}'
|
||||
]
|
||||
'"Linux Microcore 4.7.1" {ccd8c50b-c172-457d-99fa-dd69371ede0e}']
|
||||
|
||||
@asyncio.coroutine
|
||||
def execute_mock(cmd, args):
|
||||
|
||||
Reference in new issue
Block a user