Compare commits

...
23 Commits
Author SHA1 Message Date
grossmj c0c8151480 Release v2.2.9 2020-06-04 18:39:27 +09:30
grossmj ad7277c938 Merge branch 'master' into 2.2 2020-06-04 12:21:52 +09:30
Jeremy Grossmann 0c2e4d2de9 Merge pull request #1768 from GNS3/replicate-network-connection-state
Support to activate/deactive network connection state replication in Qemu
2020-06-04 10:49:47 +08:00
grossmj 1264680b51 Sync appliances. 2020-06-04 12:18:16 +09:30
piotrpekala7 a9697e925c Release 2020.2.0-beta.4 2020-06-03 19:15:56 +02:00
Jeremy Grossmann 16a0e1c308 Merge pull request #1771 from eknoes/patch-1
Fix link for appliance JSON schema
2020-06-03 19:48:07 +08:00
eknoes f53d6f1b66 Fix link for appliance JSON schema 2020-06-03 13:46:48 +02:00
grossmj 58a19af9ac Support to activate/deactive network connection state replication in Qemu. 2020-06-02 18:45:22 +09:30
grossmj a796f1e42e Possible fix for problem connecting to the GNS3 VM. Ref https://github.com/GNS3/gns3-gui/issues/2969 #1760 2020-06-01 19:40:53 +09:30
Jeremy Grossmann 6e4187741c Merge pull request #1764 from GNS3/reset-mac-addresses
Option to reset MAC addresses when exporting or duplicating a project
2020-05-27 10:53:24 +08:00
grossmj 8eefaa3f32 Option to reset or not all MAC addresses when exporting or duplicating a project. 2020-05-27 12:14:47 +09:30
grossmj 5575657318 Fix tests. Ref #1754 2020-05-26 21:40:41 +09:30
grossmj 69b816e21e Fix bug when changing properties for closed project. Fixes #1754 2020-05-26 18:34:20 +09:30
grossmj 5c3bd589b9 Fix issues with crash reporting & bump version to 2.2.9dev2. Ref https://github.com/GNS3/gns3-server/issues/1758 2020-05-21 18:19:19 +09:30
grossmj 1a20cbeefd Lock listing VMs. Ref #1755 2020-05-20 19:33:56 +09:30
grossmj da85d7b827 Try to fix error when listing Hyper-V VMs. Ref #1755 2020-05-20 19:19:04 +09:30
grossmj 7002b026fc Catch VirtualBox errors when listing VMs. Fixes #1759 2020-05-20 18:42:50 +09:30
grossmj 00f8a27404 Merge branch 'master' into 2.2
# Conflicts:
#	requirements.txt
2020-05-19 16:16:19 +09:30
grossmj 5b59a09e8d Deprecate running with Python 3.5 2020-05-19 16:14:58 +09:30
grossmj 16ca0fd915 aiocontextvars is only necessary for Python < 3.7 2020-05-19 16:04:14 +09:30
grossmj c63aad8eca Replace Raven by Sentry SDK. Fixes https://github.com/GNS3/gns3-server/issues/1758 2020-05-19 15:48:53 +09:30
grossmj 54bab7445c Require setuptools>=17.1 in setup.py. Ref https://github.com/GNS3/gns3-server/issues/1751
This is to support environmental markers.
https://github.com/pypa/setuptools/blob/master/CHANGES.rst#171
2020-05-08 12:34:57 +09:30
grossmj 32a8bc54a1 Development on 2.2.9dev1 2020-05-07 23:10:19 +09:30
26 changed files with 251 additions and 103 deletions

No files matched your search

