diff --git a/CHANGELOG b/CHANGELOG index ad5b3aba..a5321a44 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,27 @@ # Change Log +## 2.2.6 26/03/2020 + +* Remove --local when starting Docker dev server. +* Release 2020.1.0-alpha.1 +* Monitor ubrige processes. +* Add Xvnc command to the VNC servers list. Fixes #172 +* Allow controller to reconnect to compute if communication is lost. Ref #1634 +* Improvement of support for docker USER directive. Fixes #1727. +* Fix cannot delete Dynamips router the content of the "usage" field. Fixes https://github.com/GNS3/gns3-gui/issues/2947 +* Prevent locked drawings to be deleted. Fixes https://github.com/GNS3/gns3-gui/issues/2948 +* Fix issues with empty project variables. Fixes https://github.com/GNS3/gns3-gui/issues/2941 +* Upgrade psutil to version 5.6.6 due to CVE-2019-18874 https://github.com/advisories/GHSA-qfc5-mcwq-26q8 +* Remove 'format=raw' from the Qemu options of the disk interfaces. Ref #1699 +* Allocate application IDs for IOU nodes on the controller. An application ID is used by IOU to generate its interface Mac addresses. They must be unique across all opened projects sharing the same computes to avoid Mac address collisions. +* Require VirtualBox >= 6.0 on AMD and >= 6.1 on Intel processors (for GNS3 VM only). Fixes #1610 +* Add nvme disk interface and fix scsi disk interface for Qemu VMs. +* Disallow using "legacy networking mode" with Qemu >= 2.9.0 +* Add latest Qemu nic models. +* Attempt to fix error when loading wmi module. Fixes #1712 +* Handle "aborted" state for VirtualBox VMs. Fixes #1702 +* Change how Hyper-V VMs are found. Ref #1612 + ## 2.2.5 09/01/2020 * No changes diff --git a/Dockerfile b/Dockerfile index 4b176018..118feb61 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,6 @@ RUN apt-get update && apt-get install -y \ python3-pip \ python3-dev \ qemu-system-x86 \ - qemu-system-arm \ qemu-kvm \ libvirt-bin \ x11vnc @@ -33,4 +32,4 @@ RUN pip3 install -r /server/requirements.txt EXPOSE 3080 -CMD python3 -m gns3server --local +CMD python3 -m gns3server diff --git a/gns3server/appliances/cisco-2691.gns3a b/gns3server/appliances/cisco-2691.gns3a index f0bce68a..e678c81e 100644 --- a/gns3server/appliances/cisco-2691.gns3a +++ b/gns3server/appliances/cisco-2691.gns3a @@ -11,7 +11,7 @@ "maintainer": "GNS3 Team", "maintainer_email": "developers@gns3.net", "dynamips": { - "platform": "c3600", + "platform": "c2691", "ram": 192, "nvram": 256, "startup_config": "ios_base_startup-config.txt", diff --git a/gns3server/appliances/cisco-ise.gns3a b/gns3server/appliances/cisco-ise.gns3a index 5c9a0016..2f3876f9 100644 --- a/gns3server/appliances/cisco-ise.gns3a +++ b/gns3server/appliances/cisco-ise.gns3a @@ -7,7 +7,7 @@ "documentation_url": "http://www.cisco.com/c/en/us/support/security/identity-services-engine/tsd-products-support-series-home.html", "product_name": "Identity Services Engine", "product_url": "http://www.cisco.com/c/en/us/products/security/identity-services-engine/index.html", - "registry_version": 3, + "registry_version": 4, "status": "experimental", "maintainer": "GNS3 Team", "maintainer_email": "developers@gns3.net", @@ -15,9 +15,10 @@ "symbol": "cisco-ise.svg", "port_name_format": "GigabitEthernet{0}", "qemu": { + "cpus": 2, "adapter_type": "e1000", - "adapters": 2, - "ram": 4096, + "adapters": 6, + "ram": 8192, "hda_disk_interface": "ide", "arch": "x86_64", "console_type": "vnc", @@ -26,12 +27,33 @@ "options": "-smp 2 -smbios type=1,product=KVM" }, "images": [ + { + "filename": "ise-2.7.0.356.SPA.x86_64.iso", + "version": "2.7.0.356", + "md5sum": "efbc831bf05513e4df8695eb3a362921", + "filesize": 9184415744, + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.7.0" + }, + { + "filename": "ise-2.6.0.156.SPA.x86_64.iso", + "version": "2.6.0.156", + "md5sum": "296e65b662821269ad67dd3dea8804d9", + "filesize": 8618913792, + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.6.0" + }, { "filename": "ise-2.4.0.357.SPA.x86_64.iso", "version": "2.4.0.357", - "md5sum": "766945618a0ff35f6c720b3bc4b46bfb", + "md5sum": "7f32a28f8d95c7525885786a6556913e", "filesize": 8326062080, "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.4.0" + }, + { + "filename": "ise-2.3.0.298.SPA.x86_64.iso", + "version": "2.3.0.298", + "md5sum": "da98d1a34f6b11d63da0f29bd5ef9caf", + "filesize": 8174278656, + "download_url": "https://software.cisco.com/download/home/283801620/type/283802505/release/2.3.0" }, { "filename": "ise-2.2.0.470.SPA.x86_64.iso", @@ -71,12 +93,33 @@ } ], "versions": [ + { + "name": "2.7.0.356", + "images": { + "hda_disk_image": "empty200G.qcow2", + "cdrom_image": "ise-2.7.0.356.SPA.x86_64.iso" + } + }, + { + "name": "2.6.0.156", + "images": { + "hda_disk_image": "empty200G.qcow2", + "cdrom_image": "ise-2.6.0.156.SPA.x86_64.iso" + } + }, { "name": "2.4.0.357", "images": { "hda_disk_image": "empty200G.qcow2", "cdrom_image": "ise-2.4.0.357.SPA.x86_64.iso" } + }, + { + "name": "2.3.0.298", + "images": { + "hda_disk_image": "empty200G.qcow2", + "cdrom_image": "ise-2.3.0.298.SPA.x86_64.iso" + } }, { "name": "2.2.0.470", diff --git a/gns3server/appliances/cisco-nxosv9k.gns3a b/gns3server/appliances/cisco-nxosv9k.gns3a index acf4da38..3557a6d6 100644 --- a/gns3server/appliances/cisco-nxosv9k.gns3a +++ b/gns3server/appliances/cisco-nxosv9k.gns3a @@ -25,7 +25,21 @@ "kvm": "require" }, "images": [ - { + { + "filename": "nexus9500v.9.3.3.qcow2", + "version": "9500v 9.3.3", + "md5sum": "7230c944041fdaa0e1b18cecccbc9a32", + "filesize": 1714159616, + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.3(3)" + }, + { + "filename": "nexus9300v.9.3.3.qcow2", + "version": "9300v 9.3.3", + "md5sum": "8e9a7c4815907ef47d850623f77042e2", + "filesize": 1714225152, + "download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.3(3)" + }, + { "filename": "nxosv.9.3.1.qcow2", "version": "9.3.1", "md5sum": "148fd38cb1ff78df2883f844e172fad9", @@ -134,6 +148,20 @@ } ], "versions": [ + { + "name": "9500v 9.3.3", + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nexus9500v.9.3.3.qcow2" + } + }, + { + "name": "9300v 9.3.3", + "images": { + "bios_image": "OVMF-20160813.fd", + "hda_disk_image": "nexus9300v.9.3.3.qcow2" + } + }, { "name": "9.3.1", "images": { diff --git a/gns3server/appliances/f5-bigip.gns3a b/gns3server/appliances/f5-bigip.gns3a index efaf8464..412a5f00 100644 --- a/gns3server/appliances/f5-bigip.gns3a +++ b/gns3server/appliances/f5-bigip.gns3a @@ -27,6 +27,13 @@ "options": "-smp 2 -cpu host" }, "images": [ + { + "filename": "BIGIP-14.1.2.3-0.0.5.qcow2", + "version": "14.1.2.3", + "md5sum": "356520eedb615c93e985474f2b2ec603", + "filesize": 5036834816, + "download_url": "https://downloads.f5.com" + }, { "filename": "BIGIP-14.0.0.3-0.0.4.qcow2", "version": "14.0.0 HF3", @@ -142,6 +149,13 @@ } ], "versions": [ + { + "name": "14.1.2.3", + "images": { + "hda_disk_image": "BIGIP-14.1.2.3-0.0.5.qcow2", + "hdb_disk_image": "empty100G.qcow2" + } + }, { "name": "14.0.0 HF3", "images": { diff --git a/gns3server/appliances/mikrotik-chr.gns3a b/gns3server/appliances/mikrotik-chr.gns3a index bd4f2e4a..e765be2a 100644 --- a/gns3server/appliances/mikrotik-chr.gns3a +++ b/gns3server/appliances/mikrotik-chr.gns3a @@ -27,6 +27,15 @@ }, "images": [ { + "filename": "chr-7.0beta5.img", + "version": "7.0beta5", + "md5sum": "3c9855f0efdc23df29511c76aee52c95", + "filesize": 67108864, + "download_url": "http://www.mikrotik.com/download", + "direct_download_url": "https://download.mikrotik.com/routeros/7.0beta5/chr-7.0beta5.img.zip", + "compression": "zip" + }, + { "filename": "chr-7.0beta3.img", "version": "7.0beta3", "md5sum": "938c59989df039cb9f33e0da96c22174", @@ -34,8 +43,26 @@ "download_url": "http://www.mikrotik.com/download", "direct_download_url": "https://download.mikrotik.com/routeros/7.0beta3/chr-7.0beta3.img.zip", "compression": "zip" + }, + { + "filename": "chr-6.46.3.img", + "version": "6.46.3", + "md5sum": "72d72c4a585a04eb9ed24ec9e4678486", + "filesize": 67108864, + "download_url": "http://www.mikrotik.com/download", + "direct_download_url": "https://download.mikrotik.com/routeros/6.46.3/chr-6.46.3.img.zip", + "compression": "zip" }, { + "filename": "chr-6.45.8.img", + "version": "6.45.8", + "md5sum": "73cc01e22e0b301dc29416f59ced8a7d", + "filesize": 67108864, + "download_url": "http://www.mikrotik.com/download", + "direct_download_url": "https://download.mikrotik.com/routeros/6.45.8/chr-6.45.8.img.zip", + "compression": "zip" + }, + { "filename": "chr-6.45.6.img", "version": "6.45.6", "md5sum": "e68db699ba23ac7e4fba95b3075c1c6b", @@ -155,10 +182,28 @@ ], "versions": [ { + "name": "7.0beta5", + "images": { + "hda_disk_image": "chr-7.0beta5.img" + } + }, + { "name": "7.0beta3", "images": { "hda_disk_image": "chr-7.0beta3.img" } + }, + { + "name": "6.46.3", + "images": { + "hda_disk_image": "chr-6.46.3.img" + } + }, + { + "name": "6.45.8", + "images": { + "hda_disk_image": "chr-6.45.8.img" + } }, { "name": "6.45.6", diff --git a/gns3server/appliances/openwrt.gns3a b/gns3server/appliances/openwrt.gns3a index de7a750d..744359fd 100644 --- a/gns3server/appliances/openwrt.gns3a +++ b/gns3server/appliances/openwrt.gns3a @@ -21,6 +21,42 @@ "kvm": "allow" }, "images": [ + { + "filename": "openwrt-19.07.1-x86-64-combined-ext4.img", + "version": "19.07.1", + "md5sum": "2d36f48bcc37edf3c5cfc28fed44b533", + "filesize": 285736960, + "download_url": "https://downloads.openwrt.org/releases/19.07.1/targets/x86/64/", + "direct_download_url": "https://downloads.openwrt.org/releases/19.07.1/targets/x86/64/openwrt-19.07.1-x86-64-combined-ext4.img.gz", + "compression": "gzip" + }, + { + "filename": "openwrt-18.06.7-x86-64-combined-ext4.img", + "version": "18.06.7", + "md5sum": "f463f38cccf89e1a2229f74a4c42d3ef", + "filesize": 285736960, + "download_url": "https://downloads.openwrt.org/releases/18.06.7/targets/x86/64/", + "direct_download_url": "https://downloads.openwrt.org/releases/18.06.7/targets/x86/64/openwrt-18.06.7-x86-64-combined-ext4.img.gz", + "compression": "gzip" + }, + { + "filename": "openwrt-19.07.0-x86-64-combined-ext4.img", + "version": "19.07.0", + "md5sum": "cf2a353d10e017b9e71cd3761f7aa724", + "filesize": 285736960, + "download_url": "https://downloads.openwrt.org/releases/19.07.0/targets/x86/64/", + "direct_download_url": "https://downloads.openwrt.org/releases/19.07.0/targets/x86/64/openwrt-19.07.0-x86-64-combined-ext4.img.gz", + "compression": "gzip" + }, + { + "filename": "openwrt-18.06.6-x86-64-combined-ext4.img", + "version": "18.06.6", + "md5sum": "0afeec80ad7e5035f739e0ed0a07fb83", + "filesize": 285736960, + "download_url": "https://downloads.openwrt.org/releases/18.06.6/targets/x86/64/", + "direct_download_url": "https://downloads.openwrt.org/releases/18.06.6/targets/x86/64/openwrt-18.06.6-x86-64-combined-ext4.img.gz", + "compression": "gzip" + }, { "filename": "openwrt-18.06.5-x86-64-combined-ext4.img", "version": "18.06.5", @@ -68,6 +104,30 @@ } ], "versions": [ + { + "name": "19.07.1", + "images": { + "hda_disk_image": "openwrt-19.07.1-x86-64-combined-ext4.img" + } + }, + { + "name": "18.06.7", + "images": { + "hda_disk_image": "openwrt-18.06.7-x86-64-combined-ext4.img" + } + }, + { + "name": "19.07.0", + "images": { + "hda_disk_image": "openwrt-19.07.0-x86-64-combined-ext4.img" + } + }, + { + "name": "18.06.6", + "images": { + "hda_disk_image": "openwrt-18.06.6-x86-64-combined-ext4.img" + } + }, { "name": "18.06.5", "images": { diff --git a/gns3server/compute/docker/docker_vm.py b/gns3server/compute/docker/docker_vm.py index d7d4b0dc..25a9b5e7 100644 --- a/gns3server/compute/docker/docker_vm.py +++ b/gns3server/compute/docker/docker_vm.py @@ -564,12 +564,14 @@ class DockerVM(BaseNode): """ self._display = self._get_free_display_port() - if not (shutil.which("Xtigervnc") or shutil.which("Xvfb") and shutil.which("x11vnc")): - raise DockerError("Please install tigervnc-standalone-server (recommended) or Xvfb + x11vnc before using VNC support") + tigervnc_path = shutil.which("Xtigervnc") or shutil.which("Xvnc") - if shutil.which("Xtigervnc"): + if not (tigervnc_path or shutil.which("Xvfb") and shutil.which("x11vnc")): + raise DockerError("Please install TigerVNC (recommended) or Xvfb + x11vnc before using VNC support") + + if tigervnc_path: with open(os.path.join(self.working_dir, "vnc.log"), "w") as fd: - self._vnc_process = await asyncio.create_subprocess_exec("Xtigervnc", + self._vnc_process = await asyncio.create_subprocess_exec(tigervnc_path, "-geometry", self._console_resolution, "-depth", "16", "-interface", self._manager.port_manager.console_host, @@ -606,8 +608,9 @@ class DockerVM(BaseNode): """ self._display = self._get_free_display_port() - if not (shutil.which("Xtigervnc") or shutil.which("Xvfb") and shutil.which("x11vnc")): - raise DockerError("Please install tigervnc-standalone-server (recommended) or Xvfb + x11vnc before using VNC support") + tigervnc_path = shutil.which("Xtigervnc") or shutil.which("Xvnc") + if not (tigervnc_path or shutil.which("Xvfb") and shutil.which("x11vnc")): + raise DockerError("Please install TigerVNC server (recommended) or Xvfb + x11vnc before using VNC support") await self._start_vnc_process() x11_socket = os.path.join("/tmp/.X11-unix/", "X{}".format(self._display)) await wait_for_file_creation(x11_socket) diff --git a/gns3server/compute/docker/resources/init.sh b/gns3server/compute/docker/resources/init.sh index bc33ea1c..8040d025 100755 --- a/gns3server/compute/docker/resources/init.sh +++ b/gns3server/compute/docker/resources/init.sh @@ -87,9 +87,5 @@ done ifup -a -f # continue normal docker startup -GNS3_CMD="PATH=$OLD_PATH exec" -while test "$#" -gt 0 ; do - GNS3_CMD="${GNS3_CMD} \"${1//\"/\\\"}\"" - shift -done -exec su ${GNS3_USER-root} -p -c "$GNS3_CMD" +eval HOME=$(echo ~${GNS3_USER-root}) +exec su ${GNS3_USER-root} -p -- /gns3/run-cmd.sh "$OLD_PATH" "$@" diff --git a/gns3server/compute/docker/resources/run-cmd.sh b/gns3server/compute/docker/resources/run-cmd.sh new file mode 100755 index 00000000..610d8d53 --- /dev/null +++ b/gns3server/compute/docker/resources/run-cmd.sh @@ -0,0 +1,6 @@ +#!/bin/sh +# run docker startup, first arg is new PATH, remainder is command + +PATH="$1" +shift +exec "$@" diff --git a/gns3server/compute/dynamips/__init__.py b/gns3server/compute/dynamips/__init__.py index c7b35147..a996d5f5 100644 --- a/gns3server/compute/dynamips/__init__.py +++ b/gns3server/compute/dynamips/__init__.py @@ -493,7 +493,7 @@ class Dynamips(BaseManager): await vm.set_sparsemem(False) usage = settings.get("usage") - if usage and usage != vm.usage: + if usage is not None and usage != vm.usage: vm.usage = usage # update the configs if needed diff --git a/gns3server/compute/iou/__init__.py b/gns3server/compute/iou/__init__.py index 028736b7..89d47e3e 100644 --- a/gns3server/compute/iou/__init__.py +++ b/gns3server/compute/iou/__init__.py @@ -25,7 +25,6 @@ import asyncio from ..base_manager import BaseManager from .iou_error import IOUError from .iou_vm import IOUVM -from .utils.application_id import get_next_application_id import logging log = logging.getLogger(__name__) @@ -48,12 +47,7 @@ class IOU(BaseManager): :returns: IOUVM instance """ - async with self._iou_id_lock: - # wait for a node to be completely created before adding a new one - # this is important otherwise we allocate the same application ID - # when creating multiple IOU node at the same time - application_id = get_next_application_id(self.nodes) - node = await super().create_node(*args, application_id=application_id, **kwargs) + node = await super().create_node(*args, **kwargs) return node @staticmethod diff --git a/gns3server/compute/iou/iou_vm.py b/gns3server/compute/iou/iou_vm.py index 9db7c88d..e08357ef 100644 --- a/gns3server/compute/iou/iou_vm.py +++ b/gns3server/compute/iou/iou_vm.py @@ -70,6 +70,10 @@ class IOUVM(BaseNode): super().__init__(name, node_id, project, manager, console=console, console_type=console_type) + log.info('IOU "{name}" [{id}]: assigned with application ID {application_id}'.format(name=self._name, + id=self._id, + application_id=application_id)) + self._iou_process = None self._telnet_server = None self._iou_stdout_file = "" diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py index 88c27d85..6b0a61fa 100644 --- a/gns3server/compute/qemu/qemu_vm.py +++ b/gns3server/compute/qemu/qemu_vm.py @@ -1647,7 +1647,16 @@ class QemuVM(BaseNode): options.extend(["-device", 'ahci,id=ahci{}'.format(disk_index)]) options.extend(["-drive", 'file={},if=none,id=drive{},index={},media=disk'.format(disk, disk_index, disk_index)]) options.extend(["-device", 'ide-drive,drive=drive{},bus=ahci{}.0,id=drive{}'.format(disk_index, disk_index, disk_index)]) - + elif interface == "nvme": + options.extend(["-drive", 'file={},if=none,id=drive{},index={},media=disk'.format(disk, disk_index, disk_index)]) + options.extend(["-device", 'nvme,drive=drive{},serial={}'.format(disk_index, disk_index)]) + elif interface == "scsi": + options.extend(["-device", 'virtio-scsi-pci,id=scsi{}'.format(disk_index)]) + options.extend(["-drive", 'file={},if=none,id=drive{},index={},media=disk'.format(disk, disk_index, disk_index)]) + options.extend(["-device", 'scsi-hd,drive=drive{}'.format(disk_index)]) + #elif interface == "sd": + # options.extend(["-drive", 'file={},id=drive{},index={}'.format(disk, disk_index, disk_index)]) + # options.extend(["-device", 'sd-card,drive=drive{},id=drive{}'.format(disk_index, disk_index, disk_index)]) else: options.extend(["-drive", 'file={},if={},index={},media=disk,id=drive{}'.format(disk, interface, disk_index, disk_index)]) @@ -1723,10 +1732,13 @@ class QemuVM(BaseNode): patched_qemu = False if self._legacy_networking: - version = await self.manager.get_qemu_version(self.qemu_path) - if version and parse_version(version) < parse_version("1.1.0"): - # this is a patched Qemu if version is below 1.1.0 - patched_qemu = True + qemu_version = await self.manager.get_qemu_version(self.qemu_path) + if qemu_version: + if parse_version(qemu_version) >= parse_version("2.9.0"): + raise QemuError("Qemu version 2.9.0 and later doesn't support legacy networking mode") + if parse_version(qemu_version) < parse_version("1.1.0"): + # this is a patched Qemu if version is below 1.1.0 + patched_qemu = True # Each 32 PCI device we need to add a PCI bridge with max 9 bridges pci_devices = 4 + len(self._ethernet_adapters) # 4 PCI devices are use by default by qemu diff --git a/gns3server/compute/virtualbox/virtualbox_vm.py b/gns3server/compute/virtualbox/virtualbox_vm.py index 36070b5a..a1d00597 100644 --- a/gns3server/compute/virtualbox/virtualbox_vm.py +++ b/gns3server/compute/virtualbox/virtualbox_vm.py @@ -279,7 +279,7 @@ class VirtualBoxVM(BaseNode): await self._set_network_options() await self._set_serial_console() else: - raise VirtualBoxError("VirtualBox VM not powered off") + raise VirtualBoxError("VirtualBox VM '{}' is not powered off (current state is '{}')".format(self.name, vm_state)) # check if there is enough RAM to run self.check_available_ram(self.ram) @@ -320,7 +320,8 @@ class VirtualBoxVM(BaseNode): await self._stop_ubridge() await self._stop_remote_console() vm_state = await self._get_vm_state() - if vm_state in ("running", "paused", "stuck"): + log.info("Stopping VirtualBox VM '{name}' [{id}] (current state is {vm_state})".format(name=self.name, id=self.id, vm_state=vm_state)) + if vm_state in ("running", "paused"): if self.on_close == "save_vm_state": # add a guest property to know the VM has been saved @@ -348,7 +349,10 @@ class VirtualBoxVM(BaseNode): result = await self._control_vm("poweroff") self.status = "stopped" log.debug("Stop result: {}".format(result)) + elif vm_state == "aborted": + self.status = "stopped" + if self.status == "stopped": log.info("VirtualBox VM '{name}' [{id}] stopped".format(name=self.name, id=self.id)) await asyncio.sleep(0.5) # give some time for VirtualBox to unlock the VM if self.on_close != "save_vm_state": diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index cae729d4..20132f81 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -481,7 +481,7 @@ class Controller: @property def projects(self): """ - :returns: The dictionary of projects managed by GNS3 + :returns: The dictionary of projects managed by the controller """ return self._projects diff --git a/gns3server/controller/compute.py b/gns3server/controller/compute.py index 419d3e07..1e7c55ac 100644 --- a/gns3server/controller/compute.py +++ b/gns3server/controller/compute.py @@ -448,11 +448,11 @@ class Compute: log.error("Error received on compute WebSocket '{}': {}".format(ws_url, ws.exception())) elif response.type == aiohttp.WSMsgType.CLOSED: pass - self._connected = False break except aiohttp.client_exceptions.ClientResponseError as e: log.error("Client response error received on compute WebSocket '{}': {}".format(ws_url,e)) finally: + self._connected = False log.info("Connection closed to compute WebSocket '{}'".format(ws_url)) # Try to reconnect after 1 second if server unavailable only if not during tests (otherwise we create a ressources usage bomb) diff --git a/gns3server/controller/drawing.py b/gns3server/controller/drawing.py index 4ef324b4..de929b2f 100644 --- a/gns3server/controller/drawing.py +++ b/gns3server/controller/drawing.py @@ -16,7 +16,6 @@ # along with this program. If not, see . import hashlib -import asyncio import base64 import uuid import re diff --git a/gns3server/controller/gns3vm/hyperv_gns3_vm.py b/gns3server/controller/gns3vm/hyperv_gns3_vm.py index a869cf7d..0558b1b4 100644 --- a/gns3server/controller/gns3vm/hyperv_gns3_vm.py +++ b/gns3server/controller/gns3vm/hyperv_gns3_vm.py @@ -21,9 +21,6 @@ import asyncio import psutil import ipaddress -if sys.platform.startswith("win"): - import wmi - from .base_gns3_vm import BaseGNS3VM from .gns3_vm_error import GNS3VMError log = logging.getLogger(__name__) @@ -47,6 +44,7 @@ class HyperVGNS3VM(BaseGNS3VM): self._conn = None self._vm = None self._management = None + self._wmi = None def _check_requirements(self): """ @@ -64,8 +62,12 @@ class HyperVGNS3VM(BaseGNS3VM): raise GNS3VMError("Hyper-V with nested virtualization is only supported on Windows 10 Anniversary Update (build 10.0.14393) or later") try: - conn = wmi.WMI() - except wmi.x_wmi as e: + import pythoncom + pythoncom.CoInitialize() + import wmi + self._wmi = wmi + conn = self._wmi.WMI() + except self._wmi.x_wmi as e: raise GNS3VMError("Could not connect to WMI: {}".format(e)) if not conn.Win32_ComputerSystem()[0].HypervisorPresent: @@ -86,8 +88,8 @@ class HyperVGNS3VM(BaseGNS3VM): self._check_requirements() try: - self._conn = wmi.WMI(namespace=r"root\virtualization\v2") - except wmi.x_wmi as e: + self._conn = self._wmi.WMI(namespace=r"root\virtualization\v2") + except self._wmi.x_wmi as e: raise GNS3VMError("Could not connect to WMI: {}".format(e)) if not self._conn.Msvm_VirtualSystemManagementService(): @@ -182,10 +184,10 @@ class HyperVGNS3VM(BaseGNS3VM): vms = [] try: - for vm in self._conn.Msvm_VirtualSystemSettingData(): - if vm.VirtualSystemType == "Microsoft:Hyper-V:System:Realized": + for vm in self._conn.Msvm_ComputerSystem(): + if vm.ElementName != self._management.SystemName: vms.append({"vmname": vm.ElementName}) - except wmi.x_wmi as e: + except self._wmi.x_wmi as e: raise GNS3VMError("Could not list Hyper-V VMs: {}".format(e)) return vms @@ -194,7 +196,7 @@ class HyperVGNS3VM(BaseGNS3VM): Gets the WMI object. """ - return wmi.WMI(moniker=path.replace('\\', '/')) + return self._wmi.WMI(moniker=path.replace('\\', '/')) async def _set_state(self, state): """ diff --git a/gns3server/controller/gns3vm/virtualbox_gns3_vm.py b/gns3server/controller/gns3vm/virtualbox_gns3_vm.py index c4fc1414..8561fe5d 100644 --- a/gns3server/controller/gns3vm/virtualbox_gns3_vm.py +++ b/gns3server/controller/gns3vm/virtualbox_gns3_vm.py @@ -23,6 +23,8 @@ import socket from .base_gns3_vm import BaseGNS3VM from .gns3_vm_error import GNS3VMError +from gns3server.utils import parse_version +from gns3server.utils.asyncio import wait_run_in_executor from ...compute.virtualbox import ( VirtualBox, @@ -38,6 +40,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM): self._engine = "virtualbox" super().__init__(controller) + self._system_properties = {} self._virtualbox_manager = VirtualBox() async def _execute(self, subcommand, args, timeout=60): @@ -63,6 +66,42 @@ class VirtualBoxGNS3VM(BaseGNS3VM): return value.strip('"') return "unknown" + async def _get_system_properties(self): + """ + Returns the VM state (e.g. running, paused etc.) + + :returns: state (string) + """ + + properties = await self._execute("list", ["systemproperties"]) + for prop in properties.splitlines(): + try: + name, value = prop.split(':', 1) + except ValueError: + continue + self._system_properties[name.strip()] = value.strip() + + async def _check_requirements(self): + """ + Checks if the GNS3 VM can run on VirtualBox + """ + + if not self._system_properties: + await self._get_system_properties() + if "API version" not in self._system_properties: + raise VirtualBoxError("Can't access to VirtualBox API version:\n{}".format(self._system_properties)) + from cpuinfo import get_cpu_info + cpu_info = await wait_run_in_executor(get_cpu_info) + vendor_id = cpu_info['vendor_id'] + if vendor_id == "GenuineIntel": + if parse_version(self._system_properties["API version"]) < parse_version("6_1"): + raise VirtualBoxError("VirtualBox version 6.1 or above is required to run the GNS3 VM with nested virtualization enabled on Intel processors") + elif vendor_id == "AuthenticAMD": + if parse_version(self._system_properties["API version"]) < parse_version("6_0"): + raise VirtualBoxError("VirtualBox version 6.0 or above is required to run the GNS3 VM with nested virtualization enabled on AMD processors") + else: + log.warning("Could not determine CPU vendor: {}".format(vendor_id)) + async def _look_for_interface(self, network_backend): """ Look for an interface with a specific network backend. @@ -173,13 +212,16 @@ class VirtualBoxGNS3VM(BaseGNS3VM): List all VirtualBox VMs """ - return (await self._virtualbox_manager.list_vms()) + await self._check_requirements() + return await self._virtualbox_manager.list_vms() async def start(self): """ Start the GNS3 VM. """ + await self._check_requirements() + # get a NAT interface number nat_interface_number = await self._look_for_interface("nat") if nat_interface_number < 0: diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index 29f9e405..29ab0842 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -38,6 +38,7 @@ from .topology import project_to_topology, load_topology from .udp_link import UDPLink from ..config import Config from ..utils.path import check_path_allowed, get_default_project_directory +from ..utils.application_id import get_next_application_id from ..utils.asyncio.pool import Pool from ..utils.asyncio import locking from ..utils.asyncio import aiozipstream @@ -126,6 +127,8 @@ class Project: assert self._status != "closed" self.dump() + self._iou_id_lock = asyncio.Lock() + def emit_notification(self, action, event): """ Emit a notification to all clients using this project. @@ -516,17 +519,7 @@ class Project: node = await self.add_node(compute, name, node_id, node_type=node_type, **template) return node - @open_required - async def add_node(self, compute, name, node_id, dump=True, node_type=None, **kwargs): - """ - Create a node or return an existing node - - :param dump: Dump topology to disk - :param kwargs: See the documentation of node - """ - - if node_id in self._nodes: - return self._nodes[node_id] + async def _create_node(self, compute, name, node_id, node_type=None, **kwargs): node = Node(self, compute, name, node_id=node_id, node_type=node_type, **kwargs) if compute not in self._project_created_on_compute: @@ -547,10 +540,39 @@ class Project: data["variables"] = self._variables await compute.post("/projects", data=data) - self._project_created_on_compute.add(compute) + await node.create() self._nodes[node.id] = node + + return node + + @open_required + async def add_node(self, compute, name, node_id, dump=True, node_type=None, **kwargs): + """ + Create a node or return an existing node + + :param dump: Dump topology to disk + :param kwargs: See the documentation of node + """ + + if node_id in self._nodes: + return self._nodes[node_id] + + if node_type == "iou": + async with self._iou_id_lock: + # wait for a IOU node to be completely created before adding a new one + # this is important otherwise we allocate the same application ID (used + # to generate MAC addresses) when creating multiple IOU node at the same time + if "properties" in kwargs.keys(): + # allocate a new application id for nodes loaded from the project + kwargs.get("properties")["application_id"] = get_next_application_id(self._controller.projects, compute) + elif "application_id" not in kwargs.keys() and not kwargs.get("properties"): + # allocate a new application id for nodes added to the project + kwargs["application_id"] = get_next_application_id(self._controller.projects, compute) + node = await self._create_node(compute, name, node_id, node_type, **kwargs) + else: + node = await self._create_node(compute, name, node_id, node_type, **kwargs) self.emit_notification("node.created", node.__json__()) if dump: self.dump() @@ -662,6 +684,8 @@ class Project: @open_required async def delete_drawing(self, drawing_id): drawing = self.get_drawing(drawing_id) + if drawing.locked: + raise aiohttp.web.HTTPConflict(text="Drawing ID {} cannot be deleted because it is locked".format(drawing_id)) del self._drawings[drawing.id] self.dump() self.emit_notification("drawing.deleted", drawing.__json__()) @@ -1102,12 +1126,11 @@ class Project: data['z'] = z data['locked'] = False # duplicated node must not be locked new_node_uuid = str(uuid.uuid4()) - new_node = await self.add_node( - node.compute, - node.name, - new_node_uuid, - node_type=node_type, - **data) + new_node = await self.add_node(node.compute, + node.name, + new_node_uuid, + node_type=node_type, + **data) try: await node.post("/duplicate", timeout=None, data={ "destination_node_id": new_node_uuid diff --git a/gns3server/controller/topology.py b/gns3server/controller/topology.py index 2c1a6b89..8e764472 100644 --- a/gns3server/controller/topology.py +++ b/gns3server/controller/topology.py @@ -171,6 +171,11 @@ def load_topology(path): if "console_type" in node and node["console_type"] is None: node["console_type"] = "none" + # make sure we can open a project with empty variable name + variables = topo.get("variables") + if variables: + topo["variables"] = [var for var in variables if var.get("name")] + try: _check_topology_schema(topo) except aiohttp.web.HTTPConflict as e: diff --git a/gns3server/crash_report.py b/gns3server/crash_report.py index fba90c77..b6fe221d 100644 --- a/gns3server/crash_report.py +++ b/gns3server/crash_report.py @@ -58,7 +58,7 @@ class CrashReport: Report crash to a third party service """ - DSN = "https://19f9932414a74c79b74d5db1ee90af54:550055575371472ab0e71f202cdf196d@sentry.io/38482" + DSN = "https://03a62c6395a54334b0818302138c6555:d7977024b6314ffbaddae057f9bb53b8@sentry.io/38482" if hasattr(sys, "frozen"): cacert = get_resource("cacert.pem") if cacert is not None and os.path.isfile(cacert): diff --git a/gns3server/handlers/api/compute/iou_handler.py b/gns3server/handlers/api/compute/iou_handler.py index 43b1c07f..5238f90c 100644 --- a/gns3server/handlers/api/compute/iou_handler.py +++ b/gns3server/handlers/api/compute/iou_handler.py @@ -58,16 +58,17 @@ class IOUHandler: iou = IOU.instance() vm = await iou.create_node(request.json.pop("name"), - request.match_info["project_id"], - request.json.get("node_id"), - path=request.json.get("path"), - console=request.json.get("console"), - console_type=request.json.get("console_type", "telnet")) + request.match_info["project_id"], + request.json.get("node_id"), + application_id=request.json.get("application_id"), + path=request.json.get("path"), + console=request.json.get("console"), + console_type=request.json.get("console_type", "telnet")) for name, value in request.json.items(): if hasattr(vm, name) and getattr(vm, name) != value: if name == "application_id": - continue # we must ignore this to avoid overwriting the application_id allocated by the IOU manager + continue # we must ignore this to avoid overwriting the application_id allocated by the controller if name == "startup_config_content" and (vm.startup_config_content and len(vm.startup_config_content) > 0): continue if name == "private_config_content" and (vm.private_config_content and len(vm.private_config_content) > 0): diff --git a/gns3server/schemas/iou.py b/gns3server/schemas/iou.py index 84aa5421..a10c96f8 100644 --- a/gns3server/schemas/iou.py +++ b/gns3server/schemas/iou.py @@ -96,7 +96,7 @@ IOU_CREATE_SCHEMA = { }, }, "additionalProperties": False, - "required": ["name", "path"] + "required": ["application_id", "name", "path"] } diff --git a/gns3server/schemas/project.py b/gns3server/schemas/project.py index 23f23ac2..1c4e50d1 100644 --- a/gns3server/schemas/project.py +++ b/gns3server/schemas/project.py @@ -38,7 +38,8 @@ VARIABLES_OBJECT_SCHEMA = { "properties": { "name": { "type": "string", - "description": "Variable name" + "description": "Variable name", + "minLength": 1 }, "value": { "type": "string", diff --git a/gns3server/schemas/qemu_template.py b/gns3server/schemas/qemu_template.py index 514056e9..18e2a284 100644 --- a/gns3server/schemas/qemu_template.py +++ b/gns3server/schemas/qemu_template.py @@ -64,9 +64,9 @@ QEMU_TEMPLATE_PROPERTIES = { "adapter_type": { "description": "QEMU adapter type", "type": "string", - "enum": ["e1000", "i82550", "i82551", "i82557a", "i82557b", "i82557c", "i82558a","i82558b", "i82559a", - "i82559b", "i82559c", "i82559er", "i82562", "i82801", "ne2k_pci", "pcnet", "rtl8139", "virtio", - "virtio-net-pci", "vmxnet3"], + "enum": ["e1000", "e1000-82544gc", "e1000-82545em", "e1000e", "i82550", "i82551", "i82557a", "i82557b", "i82557c", "i82558a", + "i82558b", "i82559a", "i82559b", "i82559c", "i82559er", "i82562", "i82801", "ne2k_pci", "pcnet", "rocker", "rtl8139", + "virtio", "virtio-net-pci", "vmxnet3"], "default": "e1000" }, "mac_address": { @@ -115,7 +115,7 @@ QEMU_TEMPLATE_PROPERTIES = { }, "hda_disk_interface": { "description": "QEMU hda interface", - "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], + "enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], "default": "ide" }, "hdb_disk_image": { @@ -125,7 +125,7 @@ QEMU_TEMPLATE_PROPERTIES = { }, "hdb_disk_interface": { "description": "QEMU hdb interface", - "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], + "enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], "default": "ide" }, "hdc_disk_image": { @@ -135,7 +135,7 @@ QEMU_TEMPLATE_PROPERTIES = { }, "hdc_disk_interface": { "description": "QEMU hdc interface", - "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], + "enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], "default": "ide" }, "hdd_disk_image": { @@ -145,7 +145,7 @@ QEMU_TEMPLATE_PROPERTIES = { }, "hdd_disk_interface": { "description": "QEMU hdd interface", - "enum": ["ide", "sata", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], + "enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"], "default": "ide" }, "cdrom_image": { diff --git a/gns3server/static/web-ui/.gitkeep b/gns3server/static/web-ui/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/gns3server/static/web-ui/3rdpartylicenses.txt b/gns3server/static/web-ui/3rdpartylicenses.txt index 93cdeb96..876bddd2 100644 --- a/gns3server/static/web-ui/3rdpartylicenses.txt +++ b/gns3server/static/web-ui/3rdpartylicenses.txt @@ -93,6 +93,8 @@ THE SOFTWARE. @angular/material/checkbox +@angular/material/chips + @angular/material/core @angular/material/dialog @@ -1792,8 +1794,14 @@ the License, but only in their entirety and only with respect to the Combined Software. +ng-circle-progress +MIT + ng2-file-upload +ngx-childprocess +MIT + ngx-device-detector MIT The MIT License @@ -2674,30 +2682,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -webpack -MIT -Copyright JS Foundation and other contributors - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - zone.js MIT The MIT License diff --git a/gns3server/static/web-ui/index.html b/gns3server/static/web-ui/index.html index 314fbe14..5d17f3c3 100644 --- a/gns3server/static/web-ui/index.html +++ b/gns3server/static/web-ui/index.html @@ -33,9 +33,19 @@ } })(); - + - + + + diff --git a/gns3server/static/web-ui/main.89a8d561ddbdc1d9fa28.js b/gns3server/static/web-ui/main.89a8d561ddbdc1d9fa28.js deleted file mode 100644 index d7ec8204..00000000 --- a/gns3server/static/web-ui/main.89a8d561ddbdc1d9fa28.js +++ /dev/null @@ -1 +0,0 @@ -(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=0}},"/BcF":function(n,e){n.exports={name:"Selector",structure:{children:[["TypeSelector","IdSelector","ClassSelector","AttributeSelector","PseudoClassSelector","PseudoElementSelector","Combinator","WhiteSpace"]]},parse:function(){var n=this.readSequence(this.scope.Selector);return null===this.getFirstListNode(n)&&this.error("Selector is expected"),{type:"Selector",loc:this.getLocationFromList(n),children:n}},generate:function(n){this.children(n)}}},"/PH2":function(n,e,t){"use strict";t.d(e,"a",(function(){return r}));var l=t("mrSG"),o=t("MGBS"),i=t("zotm");function r(){for(var n=[],e=0;e0){var r=i.indexOf(t);-1!==r&&i.splice(r,1)}},e.prototype.notifyComplete=function(){},e.prototype._next=function(n){if(0===this.toRespond.length){var e=[n].concat(this.values);this.project?this._tryProject(e):this.destination.next(e)}},e.prototype._tryProject=function(n){var e;try{e=this.project.apply(this,n)}catch(t){return void this.destination.error(t)}this.destination.next(e)},e}(o.a)},"/WYv":function(n,e,t){"use strict";function l(n){return!!n&&"function"!=typeof n.subscribe&&"function"==typeof n.then}t.d(e,"a",(function(){return l}))},"/ojb":function(n,e,t){"use strict";t.d(e,"a",(function(){return r}));var l=t("mrSG"),o=t("FFOo"),i=t("T1DM");function r(n,e){return void 0===e&&(e=i.a),function(t){return t.lift(new a(n,e))}}var a=function(){function n(n,e){this.period=n,this.scheduler=e}return n.prototype.call=function(n,e){return e.subscribe(new u(n,this.period,this.scheduler))},n}(),u=function(n){function e(e,t,l){var o=n.call(this,e)||this;return o.period=t,o.scheduler=l,o.hasValue=!1,o.add(l.schedule(s,t,{subscriber:o,period:t})),o}return l.c(e,n),e.prototype._next=function(n){this.lastValue=n,this.hasValue=!0},e.prototype.notifyNext=function(){this.hasValue&&(this.hasValue=!1,this.destination.next(this.lastValue))},e}(o.a);function s(n){var e=n.period;n.subscriber.notifyNext(),this.schedule(n,e)}},"/slF":function(n,e,t){var l=t("vd7W").isDigit,o=t("vd7W").cmpChar,i=t("vd7W").TYPE,r=i.Delim,a=i.WhiteSpace,u=i.Comment,s=i.Ident,d=i.Number,c=i.Dimension,p=43,f=45;function h(n,e){return null!==n&&n.type===r&&n.value.charCodeAt(0)===e}function m(n,e,t){for(;null!==n&&(n.type===a||n.type===u);)n=t(++e);return e}function v(n,e,t,o){if(!n)return 0;var i=n.value.charCodeAt(e);if(i===p||i===f){if(t)return 0;e++}for(;ethis.total&&this.destination.next(n)},e}(o.a)},"0zd0":function(n,e,t){"use strict";t.d(e,"a",(function(){return a}));var l=t("T1DM"),o=t("3U0i"),i=t("ceCD"),r=t("XlPw");function a(n,e){return void 0===e&&(e=l.a),Object(i.a)(n,Object(r.a)(new o.a),e)}},"14Nl":function(n,e,t){"use strict";t.d(e,"a",(function(){return r}));var l=t("mrSG"),o=t("FFOo"),i=t("b7mW");function r(n){return function(e){return e.lift(new a(n))}}var a=function(){function n(n){if(this._skipCount=n,this._skipCount<0)throw new i.a}return n.prototype.call=function(n,e){return e.subscribe(0===this._skipCount?new o.a(n):new u(n,this._skipCount))},n}(),u=function(n){function e(e,t){var l=n.call(this,e)||this;return l._skipCount=t,l._count=0,l._ring=new Array(t),l}return l.c(e,n),e.prototype._next=function(n){var e=this._skipCount,t=this._count++;if(to&&(p=u-i+3,u=i-2);for(var f=s;f<=d;f++)f>=0&&f0&&l[f].length>p?"…":"")+l[f].substr(p,o-2)+(l[f].length>p+o-1?"…":""));return[t(s,a),new Array(u+c+2).join("-")+"^",t(a,d)].filter(Boolean).join("\n")}n.exports=function(n,e,t,o,i){var r=l("SyntaxError",n);return r.source=e,r.offset=t,r.line=o,r.column=i,r.sourceFragment=function(n){return a(r,isNaN(n)?0:n)},Object.defineProperty(r,"formattedMessage",{get:function(){return"Parse error: "+r.message+"\n"+a(r,2)}}),r.parseError={offset:t,line:o,column:i},r}},"1fDf":function(n,e,t){"use strict";t.d(e,"a",(function(){return o}));var l=t("FFOo");function o(n){for(;n;){var e=n.destination;if(n.closed||n.isStopped)return!1;n=e&&e instanceof l.a?e:null}return!0}},"26FU":function(n,e,t){"use strict";t.d(e,"a",(function(){return r}));var l=t("mrSG"),o=t("K9Ia"),i=t("8g8A"),r=function(n){function e(e){var t=n.call(this)||this;return t._value=e,t}return l.c(e,n),Object.defineProperty(e.prototype,"value",{get:function(){return this.getValue()},enumerable:!0,configurable:!0}),e.prototype._subscribe=function(e){var t=n.prototype._subscribe.call(this,e);return t&&!t.closed&&e.next(this._value),t},e.prototype.getValue=function(){if(this.hasError)throw this.thrownError;if(this.closed)throw new i.a;return this._value},e.prototype.next=function(e){n.prototype.next.call(this,this._value=e)},e}(o.b)},"2Bdj":function(n,e,t){"use strict";function l(n){return"function"==typeof n}t.d(e,"a",(function(){return l}))},"2Gxe":function(n,e,t){var l=t("vd7W").TYPE,o=l.Ident,i=l.String,r=l.Colon,a=l.LeftSquareBracket,u=l.RightSquareBracket,s=36,d=42,c=61,p=94,f=124,h=126;function m(){this.scanner.eof&&this.error("Unexpected end of input");var n=this.scanner.tokenStart,e=!1,t=!0;return this.scanner.isDelim(d)?(e=!0,t=!1,this.scanner.next()):this.scanner.isDelim(f)||this.eat(o),this.scanner.isDelim(f)?this.scanner.source.charCodeAt(this.scanner.tokenStart+1)!==c?(this.scanner.next(),this.eat(o)):e&&this.error("Identifier is expected",this.scanner.tokenEnd):e&&this.error("Vertical line is expected"),t&&this.scanner.tokenType===r&&(this.scanner.next(),this.eat(o)),{type:"Identifier",loc:this.getLocation(n,this.scanner.tokenStart),name:this.scanner.substrToCursor(n)}}function v(){var n=this.scanner.tokenStart,e=this.scanner.source.charCodeAt(n);return e!==c&&e!==h&&e!==p&&e!==s&&e!==d&&e!==f&&this.error("Attribute selector (=, ~=, ^=, $=, *=, |=) is expected"),this.scanner.next(),e!==c&&(this.scanner.isDelim(c)||this.error("Equal sign is expected"),this.scanner.next()),this.scanner.substrToCursor(n)}n.exports={name:"AttributeSelector",structure:{name:"Identifier",matcher:[String,null],value:["String","Identifier",null],flags:[String,null]},parse:function(){var n,e=this.scanner.tokenStart,t=null,l=null,r=null;return this.eat(a),this.scanner.skipSC(),n=m.call(this),this.scanner.skipSC(),this.scanner.tokenType!==u&&(this.scanner.tokenType!==o&&(t=v.call(this),this.scanner.skipSC(),l=this.scanner.tokenType===i?this.String():this.Identifier(),this.scanner.skipSC()),this.scanner.tokenType===o&&(r=this.scanner.getTokenValue(),this.scanner.next(),this.scanner.skipSC())),this.eat(u),{type:"AttributeSelector",loc:this.getLocation(e,this.scanner.tokenStart),name:n,matcher:t,value:l,flags:r}},generate:function(n){var e=" ";this.chunk("["),this.node(n.name),null!==n.matcher&&(this.chunk(n.matcher),null!==n.value&&(this.node(n.value),"String"===n.value.type&&(e=""))),null!==n.flags&&(this.chunk(e),this.chunk(n.flags)),this.chunk("]")}}},"2TAq":function(n,e,t){var l=t("vd7W").isHexDigit,o=t("vd7W").cmpChar,i=t("vd7W").TYPE,r=i.Ident,a=i.Delim,u=i.Number,s=i.Dimension,d=45,c=63;function p(n,e){return null!==n&&n.type===a&&n.value.charCodeAt(0)===e}function f(n,e){return n.value.charCodeAt(0)===e}function h(n,e,t){for(var o=e,i=0;o0?6:0;if(!l(r))return 0;if(++i>6)return 0}return i}function m(n,e,t){if(!n)return 0;for(;p(t(e),c);){if(++n>6)return 0;e++}return e}n.exports=function(n,e){var t=0;if(null===n||n.type!==r||!o(n.value,0,117))return 0;if(null===(n=e(++t)))return 0;if(p(n,43))return null===(n=e(++t))?0:n.type===r?m(h(n,0,!0),++t,e):p(n,c)?m(1,++t,e):0;if(n.type===u){if(!f(n,43))return 0;var l=h(n,1,!0);return 0===l?0:null===(n=e(++t))?t:n.type===s||n.type===u?f(n,d)&&h(n,1,!1)?t+1:0:m(l,t,e)}return n.type===s&&f(n,43)?m(h(n,1,!0),++t,e):0}},"2WpN":function(n,e,t){"use strict";t.d(e,"a",(function(){return r}));var l=t("mrSG"),o=t("FFOo"),i=t("pugT");function r(n){return function(e){return e.lift(new a(n))}}var a=function(){function n(n){this.callback=n}return n.prototype.call=function(n,e){return e.subscribe(new u(n,this.callback))},n}(),u=function(n){function e(e,t){var l=n.call(this,e)||this;return l.add(new i.a(t)),l}return l.c(e,n),e}(o.a)},"2ePl":function(n,e,t){"use strict";t.d(e,"a",(function(){return l}));var l=function(n){return n&&"number"==typeof n.length&&"function"!=typeof n}},"2pxp":function(n,e){n.exports={parse:function(){return this.createSingleNodeList(this.SelectorList())}}},"2yAJ":function(n,e){function t(n,e){var t=(65535&n)+(65535&e);return(n>>16)+(e>>16)+(t>>16)<<16|65535&t}function l(n,e,l,o,i,r){return t((a=t(t(e,n),t(o,r)))<<(u=i)|a>>>32-u,l);var a,u}function o(n,e,t,o,i,r,a){return l(e&t|~e&o,n,e,i,r,a)}function i(n,e,t,o,i,r,a){return l(e&o|t&~o,n,e,i,r,a)}function r(n,e,t,o,i,r,a){return l(e^t^o,n,e,i,r,a)}function a(n,e,t,o,i,r,a){return l(t^(e|~o),n,e,i,r,a)}function u(n,e){var l,u,s,d,c;n[e>>5]|=128<>>9<<4)]=e;var p=1732584193,f=-271733879,h=-1732584194,m=271733878;for(l=0;l>5]>>>e%32&255);return t}function d(n){var e,t=[];for(t[(n.length>>2)-1]=void 0,e=0;e>5]|=(255&n.charCodeAt(e/8))<>>4&15)+"0123456789abcdef".charAt(15&e);return l}function p(n){return unescape(encodeURIComponent(n))}function f(n){return function(n){return s(u(d(n),8*n.length))}(p(n))}function h(n,e){return function(n,e){var t,l,o=d(n),i=[],r=[];for(i[15]=r[15]=void 0,o.length>16&&(o=u(o,8*n.length)),t=0;t<16;t+=1)i[t]=909522486^o[t],r[t]=1549556828^o[t];return l=u(i.concat(d(e)),512+8*e.length),s(u(r.concat(l),640))}(p(n),p(e))}n.exports=function(n,e,t){return e?t?h(e,n):c(h(e,n)):t?f(n):c(f(n))}},"31qQ":function(n,e,t){"use strict";t.d(e,"a",(function(){return r}));var l=t("mrSG"),o=t("MGBS"),i=t("zotm");function r(){return function(n){return n.lift(new a)}}var a=function(){function n(){}return n.prototype.call=function(n,e){return e.subscribe(new u(n))},n}(),u=function(n){function e(e){var t=n.call(this,e)||this;return t.hasCompleted=!1,t.hasSubscription=!1,t}return l.c(e,n),e.prototype._next=function(n){this.hasSubscription||(this.hasSubscription=!0,this.add(Object(i.a)(this,n)))},e.prototype._complete=function(){this.hasCompleted=!0,this.hasSubscription||this.destination.complete()},e.prototype.notifyComplete=function(n){this.remove(n),this.hasSubscription=!1,this.hasCompleted&&this.destination.complete()},e}(o.a)},"33Dm":function(n,e,t){var l=t("vd7W").TYPE,o=l.WhiteSpace,i=l.Comment,r=l.Ident,a=l.LeftParenthesis;n.exports={name:"MediaQuery",structure:{children:[["Identifier","MediaFeature","WhiteSpace"]]},parse:function(){this.scanner.skipSC();var n=this.createList(),e=null,t=null;n:for(;!this.scanner.eof;){switch(this.scanner.tokenType){case i:this.scanner.next();continue;case o:t=this.WhiteSpace();continue;case r:e=this.Identifier();break;case a:e=this.MediaFeature();break;default:break n}null!==t&&(n.push(t),t=null),n.push(e)}return null===e&&this.error("Identifier or parenthesis is expected"),{type:"MediaQuery",loc:this.getLocationFromList(n),children:n}},generate:function(n){this.children(n)}}},"3J/R":function(n,e,t){"use strict";t.d(e,"a",(function(){return i}));var l=t("26FU"),o=t("xlPZ");function i(n){return function(e){return Object(o.a)(new l.a(n))(e)}}},"3U0i":function(n,e,t){"use strict";t.d(e,"a",(function(){return l}));var l=function(){function n(){return Error.call(this),this.message="Timeout has occurred",this.name="TimeoutError",this}return n.prototype=Object.create(Error.prototype),n}()},"3XNy":function(n,e){var t=0;function l(n){return n>=48&&n<=57}function o(n){return n>=65&&n<=90}function i(n){return n>=97&&n<=122}function r(n){return o(n)||i(n)}function a(n){return n>=128}function u(n){return r(n)||a(n)||95===n}function s(n){return n>=0&&n<=8||11===n||n>=14&&n<=31||127===n}function d(n){return 10===n||13===n||12===n}function c(n){return d(n)||32===n||9===n}function p(n,e){return 92===n&&!d(e)&&e!==t}var f=new Array(128);m.Eof=128,m.WhiteSpace=130,m.Digit=131,m.NameStart=132,m.NonPrintable=133;for(var h=0;h=65&&n<=70||n>=97&&n<=102},isUppercaseLetter:o,isLowercaseLetter:i,isLetter:r,isNonAscii:a,isNameStart:u,isName:function(n){return u(n)||l(n)||45===n},isNonPrintable:s,isNewline:d,isWhiteSpace:c,isValidEscape:p,isIdentifierStart:function(n,e,t){return 45===n?u(e)||45===e||p(e,t):!!u(n)||92===n&&p(n,e)},isNumberStart:function(n,e,t){return 43===n||45===n?l(e)?2:46===e&&l(t)?3:0:46===n?l(e)?2:0:l(n)?1:0},isBOM:function(n){return 65279===n?1:65534===n?1:0},charCodeCategory:m}},"3fWJ":function(n,e,t){"use strict";t.d(e,"a",(function(){return l}));var l=function(){function n(){return Error.call(this),this.message="no elements in sequence",this.name="EmptyError",this}return n.prototype=Object.create(Error.prototype),n}()},"41IB":function(n,e,t){"use strict";t.d(e,"a",(function(){return i}));var l=t("mrSG"),o=t("FFOo");function i(){return function(n){return n.lift(new r)}}var r=function(){function n(){}return n.prototype.call=function(n,e){return e.subscribe(new a(n))},n}(),a=function(n){function e(e){return n.call(this,e)||this}return l.c(e,n),e.prototype._next=function(n){n.observe(this.destination)},e}(o.a)},"4HHr":function(n,e){var t=Object.prototype.hasOwnProperty,l=function(){};function o(n){return"function"==typeof n?n:l}function i(n,e){return function(t,l,o){t.type===e&&n.call(this,t,l,o)}}function r(n,e){var l=e.structure,o=[];for(var i in l)if(!1!==t.call(l,i)){var r=l[i],a={name:i,type:!1,nullable:!1};Array.isArray(l[i])||(r=[l[i]]);for(var u=0;u=0;--e)t[e]===n&&t.splice(e,1)},v.uninstall=function(){e&&(i.onerror=n,e=!1,n=void 0),t=[]},v}(),o.computeStackTrace=function(){function n(n){if(void 0!==n.stack&&n.stack){for(var e,t,l,o=/^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,i=/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx(?:-web)|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,r=/^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js))(?::(\d+))?(?::(\d+))?\s*$/i,u=/(\S+) line (\d+)(?: > eval line \d+)* > eval/i,d=/\((\S*)(?::(\d+))(?::(\d+))\)/,c=n.stack.split("\n"),p=[],f=(/^(.*) is undefined$/.exec(n.message),0),h=c.length;f eval")>-1&&(e=u.exec(t[3]))?(t[3]=e[1],t[4]=e[2],t[5]=null):0!==f||t[5]||void 0===n.columnNumber||(p[0].column=n.columnNumber+1),l={url:t[3],func:t[1]||a,args:t[2]?t[2].split(","):[],line:t[4]?+t[4]:null,column:t[5]?+t[5]:null}}if(!l.func&&l.line&&(l.func=a),l.url&&"blob:"===l.url.substr(0,5)){var v=new XMLHttpRequest;if(v.open("GET",l.url,!1),v.send(null),200===v.status){var g=v.responseText||"",b=(g=g.slice(-300)).match(/\/\/# sourceMappingURL=(.*)$/);if(b){var _=b[1];"~"===_.charAt(0)&&(_=("undefined"==typeof document||null==document.location?"":document.location.origin?document.location.origin:document.location.protocol+"//"+document.location.hostname+(document.location.port?":"+document.location.port:""))+_.slice(1)),l.url=_.slice(0,-4)}}}p.push(l)}return p.length?{name:n.name,message:n.message,url:s(),stack:p}:null}}function e(n,e,t,l){var o={url:e,line:t};if(o.url&&o.line){if(n.incomplete=!1,o.func||(o.func=a),n.stack.length>0&&n.stack[0].url===o.url){if(n.stack[0].line===o.line)return!1;if(!n.stack[0].line&&n.stack[0].func===o.func)return n.stack[0].line=o.line,!1}return n.stack.unshift(o),n.partial=!0,!0}return n.incomplete=!0,!1}function t(n,i){for(var r,u,d=/function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,c=[],p={},f=!1,h=t.caller;h&&!f;h=h.caller)if(h!==l&&h!==o.report){if(u={url:null,func:a,line:null,column:null},h.name?u.func=h.name:(r=d.exec(h.toString()))&&(u.func=r[1]),void 0===u.func)try{u.func=r.input.substring(0,r.input.indexOf("{"))}catch(v){}p[""+h]?f=!0:p[""+h]=!0,c.push(u)}i&&c.splice(0,i);var m={name:n.name,message:n.message,url:s(),stack:c};return e(m,n.sourceURL||n.fileName,n.line||n.lineNumber),m}function l(e,l){var i=null;l=null==l?0:+l;try{if(i=n(e))return i}catch(r){if(o.debug)throw r}try{if(i=t(e,l+1))return i}catch(r){if(o.debug)throw r}return{name:e.name,message:e.message,url:s()}}return l.augmentStackTraceWithInitialElement=e,l.computeStackTraceFromStackProp=n,l}(),n.exports=o},"4fRq":function(n,e){var t="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(t){var l=new Uint8Array(16);n.exports=function(){return t(l),l}}else{var o=new Array(16);n.exports=function(){for(var n,e=0;e<16;e++)0==(3&e)&&(n=4294967296*Math.random()),o[e]=n>>>((3&e)<<3)&255;return o}}},"4njK":function(n,e,t){var l=t("vd7W").TYPE,o=l.WhiteSpace,i=l.Semicolon,r=l.LeftCurlyBracket,a=l.Delim;function u(){return this.scanner.tokenIndex>0&&this.scanner.lookupType(-1)===o?this.scanner.tokenIndex>1?this.scanner.getTokenStart(this.scanner.tokenIndex-1):this.scanner.firstCharOffset:this.scanner.tokenStart}function s(){return 0}n.exports={name:"Raw",structure:{value:String},parse:function(n,e,t){var l,o=this.scanner.getTokenStart(n);return this.scanner.skip(this.scanner.getRawLength(n,e||s)),l=t&&this.scanner.tokenStart>o?u.call(this):this.scanner.tokenStart,{type:"Raw",loc:this.getLocation(o,l),value:this.scanner.source.substring(o,l)}},generate:function(n){this.chunk(n.value)},mode:{default:s,leftCurlyBracket:function(n){return n===r?1:0},leftCurlyBracketOrSemicolon:function(n){return n===r||n===i?1:0},exclamationMarkOrSemicolon:function(n,e,t){return n===a&&33===e.charCodeAt(t)?1:n===i?1:0},semicolonIncluded:function(n){return n===i?2:0}}}},"4vYp":function(n){n.exports=JSON.parse('{"generic":true,"types":{"absolute-size":"xx-small|x-small|small|medium|large|x-large|xx-large","alpha-value":"|","angle-percentage":"|","angular-color-hint":"","angular-color-stop":"&&?","angular-color-stop-list":"[ [, ]?]# , ","animateable-feature":"scroll-position|contents|","attachment":"scroll|fixed|local","attr()":"attr( ? [, ]? )","attr-matcher":"[\'~\'|\'|\'|\'^\'|\'$\'|\'*\']? \'=\'","attr-modifier":"i|s","attribute-selector":"\'[\' \']\'|\'[\' [|] ? \']\'","auto-repeat":"repeat( [auto-fill|auto-fit] , [? ]+ ? )","auto-track-list":"[? [|]]* ? [? [|]]* ?","baseline-position":"[first|last]? baseline","basic-shape":"|||","bg-image":"none|","bg-layer":"|| [/ ]?||||||||","bg-position":"[[left|center|right|top|bottom|]|[left|center|right|] [top|center|bottom|]|[center|[left|right] ?]&&[center|[top|bottom] ?]]","bg-size":"[|auto]{1,2}|cover|contain","blur()":"blur( )","blend-mode":"normal|multiply|screen|overlay|darken|lighten|color-dodge|color-burn|hard-light|soft-light|difference|exclusion|hue|saturation|color|luminosity","box":"border-box|padding-box|content-box","brightness()":"brightness( )","calc()":"calc( )","calc-sum":" [[\'+\'|\'-\'] ]*","calc-product":" [\'*\' |\'/\' ]*","calc-value":"|||( )","cf-final-image":"|","cf-mixing-image":"?&&","circle()":"circle( []? [at ]? )","clamp()":"clamp( #{3} )","class-selector":"\'.\' ","clip-source":"","color":"||||||currentcolor|","color-stop":"|","color-stop-angle":"{1,2}","color-stop-length":"{1,2}","color-stop-list":"[ [, ]?]# , ","combinator":"\'>\'|\'+\'|\'~\'|[\'||\']","common-lig-values":"[common-ligatures|no-common-ligatures]","compat":"searchfield|textarea|push-button|button-bevel|slider-horizontal|checkbox|radio|square-button|menulist|menulist-button|listbox|meter|progress-bar","composite-style":"clear|copy|source-over|source-in|source-out|source-atop|destination-over|destination-in|destination-out|destination-atop|xor","compositing-operator":"add|subtract|intersect|exclude","compound-selector":"[? * [ *]*]!","compound-selector-list":"#","complex-selector":" [? ]*","complex-selector-list":"#","conic-gradient()":"conic-gradient( [from ]? [at ]? , )","contextual-alt-values":"[contextual|no-contextual]","content-distribution":"space-between|space-around|space-evenly|stretch","content-list":"[|contents||||counter( , <\'list-style-type\'>? )]+","content-position":"center|start|end|flex-start|flex-end","content-replacement":"","contrast()":"contrast( [] )","counter()":"counter( , [|none]? )","counter-style":"|symbols( )","counter-style-name":"","counters()":"counters( , , [|none]? )","cross-fade()":"cross-fade( , ? )","cubic-bezier-timing-function":"ease|ease-in|ease-out|ease-in-out|cubic-bezier( , , , )","deprecated-system-color":"ActiveBorder|ActiveCaption|AppWorkspace|Background|ButtonFace|ButtonHighlight|ButtonShadow|ButtonText|CaptionText|GrayText|Highlight|HighlightText|InactiveBorder|InactiveCaption|InactiveCaptionText|InfoBackground|InfoText|Menu|MenuText|Scrollbar|ThreeDDarkShadow|ThreeDFace|ThreeDHighlight|ThreeDLightShadow|ThreeDShadow|Window|WindowFrame|WindowText","discretionary-lig-values":"[discretionary-ligatures|no-discretionary-ligatures]","display-box":"contents|none","display-inside":"flow|flow-root|table|flex|grid|ruby","display-internal":"table-row-group|table-header-group|table-footer-group|table-row|table-cell|table-column-group|table-column|table-caption|ruby-base|ruby-text|ruby-base-container|ruby-text-container","display-legacy":"inline-block|inline-list-item|inline-table|inline-flex|inline-grid","display-listitem":"?&&[flow|flow-root]?&&list-item","display-outside":"block|inline|run-in","drop-shadow()":"drop-shadow( {2,3} ? )","east-asian-variant-values":"[jis78|jis83|jis90|jis04|simplified|traditional]","east-asian-width-values":"[full-width|proportional-width]","element()":"element( )","ellipse()":"ellipse( [{2}]? [at ]? )","ending-shape":"circle|ellipse","env()":"env( , ? )","explicit-track-list":"[? ]+ ?","family-name":"|+","feature-tag-value":" [|on|off]?","feature-type":"@stylistic|@historical-forms|@styleset|@character-variant|@swash|@ornaments|@annotation","feature-value-block":" \'{\' \'}\'","feature-value-block-list":"+","feature-value-declaration":" : + ;","feature-value-declaration-list":"","feature-value-name":"","fill-rule":"nonzero|evenodd","filter-function":"|||||||||","filter-function-list":"[|]+","final-bg-layer":"<\'background-color\'>|||| [/ ]?||||||||","fit-content()":"fit-content( [|] )","fixed-breadth":"","fixed-repeat":"repeat( [] , [? ]+ ? )","fixed-size":"|minmax( , )|minmax( , )","font-stretch-absolute":"normal|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded|","font-variant-css21":"[normal|small-caps]","font-weight-absolute":"normal|bold|","frequency-percentage":"|","general-enclosed":"[ )]|( )","generic-family":"serif|sans-serif|cursive|fantasy|monospace|-apple-system","generic-name":"serif|sans-serif|cursive|fantasy|monospace","geometry-box":"|fill-box|stroke-box|view-box","gradient":"|||||<-legacy-gradient>","grayscale()":"grayscale( )","grid-line":"auto||[&&?]|[span&&[||]]","historical-lig-values":"[historical-ligatures|no-historical-ligatures]","hsl()":"hsl( [/ ]? )|hsl( , , , ? )","hsla()":"hsla( [/ ]? )|hsla( , , , ? )","hue":"|","hue-rotate()":"hue-rotate( )","image":"|||||","image()":"image( ? [? , ?]! )","image-set()":"image-set( # )","image-set-option":"[|] ","image-src":"|","image-tags":"ltr|rtl","inflexible-breadth":"||min-content|max-content|auto","inset()":"inset( {1,4} [round <\'border-radius\'>]? )","invert()":"invert( )","keyframes-name":"|","keyframe-block":"# { }","keyframe-block-list":"+","keyframe-selector":"from|to|","leader()":"leader( )","leader-type":"dotted|solid|space|","length-percentage":"|","line-names":"\'[\' * \']\'","line-name-list":"[|]+","line-style":"none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset","line-width":"|thin|medium|thick","linear-color-hint":"","linear-color-stop":" ?","linear-gradient()":"linear-gradient( [|to ]? , )","mask-layer":"|| [/ ]?||||||[|no-clip]||||","mask-position":"[|left|center|right] [|top|center|bottom]?","mask-reference":"none||","mask-source":"","masking-mode":"alpha|luminance|match-source","matrix()":"matrix( #{6} )","matrix3d()":"matrix3d( #{16} )","max()":"max( # )","media-and":" [and ]+","media-condition":"|||","media-condition-without-or":"||","media-feature":"( [||] )","media-in-parens":"( )||","media-not":"not ","media-or":" [or ]+","media-query":"|[not|only]? [and ]?","media-query-list":"#","media-type":"","mf-boolean":"","mf-name":"","mf-plain":" : ","mf-range":" [\'<\'|\'>\']? \'=\'? | [\'<\'|\'>\']? \'=\'? | \'<\' \'=\'? \'<\' \'=\'? | \'>\' \'=\'? \'>\' \'=\'? ","mf-value":"|||","min()":"min( # )","minmax()":"minmax( [|||min-content|max-content|auto] , [|||min-content|max-content|auto] )","named-color":"transparent|aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|rebeccapurple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen|<-non-standard-color>","namespace-prefix":"","ns-prefix":"[|\'*\']? \'|\'","number-percentage":"|","numeric-figure-values":"[lining-nums|oldstyle-nums]","numeric-fraction-values":"[diagonal-fractions|stacked-fractions]","numeric-spacing-values":"[proportional-nums|tabular-nums]","nth":"|even|odd","opacity()":"opacity( [] )","overflow-position":"unsafe|safe","outline-radius":"|","page-body":"? [; ]?| ","page-margin-box":" \'{\' \'}\'","page-margin-box-type":"@top-left-corner|@top-left|@top-center|@top-right|@top-right-corner|@bottom-left-corner|@bottom-left|@bottom-center|@bottom-right|@bottom-right-corner|@left-top|@left-middle|@left-bottom|@right-top|@right-middle|@right-bottom","page-selector-list":"[#]?","page-selector":"+| *","perspective()":"perspective( )","polygon()":"polygon( ? , [ ]# )","position":"[[left|center|right]||[top|center|bottom]|[left|center|right|] [top|center|bottom|]?|[[left|right] ]&&[[top|bottom] ]]","pseudo-class-selector":"\':\' |\':\' \')\'","pseudo-element-selector":"\':\' ","pseudo-page":": [left|right|first|blank]","quote":"open-quote|close-quote|no-open-quote|no-close-quote","radial-gradient()":"radial-gradient( [||]? [at ]? , )","relative-selector":"? ","relative-selector-list":"#","relative-size":"larger|smaller","repeat-style":"repeat-x|repeat-y|[repeat|space|round|no-repeat]{1,2}","repeating-linear-gradient()":"repeating-linear-gradient( [|to ]? , )","repeating-radial-gradient()":"repeating-radial-gradient( [||]? [at ]? , )","rgb()":"rgb( {3} [/ ]? )|rgb( {3} [/ ]? )|rgb( #{3} , ? )|rgb( #{3} , ? )","rgba()":"rgba( {3} [/ ]? )|rgba( {3} [/ ]? )|rgba( #{3} , ? )|rgba( #{3} , ? )","rotate()":"rotate( [|] )","rotate3d()":"rotate3d( , , , [|] )","rotateX()":"rotateX( [|] )","rotateY()":"rotateY( [|] )","rotateZ()":"rotateZ( [|] )","saturate()":"saturate( )","scale()":"scale( , ? )","scale3d()":"scale3d( , , )","scaleX()":"scaleX( )","scaleY()":"scaleY( )","scaleZ()":"scaleZ( )","self-position":"center|start|end|self-start|self-end|flex-start|flex-end","shape-radius":"|closest-side|farthest-side","skew()":"skew( [|] , [|]? )","skewX()":"skewX( [|] )","skewY()":"skewY( [|] )","sepia()":"sepia( )","shadow":"inset?&&{2,4}&&?","shadow-t":"[{2,3}&&?]","shape":"rect( , , , )|rect( )","shape-box":"|margin-box","side-or-corner":"[left|right]||[top|bottom]","single-animation":"