-1
View File
@@ -27,7 +27,6 @@ deploy:
env:
matrix:
- PYTHON_VERSION=3.5
- PYTHON_VERSION=3.6
- PYTHON_VERSION=3.7
- PYTHON_VERSION=3.8
+16
View File
@@ -1,5 +1,21 @@
# Change Log
## 2.2.9 04/06/2020
* Release Web-Ui version 2020.2.0-beta.4
* Support to activate/deactive network connection state replication in Qemu.
* Possible fix for problem connecting to the GNS3 VM. Ref https://github.com/GNS3/gns3-gui/issues/2969 #1760
* Option to reset or not all MAC addresses when exporting or duplicating a project.
* Fix bug when changing properties for closed project. Fixes #1754
* Fix issues with crash reporting & bump version to 2.2.9dev2. Ref https://github.com/GNS3/gns3-server/issues/1758
* Lock listing VMs. Ref #1755
* Try to fix error when listing Hyper-V VMs. Ref #1755
* Catch VirtualBox errors when listing VMs. Fixes #1759
* Deprecate running with Python 3.5
* aiocontextvars is only necessary for Python < 3.7
* Replace Raven by Sentry SDK. Fixes https://github.com/GNS3/gns3-server/issues/1758
* Require setuptools>=17.1 in setup.py. Ref https://github.com/GNS3/gns3-server/issues/1751 This is to support environmental markers. https://github.com/pypa/setuptools/blob/master/CHANGES.rst#171
## 2.2.8 07/05/2020
* Release Web-Ui 2020.2.0-beta.3
+1 -1
View File
@@ -58,7 +58,7 @@ The zip can be a ZIP64 if the project is too big for standard zip file.
These files contain everything needed to create a new appliance template in GNS3.
A JSON schema is available there:
https://github.com/GNS3/gns3-registry/blob/master/schemas/appliance.json
https://github.com/GNS3/gns3-registry/blob/master/schemas/appliance_v6.json
And samples there:
https://github.com/GNS3/gns3-registry/tree/master/appliances
+15
View File
@@ -21,6 +21,15 @@
"kvm": "allow"
},
"images": [
{
"filename": "openwrt-19.07.3-x86-64-combined-ext4.img",
"version": "19.07.3",
"md5sum": "d150595d624cba9c8989a675fdfbc329",
"filesize": 285736960,
"download_url": "https://downloads.openwrt.org/releases/19.07.3/targets/x86/64/",
"direct_download_url": "https://downloads.openwrt.org/releases/19.07.3/targets/x86/64/openwrt-19.07.3-x86-64-combined-ext4.img.gz",
"compression": "gzip"
},
{
"filename": "openwrt-19.07.2-x86-64-combined-ext4.img",
"version": "19.07.2",
@@ -122,6 +131,12 @@
}
],
"versions": [
{
"name": "19.07.3",
"images": {
"hda_disk_image": "openwrt-19.07.3-x86-64-combined-ext4.img"
}
},
{
"name": "19.07.2",
"images": {
+37 -9
View File
@@ -117,6 +117,7 @@ class QemuVM(BaseNode):
self._kernel_image = ""
self._kernel_command_line = ""
self._legacy_networking = False
self._replicate_network_connection_state = True
self._on_close = "power_off"
self._cpu_throttling = 0 # means no CPU throttling
self._process_priority = "low"
@@ -615,6 +616,30 @@ class QemuVM(BaseNode):
log.info('QEMU VM "{name}" [{id}] has disabled legacy networking'.format(name=self._name, id=self._id))
self._legacy_networking = legacy_networking
@property
def replicate_network_connection_state(self):
"""
Returns whether the network connection state for links is replicated in QEMU.
:returns: boolean
"""
return self._replicate_network_connection_state
@replicate_network_connection_state.setter
def replicate_network_connection_state(self, replicate_network_connection_state):
"""
Sets whether the network connection state for links is replicated in QEMU
:param replicate_network_connection_state: boolean
"""
if replicate_network_connection_state:
log.info('QEMU VM "{name}" [{id}] has enabled network connection state replication'.format(name=self._name, id=self._id))
else:
log.info('QEMU VM "{name}" [{id}] has disabled network connection state replication'.format(name=self._name, id=self._id))
self._replicate_network_connection_state = replicate_network_connection_state
@property
def on_close(self):
"""
@@ -1004,12 +1029,12 @@ class QemuVM(BaseNode):
await self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number),
self._local_udp_tunnels[adapter_number][1],
nio)
if nio.suspend:
if nio.suspend and self._replicate_network_connection_state:
set_link_commands.append("set_link gns3-{} off".format(adapter_number))
else:
elif self._replicate_network_connection_state:
set_link_commands.append("set_link gns3-{} off".format(adapter_number))
if "-loadvm" not in command_string:
if "-loadvm" not in command_string and self._replicate_network_connection_state:
# only set the link statuses if not restoring a previous VM state
await self._control_vm_commands(set_link_commands)
@@ -1293,7 +1318,8 @@ class QemuVM(BaseNode):
await self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number),
self._local_udp_tunnels[adapter_number][1],
nio)
await self._control_vm("set_link gns3-{} on".format(adapter_number))
if self._replicate_network_connection_state:
await self._control_vm("set_link gns3-{} on".format(adapter_number))
except (IndexError, KeyError):
raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name,
adapter_number=adapter_number))
@@ -1317,10 +1343,11 @@ class QemuVM(BaseNode):
await self.update_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number),
self._local_udp_tunnels[adapter_number][1],
nio)
if nio.suspend:
await self._control_vm("set_link gns3-{} off".format(adapter_number))
else:
await self._control_vm("set_link gns3-{} on".format(adapter_number))
if self._replicate_network_connection_state:
if nio.suspend:
await self._control_vm("set_link gns3-{} off".format(adapter_number))
else:
await self._control_vm("set_link gns3-{} on".format(adapter_number))
except IndexError:
raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name,
adapter_number=adapter_number))
@@ -1342,7 +1369,8 @@ class QemuVM(BaseNode):
await self.stop_capture(adapter_number)
if self.is_running():
await self._control_vm("set_link gns3-{} off".format(adapter_number))
if self._replicate_network_connection_state:
await self._control_vm("set_link gns3-{} off".format(adapter_number))
await self._ubridge_send("bridge delete {name}".format(name="QEMU-{}-{}".format(self._id, adapter_number)))
nio = adapter.get_nio(0)
+4 -4
View File
@@ -361,17 +361,17 @@ class Compute:
response = await self._run_http_query("GET", "/capabilities")
except ComputeError as e:
log.warning("Cannot connect to compute '{}': {}".format(self._id, e))
# Try to reconnect after 2 seconds if server unavailable only if not during tests (otherwise we create a ressource usage bomb)
# Try to reconnect after 5 seconds if server unavailable only if not during tests (otherwise we create a ressource usage bomb)
if not hasattr(sys, "_called_from_test") or not sys._called_from_test:
if self.id != "local" and not self._controller.compute_has_open_project(self):
log.info("Not reconnecting to compute '{}' because there is no project opened on it".format(self._id))
if self.id != "local" and self.id != "vm" and not self._controller.compute_has_open_project(self):
log.warning("Not reconnecting to compute '{}' because there is no project opened on it".format(self._id))
return
self._connection_failure += 1
# After 5 failure we close the project using the compute to avoid sync issues
if self._connection_failure == 10:
log.error("Could not connect to compute '{}' after multiple attempts: {}".format(self._id, e))
await self._controller.close_compute_projects(self)
asyncio.get_event_loop().call_later(2, lambda: asyncio.ensure_future(self._try_reconnect()))
asyncio.get_event_loop().call_later(5, lambda: asyncio.ensure_future(self._try_reconnect()))
return
except aiohttp.web.HTTPNotFound:
raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server or it's a 1.X server".format(self._id))
+1
View File
@@ -250,6 +250,7 @@ class GNS3VM:
def __json__(self):
return self._settings
@locking
async def list(self, engine):
"""
List VMS for an engine
@@ -179,7 +179,7 @@ class HyperVGNS3VM(BaseGNS3VM):
List all Hyper-V VMs
"""
if self._conn is None:
if self._conn is None or self._management is None:
self._connect()
vms = []
@@ -212,8 +212,11 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
List all VirtualBox VMs
"""
await self._check_requirements()
return await self._virtualbox_manager.list_vms()
try:
await self._check_requirements()
return await self._virtualbox_manager.list_vms()
except VirtualBoxError as e:
raise GNS3VMError("Could not list VirtualBox VMs: {}".format(str(e)))
async def start(self):
"""
@@ -115,6 +115,7 @@ class VMwareGNS3VM(BaseGNS3VM):
"""
List all VMware VMs
"""
try:
return (await self._vmware_manager.list_vms())
except VMwareError as e:
+6 -2
View File
@@ -437,6 +437,9 @@ class Project:
"""
:return: List of computes used by the project
"""
if self._status == "closed":
return self._get_closed_data("computes", "compute_id").values()
return self._project_created_on_compute
def remove_allocated_node_name(self, name):
@@ -996,7 +999,7 @@ class Project:
while self._loading:
await asyncio.sleep(0.5)
async def duplicate(self, name=None, location=None):
async def duplicate(self, name=None, location=None, reset_mac_addresses=True):
"""
Duplicate a project
@@ -1006,6 +1009,7 @@ class Project:
:param name: Name of the new project. A new one will be generated in case of conflicts
:param location: Parent directory of the new project
:param reset_mac_addresses: Reset MAC addresses for the new project
"""
# If the project was not open we open it temporary
previous_status = self._status
@@ -1019,7 +1023,7 @@ class Project:
with tempfile.TemporaryDirectory() as tmpdir:
# Do not compress the exported project when duplicating
with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream:
await export_project(zstream, self, tmpdir, keep_compute_id=True, allow_all_nodes=True, reset_mac_addresses=True)
await export_project(zstream, self, tmpdir, keep_compute_id=True, allow_all_nodes=True, reset_mac_addresses=reset_mac_addresses)
# export the project to a temporary location
project_path = os.path.join(tmpdir, "project.gns3p")
+15 -6
View File
@@ -99,19 +99,28 @@ def project_to_topology(project):
"version": __version__
}
computes = set()
for node in project.nodes.values():
computes.add(node.compute)
data["topology"]["nodes"].append(node.__json__(topology_dump=True))
if hasattr(node, "__json__"):
data["topology"]["nodes"].append(node.__json__(topology_dump=True))
else:
data["topology"]["nodes"].append(node)
for link in project.links.values():
data["topology"]["links"].append(link.__json__(topology_dump=True))
if hasattr(link, "__json__"):
data["topology"]["links"].append(link.__json__(topology_dump=True))
else:
data["topology"]["links"].append(link)
for drawing in project.drawings.values():
data["topology"]["drawings"].append(drawing.__json__(topology_dump=True))
for compute in computes:
if hasattr(drawing, "__json__"):
data["topology"]["drawings"].append(drawing.__json__(topology_dump=True))
else:
data["topology"]["drawings"].append(drawing)
for compute in project.computes:
if hasattr(compute, "__json__"):
compute = compute.__json__(topology_dump=True)
if compute["compute_id"] not in ("vm", "local", ):
data["topology"]["computes"].append(compute)
elif isinstance(compute, dict):
data["topology"]["computes"].append(compute)
_check_topology_schema(data)
return data
+76 -46
View File
@@ -15,22 +15,21 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
try:
import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
SENTRY_SDK_AVAILABLE = True
except ImportError:
# Sentry SDK is not installed with deb package in order to simplify packaging
SENTRY_SDK_AVAILABLE = False
import os
import sys
import struct
import aiohttp
import platform
import locale
import distro
try:
import raven
from raven.transport.http import HTTPTransport
RAVEN_AVAILABLE = True
except ImportError:
# raven is not installed with deb package in order to simplify packaging
RAVEN_AVAILABLE = False
from .version import __version__, __version_info__
from .config import Config
from .utils.get_resource import get_resource
@@ -43,7 +42,8 @@ log = logging.getLogger(__name__)
if __version_info__[3] != 0:
import faulthandler
# Display a traceback in case of segfault crash. Usefull when frozen
# Display a traceback in case of segfault crash.
# Useful when this application is frozen.
# Not enabled by default for security reason
log.info("Enable catching segfault")
try:
@@ -58,49 +58,49 @@ class CrashReport:
Report crash to a third party service
"""
DSN = "https://dbfb677c73304b1286aef33dfbb749c6:93b9a937d4884426a1b15f37536fcd94@o19455.ingest.sentry.io/38482"
if hasattr(sys, "frozen"):
cacert = get_resource("cacert.pem")
if cacert is not None and os.path.isfile(cacert):
DSN += "?ca_certs={}".format(cacert)
else:
log.warning("The SSL certificate bundle file '{}' could not be found".format(cacert))
DSN = "https://bc5e20f335f3445ea297aa0049f2acd8:13e6c221d8f5480e9f04ce5a132ea926@o19455.ingest.sentry.io/38482"
_instance = None
def __init__(self):
self._client = None
# We don't want sentry making noise if an error is catched when you don't have internet
# We don't want sentry making noise if an error is caught when you don't have internet
sentry_errors = logging.getLogger('sentry.errors')
sentry_errors.disabled = True
sentry_uncaught = logging.getLogger('sentry.errors.uncaught')
sentry_uncaught.disabled = True
def capture_exception(self, request=None):
if not RAVEN_AVAILABLE:
return
if os.path.exists(".git"):
log.warning("A .git directory exist crash report is turn off for developers")
return
server_config = Config.instance().get_section_config("Server")
if server_config.getboolean("report_errors"):
if self._client is None:
self._client = raven.Client(CrashReport.DSN, release=__version__, raise_send_errors=True, transport=HTTPTransport)
if request is not None:
self._client.http_context({
"method": request.method,
"url": request.path,
"data": request.json,
})
if SENTRY_SDK_AVAILABLE:
cacert = None
if hasattr(sys, "frozen"):
cacert_resource = get_resource("cacert.pem")
if cacert_resource is not None and os.path.isfile(cacert_resource):
cacert = cacert_resource
else:
log.error("The SSL certificate bundle file '{}' could not be found".format(cacert_resource))
context = {
# Don't send log records as events.
sentry_logging = LoggingIntegration(level=logging.INFO, event_level=None)
sentry_sdk.init(dsn=CrashReport.DSN,
release=__version__,
ca_certs=cacert,
integrations=[sentry_logging])
tags = {
"os:name": platform.system(),
"os:release": platform.release(),
"os:win_32": " ".join(platform.win32_ver()),
"os:mac": "{} {}".format(platform.mac_ver()[0], platform.mac_ver()[2]),
"os:linux": " ".join(distro.linux_distribution()),
"aiohttp:version": aiohttp.__version__,
}
with sentry_sdk.configure_scope() as scope:
for key, value in tags.items():
scope.set_tag(key, value)
extra_context = {
"python:version": "{}.{}.{}".format(sys.version_info[0],
sys.version_info[1],
sys.version_info[2]),
@@ -113,8 +113,8 @@ class CrashReport:
# add locale information
try:
language, encoding = locale.getlocale()
context["locale:language"] = language
context["locale:encoding"] = encoding
extra_context["locale:language"] = language
extra_context["locale:encoding"] = encoding
except ValueError:
pass
@@ -124,17 +124,47 @@ class CrashReport:
if os.path.isfile(gns3vm_version):
try:
with open(gns3vm_version) as fd:
context["gns3vm:version"] = fd.readline().strip()
extra_context["gns3vm:version"] = fd.readline().strip()
except OSError:
pass
self._client.tags_context(context)
try:
report = self._client.captureException()
except Exception as e:
log.error("Can't send crash report to Sentry: {}".format(e))
with sentry_sdk.configure_scope() as scope:
for key, value in extra_context.items():
scope.set_extra(key, value)
def capture_exception(self, request):
if not SENTRY_SDK_AVAILABLE:
return
if not hasattr(sys, "frozen") and os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".git")):
log.warning(".git directory detected, crash reporting is turned off for developers.")
return
server_config = Config.instance().get_section_config("Server")
if server_config.getboolean("report_errors"):
if not SENTRY_SDK_AVAILABLE:
log.warning("Cannot capture exception: Sentry SDK is not available")
return
log.info("Crash report sent with event ID: {}".format(self._client.get_ident(report)))
if os.path.exists(".git"):
log.warning(".git directory detected, crash reporting is turned off for developers.")
return
try:
if request:
# add specific extra request information
with sentry_sdk.push_scope() as scope:
scope.set_extra("method", request.method)
scope.set_extra("url", request.path)
scope.set_extra("json", request.json)
sentry_sdk.capture_exception()
else:
sentry_sdk.capture_exception()
log.info("Crash report sent with event ID: {}".format(sentry_sdk.last_event_id()))
except Exception as e:
log.warning("Can't send crash report to Sentry: {}".format(e))
@classmethod
def instance(cls):
@@ -35,7 +35,8 @@ from gns3server.schemas.project import (
PROJECT_OBJECT_SCHEMA,
PROJECT_UPDATE_SCHEMA,
PROJECT_LOAD_SCHEMA,
PROJECT_CREATE_SCHEMA
PROJECT_CREATE_SCHEMA,
PROJECT_DUPLICATE_SCHEMA
)
import logging
@@ -313,6 +314,11 @@ class ProjectHandler:
include_images = True
else:
include_images = False
if request.query.get("reset_mac_addresses", "no").lower() == "yes":
reset_mac_addresses = True
else:
reset_mac_addresses = False
compression_query = request.query.get("compression", "zip").lower()
if compression_query == "zip":
compression = zipfile.ZIP_DEFLATED
@@ -327,7 +333,7 @@ class ProjectHandler:
begin = time.time()
with tempfile.TemporaryDirectory() as tmp_dir:
with aiozipstream.ZipFile(compression=compression) as zstream:
await export_project(zstream, project, tmp_dir, include_snapshots=include_snapshots, include_images=include_images)
await export_project(zstream, project, tmp_dir, include_snapshots=include_snapshots, include_images=include_images, reset_mac_addresses=reset_mac_addresses)
# We need to do that now because export could failed and raise an HTTP error
# that why response start need to be the later possible
@@ -398,7 +404,7 @@ class ProjectHandler:
parameters={
"project_id": "Project UUID",
},
input=PROJECT_CREATE_SCHEMA,
input=PROJECT_DUPLICATE_SCHEMA,
output=PROJECT_OBJECT_SCHEMA,
status_codes={
201: "Project duplicate",
@@ -419,7 +425,9 @@ class ProjectHandler:
else:
location = None
new_project = await project.duplicate(name=request.json.get("name"), location=location)
reset_mac_addresses = request.json.get("reset_mac_addresses", False)
new_project = await project.duplicate(name=request.json.get("name"), location=location, reset_mac_addresses=reset_mac_addresses)
response.json(new_project)
response.set_status(201)
+3 -3
View File
@@ -236,9 +236,9 @@ def run():
return
log.info("HTTP authentication is enabled with username '{}'".format(user))
# we only support Python 3 version >= 3.5.3
if sys.version_info < (3, 5, 3):
raise SystemExit("Python 3.5.3 or higher is required")
# we only support Python 3 version >= 3.6
if sys.version_info < (3, 6, 0):
raise SystemExit("Python 3.6 or higher is required")
user_log.info("Running with Python {major}.{minor}.{micro} and has PID {pid}".format(major=sys.version_info[0], minor=sys.version_info[1],
micro=sys.version_info[2], pid=os.getpid()))
+9
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/>.
import copy
SUPPLIER_OBJECT_SCHEMA = {
"type": ["object", "null"],
"description": "Supplier of the project",
@@ -120,6 +122,13 @@ PROJECT_CREATE_SCHEMA = {
"required": ["name"]
}
# Create a project duplicate schema based on create schema and add "reset_mac_addresses" properties
PROJECT_DUPLICATE_SCHEMA = copy.deepcopy(PROJECT_CREATE_SCHEMA)
PROJECT_DUPLICATE_SCHEMA["description"] = "Request validation to duplicate a Project instance"
PROJECT_DUPLICATE_SCHEMA["properties"].update({"reset_mac_addresses": {"type": "boolean",
"description": "Reset MAC addresses for this project"
}})
PROJECT_UPDATE_SCHEMA = {
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Request validation to update a Project instance",
+13
View File
@@ -186,6 +186,10 @@ QEMU_CREATE_SCHEMA = {
"description": "Use QEMU legagy networking commands (-net syntax)",
"type": ["boolean", "null"],
},
"replicate_network_connection_state": {
"description": "Replicate the network connection state for links in Qemu",
"type": ["boolean", "null"],
},
"on_close": {
"description": "Action to execute on the VM is closed",
"enum": ["power_off", "shutdown_signal", "save_vm_state"],
@@ -372,6 +376,10 @@ QEMU_UPDATE_SCHEMA = {
"description": "Use QEMU legagy networking commands (-net syntax)",
"type": ["boolean", "null"],
},
"replicate_network_connection_state": {
"description": "Replicate the network connection state for links in Qemu",
"type": ["boolean", "null"],
},
"on_close": {
"description": "Action to execute on the VM is closed",
"enum": ["power_off", "shutdown_signal", "save_vm_state"],
@@ -571,6 +579,10 @@ QEMU_OBJECT_SCHEMA = {
"description": "Use QEMU legagy networking commands (-net syntax)",
"type": "boolean",
},
"replicate_network_connection_state": {
"description": "Replicate the network connection state for links in Qemu",
"type": "boolean",
},
"on_close": {
"description": "Action to execute on the VM is closed",
"enum": ["power_off", "shutdown_signal", "save_vm_state"],
@@ -640,6 +652,7 @@ QEMU_OBJECT_SCHEMA = {
"kernel_image_md5sum",
"kernel_command_line",
"legacy_networking",
"replicate_network_connection_state",
"on_close",
"cpu_throttling",
"process_priority",
+5
View File
@@ -178,6 +178,11 @@ QEMU_TEMPLATE_PROPERTIES = {
"type": "boolean",
"default": False
},
"replicate_network_connection_state": {
"description": "Replicate the network connection state for links in Qemu",
"type": "boolean",
"default": True
},
"on_close": {
"description": "Action to execute on the VM is closed",
"enum": ["power_off", "shutdown_signal", "save_vm_state"],
+14 -1
View File
@@ -1,6 +1,19 @@
GNS3 WebUI is web implementation of user interface for GNS3 software.
Current version: GNS3 Web UI 2020.2.0-beta.2
Current version: GNS3 Web UI 2020.2.0-beta.4
Bug Fixes
- New port setting for GNS3 VM preferences
- Option to auto-hide menu toolbar on the left side
- Server type in template preferences
- Error when selecting existing Docker image
- Default values in templates
- TypeError: Cannot read property 'message' of undefined
- TypeError: e.error is undefined
- TypeError: Cannot read property 'placements' of null
- Creating IOS templates -> fix for platforms and network adapters
GNS3 Web UI 2020.2.0-beta.2
What's New
- Drag & drop to add new nodes on topology
+1 -1
View File
@@ -48,5 +48,5 @@
gtag('config', 'G-5D6FZL9923');
</script>
<script src="runtime.a8ef3a8272419c2e2c66.js" defer></script><script src="polyfills-es5.adfecedb3e8b94a475d4.js" nomodule defer></script><script src="polyfills.312ad1f991887572d9bc.js" defer></script><script src="main.675279bd49308a23d11c.js" defer></script></body>
<script src="runtime.a8ef3a8272419c2e2c66.js" defer></script><script src="polyfills-es5.adfecedb3e8b94a475d4.js" nomodule defer></script><script src="polyfills.312ad1f991887572d9bc.js" defer></script><script src="main.0846ddc10f839bedfff3.js" defer></script></body>
</html>
@@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{"+/L5":function(n,e,t){var l=t("t1UP").isCustomProperty,o=t("vd7W").TYPE,i=t("4njK").mode,r=o.Ident,a=o.Hash,u=o.Colon,s=o.Semicolon,d=o.Delim,c=33,p=35,f=36,h=38,m=42,v=43,g=47;function b(n){return this.Raw(n,i.exclamationMarkOrSemicolon,!0)}function _(n){return this.Raw(n,i.exclamationMarkOrSemicolon,!1)}function y(){var n=this.scanner.tokenIndex,e=this.Value();return"Raw"!==e.type&&!1===this.scanner.eof&&this.scanner.tokenType!==s&&!1===this.scanner.isDelim(c)&&!1===this.scanner.isBalanceEdge(n)&&this.error(),e}function C(){var n=this.scanner.tokenStart;if(this.scanner.tokenType===d)switch(this.scanner.source.charCodeAt(this.scanner.tokenStart)){case m:case f:case v:case p:case h:this.scanner.next();break;case g:this.scanner.next(),this.scanner.isDelim(g)&&this.scanner.next()}return this.eat(this.scanner.tokenType===a?a:r),this.scanner.substrToCursor(n)}function w(){this.eat(d),this.scanner.skipSC();var n=this.consume(r);return"important"===n||n}n.exports={name:"Declaration",structure:{important:[Boolean,String],property:String,value:["Value","Raw"]},parse:function(){var n,e=this.scanner.tokenStart,t=this.scanner.tokenIndex,o=C.call(this),i=l(o),r=i?this.parseCustomProperty:this.parseValue,a=i?_:b,d=!1;return this.scanner.skipSC(),this.eat(u),i||this.scanner.skipSC(),n=r?this.parseWithFallback(y,a):a.call(this,this.scanner.tokenIndex),this.scanner.isDelim(c)&&(d=w.call(this),this.scanner.skipSC()),!1===this.scanner.eof&&this.scanner.tokenType!==s&&!1===this.scanner.isBalanceEdge(t)&&this.error(),{type:"Declaration",loc:this.getLocation(e,this.scanner.tokenStart),important:d,property:o,value:n}},generate:function(n){this.chunk(n.property),this.chunk(":"),this.node(n.value),n.important&&this.chunk(!0===n.important?"!important":"!"+n.important)},walkContext:"declaration"}},"+Kd2":function(n,e,t){var l=t("vd7W").TYPE,o=t("4njK").mode,i=l.Comma;n.exports=function(){var n=this.createList();return this.scanner.skipSC(),n.push(this.Identifier()),this.scanner.skipSC(),this.scanner.tokenType===i&&(n.push(this.Operator()),n.push(this.parseCustomProperty?this.Value(null):this.Raw(this.scanner.tokenIndex,o.exclamationMarkOrSemicolon,!1))),n}},"+gEr":function(n,e,t){"use strict";t.d(e,"a",(function(){return r})),t.d(e,"b",(function(){return a}));var l=t("mrSG"),o=t("MGBS"),i=t("zotm"),r={leading:!0,trailing:!1};function a(n,e){return void 0===e&&(e=r),function(t){return t.lift(new u(n,e.leading,e.trailing))}}var u=function(){function n(n,e,t){this.durationSelector=n,this.leading=e,this.trailing=t}return n.prototype.call=function(n,e){return e.subscribe(new s(n,this.durationSelector,this.leading,this.trailing))},n}(),s=function(n){function e(e,t,l,o){var i=n.call(this,e)||this;return i.destination=e,i.durationSelector=t,i._leading=l,i._trailing=o,i._hasValue=!1,i}return l.c(e,n),e.prototype._next=function(n){this._hasValue=!0,this._sendValue=n,this._throttled||(this._leading?this.send():this.throttle(n))},e.prototype.send=function(){var n=this._sendValue;this._hasValue&&(this.destination.next(n),this.throttle(n)),this._hasValue=!1,this._sendValue=null},e.prototype.throttle=function(n){var e=this.tryDurationSelector(n);e&&this.add(this._throttled=Object(i.a)(this,e))},e.prototype.tryDurationSelector=function(n){try{return this.durationSelector(n)}catch(e){return this.destination.error(e),null}},e.prototype.throttlingDone=function(){var n=this._throttled,e=this._trailing;n&&n.unsubscribe(),this._throttled=null,e&&this.send()},e.prototype.notifyNext=function(n,e,t,l,o){this.throttlingDone()},e.prototype.notifyComplete=function(){this.throttlingDone()},e}(o.a)},"+ryv":function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var l=t("CcnG");e.HotkeyOptions=new l.InjectionToken("HotkeyOptions")},"+tJ4":function(n,e,t){"use strict";t.d(e,"a",(function(){return l}));var l=function(n){return function(e){for(var t=0,l=n.length;t<l&&!e.closed;t++)e.next(n[t]);e.complete()}}},"+umK":function(n,e,t){"use strict";function l(){}t.d(e,"a",(function(){return l}))},"/+5V":function(n,e){function t(n){function e(n){return null!==n&&("Type"===n.type||"Property"===n.type||"Keyword"===n.type)}var t=null;return null!==this.matched&&function l(o){if(Array.isArray(o.match)){for(var i=0;i<o.match.length;i++)if(l(o.match[i]))return e(o.syntax)&&t.unshift(o.syntax),!0}else if(o.node===n)return t=e(o.syntax)?[o.syntax]:[],!0;return!1}(this.matched),t}function l(n,e,l){var o=t.call(n,e);return null!==o&&o.some(l)}n.exports={getTrace:t,isType:function(n,e){return l(this,n,(function(n){return"Type"===n.type&&n.name===e}))},isProperty:function(n,e){return l(this,n,(function(n){return"Property"===n.type&&n.name===e}))},isKeyword:function(n){return l(this,n,(function(n){return"Keyword"===n.type}))}}},"/21U":function(n,e,t){"use strict";t.d(e,"a",(function(){return o}));var l=t("isby");function o(n){return!Object(l.a)(n)&&n-parseFloat(n)+1>=0}},"/BcF":function(n,e){n.exports={nLine truncated
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{"+/L5":function(n,e,t){var l=t("t1UP").isCustomProperty,o=t("vd7W").TYPE,i=t("4njK").mode,r=o.Ident,a=o.Hash,u=o.Colon,s=o.Semicolon,d=o.Delim,c=33,p=35,f=36,h=38,m=42,v=43,g=47;function b(n){return this.Raw(n,i.exclamationMarkOrSemicolon,!0)}function _(n){return this.Raw(n,i.exclamationMarkOrSemicolon,!1)}function y(){var n=this.scanner.tokenIndex,e=this.Value();return"Raw"!==e.type&&!1===this.scanner.eof&&this.scanner.tokenType!==s&&!1===this.scanner.isDelim(c)&&!1===this.scanner.isBalanceEdge(n)&&this.error(),e}function C(){var n=this.scanner.tokenStart;if(this.scanner.tokenType===d)switch(this.scanner.source.charCodeAt(this.scanner.tokenStart)){case m:case f:case v:case p:case h:this.scanner.next();break;case g:this.scanner.next(),this.scanner.isDelim(g)&&this.scanner.next()}return this.eat(this.scanner.tokenType===a?a:r),this.scanner.substrToCursor(n)}function w(){this.eat(d),this.scanner.skipSC();var n=this.consume(r);return"important"===n||n}n.exports={name:"Declaration",structure:{important:[Boolean,String],property:String,value:["Value","Raw"]},parse:function(){var n,e=this.scanner.tokenStart,t=this.scanner.tokenIndex,o=C.call(this),i=l(o),r=i?this.parseCustomProperty:this.parseValue,a=i?_:b,d=!1;return this.scanner.skipSC(),this.eat(u),i||this.scanner.skipSC(),n=r?this.parseWithFallback(y,a):a.call(this,this.scanner.tokenIndex),this.scanner.isDelim(c)&&(d=w.call(this),this.scanner.skipSC()),!1===this.scanner.eof&&this.scanner.tokenType!==s&&!1===this.scanner.isBalanceEdge(t)&&this.error(),{type:"Declaration",loc:this.getLocation(e,this.scanner.tokenStart),important:d,property:o,value:n}},generate:function(n){this.chunk(n.property),this.chunk(":"),this.node(n.value),n.important&&this.chunk(!0===n.important?"!important":"!"+n.important)},walkContext:"declaration"}},"+Kd2":function(n,e,t){var l=t("vd7W").TYPE,o=t("4njK").mode,i=l.Comma;n.exports=function(){var n=this.createList();return this.scanner.skipSC(),n.push(this.Identifier()),this.scanner.skipSC(),this.scanner.tokenType===i&&(n.push(this.Operator()),n.push(this.parseCustomProperty?this.Value(null):this.Raw(this.scanner.tokenIndex,o.exclamationMarkOrSemicolon,!1))),n}},"+gEr":function(n,e,t){"use strict";t.d(e,"a",(function(){return r})),t.d(e,"b",(function(){return a}));var l=t("mrSG"),o=t("MGBS"),i=t("zotm"),r={leading:!0,trailing:!1};function a(n,e){return void 0===e&&(e=r),function(t){return t.lift(new u(n,e.leading,e.trailing))}}var u=function(){function n(n,e,t){this.durationSelector=n,this.leading=e,this.trailing=t}return n.prototype.call=function(n,e){return e.subscribe(new s(n,this.durationSelector,this.leading,this.trailing))},n}(),s=function(n){function e(e,t,l,o){var i=n.call(this,e)||this;return i.destination=e,i.durationSelector=t,i._leading=l,i._trailing=o,i._hasValue=!1,i}return l.c(e,n),e.prototype._next=function(n){this._hasValue=!0,this._sendValue=n,this._throttled||(this._leading?this.send():this.throttle(n))},e.prototype.send=function(){var n=this._sendValue;this._hasValue&&(this.destination.next(n),this.throttle(n)),this._hasValue=!1,this._sendValue=null},e.prototype.throttle=function(n){var e=this.tryDurationSelector(n);e&&this.add(this._throttled=Object(i.a)(this,e))},e.prototype.tryDurationSelector=function(n){try{return this.durationSelector(n)}catch(e){return this.destination.error(e),null}},e.prototype.throttlingDone=function(){var n=this._throttled,e=this._trailing;n&&n.unsubscribe(),this._throttled=null,e&&this.send()},e.prototype.notifyNext=function(n,e,t,l,o){this.throttlingDone()},e.prototype.notifyComplete=function(){this.throttlingDone()},e}(o.a)},"+ryv":function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var l=t("CcnG");e.HotkeyOptions=new l.InjectionToken("HotkeyOptions")},"+tJ4":function(n,e,t){"use strict";t.d(e,"a",(function(){return l}));var l=function(n){return function(e){for(var t=0,l=n.length;t<l&&!e.closed;t++)e.next(n[t]);e.complete()}}},"+umK":function(n,e,t){"use strict";function l(){}t.d(e,"a",(function(){return l}))},"/+5V":function(n,e){function t(n){function e(n){return null!==n&&("Type"===n.type||"Property"===n.type||"Keyword"===n.type)}var t=null;return null!==this.matched&&function l(o){if(Array.isArray(o.match)){for(var i=0;i<o.match.length;i++)if(l(o.match[i]))return e(o.syntax)&&t.unshift(o.syntax),!0}else if(o.node===n)return t=e(o.syntax)?[o.syntax]:[],!0;return!1}(this.matched),t}function l(n,e,l){var o=t.call(n,e);return null!==o&&o.some(l)}n.exports={getTrace:t,isType:function(n,e){return l(this,n,(function(n){return"Type"===n.type&&n.name===e}))},isProperty:function(n,e){return l(this,n,(function(n){return"Property"===n.type&&n.name===e}))},isKeyword:function(n){return l(this,n,(function(n){return"Keyword"===n.type}))}}},"/21U":function(n,e,t){"use strict";t.d(e,"a",(function(){return o}));var l=t("isby");function o(n){return!Object(l.a)(n)&&n-parseFloat(n)+1>=0}},"/BcF":function(n,e){n.exports={nLine truncated
@@ -1 +1 @@
{"version":3,"sources":["./node_modules/css-tree/lib/syntax/node/Declaration.js","./node_modules/css-tree/lib/syntax/function/var.js","./node_modules/rxjs/_esm5/internal/operators/throttle.js.pre-build-optimizer.js","./node_modules/angular2-hotkeys/src/hotkey.options.js","./node_modules/rxjs/_esm5/internal/util/subscribeToArray.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/noop.js.pre-build-optimizer.js","./node_modules/css-tree/lib/lexer/trace.js","./node_modules/rxjs/_esm5/internal/util/isNumeric.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/Selector.js","./node_modules/rxjs/_esm5/internal/operators/withLatestFrom.js.pre-build-optimizer.js","./node_modules/xterm/lib/xterm.js","./node_modules/rxjs/_esm5/internal/util/isPromise.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/sampleTime.js.pre-build-optimizer.js","./node_modules/css-tree/lib/lexer/generic-an-plus-b.js","./node_modules/rxjs/_esm5/internal/observable/from.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/Value.js","./node_modules/rxjs/_esm5/internal/operators/skipUntil.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/skip.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/timeout.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/skipLast.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/switchMap.js.pre-build-optimizer.js","./node_modules/css-tree/lib/common/SyntaxError.js","./node_modules/rxjs/_esm5/internal/util/canReportError.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/BehaviorSubject.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/isFunction.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/AttributeSelector.js","./node_modules/css-tree/lib/lexer/generic-urange.js","./node_modules/rxjs/_esm5/internal/operators/finalize.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/isArrayLike.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/pseudo/common/selectorList.js","./node_modules/raven-js/vendor/md5/md5.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/exhaust.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/MediaQuery.js","./node_modules/rxjs/_esm5/internal/operators/publishBehavior.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/TimeoutError.js.pre-build-optimizer.js","./node_modules/css-tree/lib/tokenizer/char-code-definitions.js","./node_modules/rxjs/_esm5/internal/util/EmptyError.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/dematerialize.js.pre-build-optimizer.js","./node_modules/css-tree/lib/walker/create.js","./node_modules/raven-js/vendor/TraceKit/tracekit.js.pre-build-optimizer.js","./node_modules/uuid/lib/rng-browser.js","./node_modules/css-tree/lib/syntax/node/Raw.js","./node_modules/css-tree/lib/syntax/node/index.js","./node_modules/rxjs/_esm5/internal/operators/timestamp.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/retry.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/Notification.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/map.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/count.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/StyleSheet.js","./node_modules/rxjs/_esm5/internal/operators/exhaustMap.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/Observer.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/Observable.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/toSubscriber.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/atrule/index.js","./node_modules/rxjs/_esm5/internal/operators/timeInterval.js.pre-build-optimizer.js","./node_modules/create-point-cb/dist/bundle.js","./node_modules/css-tree/lib/syntax/scope/default.js","./node_modules/rxjs/_esm5/internal/observable/using.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/scope/index.js","../node_modules/xterm-addon-fit/lib/xterm-addon-fit.js","./node_modules/css-tree/lib/syntax/config/mix.js","./node_modules/rxjs/_esm5/internal/util/ObjectUnsubscribedError.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/Combinator.js","./node_modules/css-tree/lib/common/TokenStream.js","./node_modules/rxjs/_esm5/internal/observable/zip.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/HexColor.js","./node_modules/rxjs/_esm5/internal/operators/catchError.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/observable/SubscribeOnObservable.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/subscribeOn.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/throttleTime.js.pre-build-optimizer.js","./node_modules/raven-js/src/console.js.pre-build-optimizer.js","./node_moduleLine truncated
{"version":3,"sources":["./node_modules/css-tree/lib/syntax/node/Declaration.js","./node_modules/css-tree/lib/syntax/function/var.js","./node_modules/rxjs/_esm5/internal/operators/throttle.js.pre-build-optimizer.js","./node_modules/angular2-hotkeys/src/hotkey.options.js","./node_modules/rxjs/_esm5/internal/util/subscribeToArray.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/noop.js.pre-build-optimizer.js","./node_modules/css-tree/lib/lexer/trace.js","./node_modules/rxjs/_esm5/internal/util/isNumeric.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/Selector.js","./node_modules/rxjs/_esm5/internal/operators/withLatestFrom.js.pre-build-optimizer.js","./node_modules/xterm/lib/xterm.js","./node_modules/rxjs/_esm5/internal/util/isPromise.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/sampleTime.js.pre-build-optimizer.js","./node_modules/css-tree/lib/lexer/generic-an-plus-b.js","./node_modules/rxjs/_esm5/internal/observable/from.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/Value.js","./node_modules/rxjs/_esm5/internal/operators/skipUntil.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/skip.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/timeout.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/skipLast.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/switchMap.js.pre-build-optimizer.js","./node_modules/css-tree/lib/common/SyntaxError.js","./node_modules/rxjs/_esm5/internal/util/canReportError.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/BehaviorSubject.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/isFunction.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/AttributeSelector.js","./node_modules/css-tree/lib/lexer/generic-urange.js","./node_modules/rxjs/_esm5/internal/operators/finalize.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/isArrayLike.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/pseudo/common/selectorList.js","./node_modules/raven-js/vendor/md5/md5.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/exhaust.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/MediaQuery.js","./node_modules/rxjs/_esm5/internal/operators/publishBehavior.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/TimeoutError.js.pre-build-optimizer.js","./node_modules/css-tree/lib/tokenizer/char-code-definitions.js","./node_modules/rxjs/_esm5/internal/util/EmptyError.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/dematerialize.js.pre-build-optimizer.js","./node_modules/css-tree/lib/walker/create.js","./node_modules/raven-js/vendor/TraceKit/tracekit.js.pre-build-optimizer.js","./node_modules/uuid/lib/rng-browser.js","./node_modules/css-tree/lib/syntax/node/Raw.js","./node_modules/css-tree/lib/syntax/node/index.js","./node_modules/rxjs/_esm5/internal/operators/timestamp.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/retry.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/Notification.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/map.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/count.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/StyleSheet.js","./node_modules/rxjs/_esm5/internal/operators/exhaustMap.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/Observer.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/Observable.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/util/toSubscriber.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/atrule/index.js","./node_modules/rxjs/_esm5/internal/operators/timeInterval.js.pre-build-optimizer.js","./node_modules/create-point-cb/dist/bundle.js","./node_modules/css-tree/lib/syntax/scope/default.js","./node_modules/rxjs/_esm5/internal/observable/using.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/scope/index.js","../node_modules/xterm-addon-fit/lib/xterm-addon-fit.js","./node_modules/css-tree/lib/syntax/config/mix.js","./node_modules/rxjs/_esm5/internal/util/ObjectUnsubscribedError.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/Combinator.js","./node_modules/css-tree/lib/common/TokenStream.js","./node_modules/rxjs/_esm5/internal/observable/zip.js.pre-build-optimizer.js","./node_modules/css-tree/lib/syntax/node/HexColor.js","./node_modules/rxjs/_esm5/internal/operators/catchError.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/observable/SubscribeOnObservable.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/subscribeOn.js.pre-build-optimizer.js","./node_modules/rxjs/_esm5/internal/operators/throttleTime.js.pre-build-optimizer.js","./node_modules/raven-js/src/console.js.pre-build-optimizer.js","./node_moduleLine truncated
+9 -13
View File
@@ -31,7 +31,6 @@ import zipfile
import asyncio
import aiofiles
from concurrent import futures
from async_generator import async_generator, yield_
from zipfile import (structCentralDir, structEndArchive64, structEndArchive, structEndArchive64Locator,
stringCentralDir, stringEndArchive64, stringEndArchive, stringEndArchive64Locator)
@@ -162,7 +161,6 @@ class ZipFile(zipfile.ZipFile):
self._comment = comment
self._didModify = True
@async_generator
async def data_generator(self, path):
async with aiofiles.open(path, "rb") as f:
@@ -170,7 +168,7 @@ class ZipFile(zipfile.ZipFile):
part = await f.read(self._chunksize)
if not part:
break
await yield_(part)
yield part
return
async def _run_in_executor(self, task, *args, **kwargs):
@@ -181,14 +179,13 @@ class ZipFile(zipfile.ZipFile):
loop = asyncio.get_event_loop()
return await loop.run_in_executor(futures.ThreadPoolExecutor(max_workers=1), task, *args, **kwargs)
@async_generator
async def _stream(self):
for kwargs in self.paths_to_write:
async for chunk in self._write(**kwargs):
await yield_(chunk)
yield chunk
for chunk in self._close():
await yield_(chunk)
yield chunk
def write(self, filename, arcname=None, compress_type=None):
"""
@@ -215,7 +212,6 @@ class ZipFile(zipfile.ZipFile):
yield data
return self.write_iter(arcname, _iterable(), compress_type=compress_type)
@async_generator
async def _write(self, filename=None, iterable=None, arcname=None, compress_type=None):
"""
Put the bytes from filename into the archive under the name `arcname`.
@@ -272,7 +268,7 @@ class ZipFile(zipfile.ZipFile):
zinfo.CRC = 0
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
await yield_(self.fp.write(zinfo.FileHeader(False)))
yield self.fp.write(zinfo.FileHeader(False))
return
cmpr = _get_compressor(zinfo.compress_type)
@@ -282,7 +278,7 @@ class ZipFile(zipfile.ZipFile):
zinfo.compress_size = compress_size = 0
# Compressed size can be larger than uncompressed size
zip64 = self._allowZip64 and zinfo.file_size * 1.05 > zipfile.ZIP64_LIMIT
await yield_(self.fp.write(zinfo.FileHeader(zip64)))
yield self.fp.write(zinfo.FileHeader(zip64))
file_size = 0
if filename:
@@ -292,7 +288,7 @@ class ZipFile(zipfile.ZipFile):
if cmpr:
buf = await self._run_in_executor(cmpr.compress, buf)
compress_size = compress_size + len(buf)
await yield_(self.fp.write(buf))
yield self.fp.write(buf)
else: # we have an iterable
for buf in iterable:
file_size = file_size + len(buf)
@@ -300,12 +296,12 @@ class ZipFile(zipfile.ZipFile):
if cmpr:
buf = await self._run_in_executor(cmpr.compress, buf)
compress_size = compress_size + len(buf)
await yield_(self.fp.write(buf))
yield self.fp.write(buf)
if cmpr:
buf = cmpr.flush()
compress_size = compress_size + len(buf)
await yield_(self.fp.write(buf))
yield self.fp.write(buf)
zinfo.compress_size = compress_size
else:
zinfo.compress_size = file_size
@@ -317,7 +313,7 @@ class ZipFile(zipfile.ZipFile):
if compress_size > zipfile.ZIP64_LIMIT:
raise RuntimeError('Compressed size larger than uncompressed size')
await yield_(self.fp.write(zinfo.DataDescriptor()))
yield self.fp.write(zinfo.DataDescriptor())
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
+2 -2
View File
@@ -23,8 +23,8 @@
# or negative for a release candidate or beta (after the base version
# number has been incremented)
__version__ = "2.2.8"
__version_info__ = (2, 2, 8, 0)
__version__ = "2.2.9"
__version_info__ = (2, 2, 9, 0)
if "dev" in __version__:
try:
+1 -3
View File
@@ -1,12 +1,10 @@
yarl==1.3.0 # yarl 1.4+ requires Python 3.6+ (needed by aiohttp and aiohttp-cors)
jsonschema==3.2.0; python_version >= '3.8' # pyup: ignore
jsonschema==2.6.0; python_version < '3.8' # pyup: ignore
aiohttp==3.6.2
aiohttp-cors==0.7.0
aiofiles==0.4.0
async_generator>=1.10
Jinja2>=2.7.3
raven>=5.23.0
sentry-sdk>=0.14.4
psutil==5.6.6
async-timeout==3.0.1
distro>=1.3.0
+2 -2
View File
@@ -61,7 +61,8 @@ setup(
include_package_data=True,
zip_safe=False,
platforms="any",
python_requires='>=3.5.3',
python_requires='>=3.6.0',
setup_requires=["setuptools>=17.1"],
classifiers=[
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
@@ -74,7 +75,6 @@ setup(
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",