Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c213cae500 | ||
|
|
1043be02a6 | ||
|
|
56c25727b6 | ||
|
|
0b854ffceb | ||
|
|
366e904698 | ||
|
|
16c84e23a9 | ||
|
|
64f172fe20 | ||
|
|
bb0206d7d2 | ||
|
|
9de61cd671 | ||
|
|
9e6ccc3f61 | ||
|
|
4c339eade1 | ||
|
|
128e494134 | ||
|
|
0e6b97b27b | ||
|
|
235a127111 | ||
|
|
bb51146e80 | ||
|
|
e6944276a6 | ||
|
|
704858fd8d | ||
|
|
87ede50827 | ||
|
|
24fe67f82b | ||
|
|
18c878429f | ||
|
|
6c3a070733 | ||
|
|
a157ef5a8a | ||
|
|
5244ae6d4c | ||
|
|
db47615d43 | ||
|
|
603683e2c5 | ||
|
|
e45bc5aec1 | ||
|
|
a3ee1d9ee6 | ||
|
|
0e95e7e023 | ||
|
|
1748250179 | ||
|
|
c8ea22c651 | ||
|
|
d16cb5ef89 | ||
|
|
004acdc271 | ||
|
|
e182f53d69 | ||
|
|
aef8f0dff3 | ||
|
|
b6a021dabd | ||
|
|
5dab0c2587 | ||
|
|
5d1fdceb98 | ||
|
|
5743d47327 | ||
|
|
ca69b01d11 | ||
|
|
dd785b61cf | ||
|
|
0f154e5f29 | ||
|
|
f9c4c82da6 | ||
|
|
3a136a46a1 | ||
|
|
a6a35e7c43 | ||
|
|
163a867f00 | ||
|
|
d2b7c9bcbf | ||
|
|
fb8df1cc6b | ||
|
|
d063b3e39d | ||
|
|
83fbd1f627 | ||
|
|
1aa6fe8535 | ||
|
|
de2b9caeeb | ||
|
|
362701f5aa | ||
|
|
91244456f5 | ||
|
|
88ab528977 | ||
|
|
7d031e71a0 | ||
|
|
c46c095fcb | ||
|
|
e592b95639 | ||
|
|
593e379523 | ||
|
|
d451d3125e | ||
|
|
e014d36ad2 | ||
|
|
c248764efb | ||
|
|
0259696872 | ||
|
|
165ba4d8d5 | ||
|
|
8049ab8b64 | ||
|
|
2857cab94e | ||
|
|
4843084158 | ||
|
|
01db2d2a86 | ||
|
|
f2ddef855f | ||
|
|
ec02150fd2 | ||
|
|
a56b816c1a | ||
|
|
9d3f7c79a2 | ||
|
|
c684c554bf | ||
|
|
9acb2ceda1 | ||
|
|
053828f3e8 | ||
|
|
f747b3a880 | ||
|
|
750590d0db | ||
|
|
347035a99b | ||
|
|
0db0f6256b | ||
|
|
99d9728360 | ||
|
|
6a1eef0627 |
No files matched your search
@@ -0,0 +1,43 @@
|
||||
name: publish-api-documentation
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- v3.*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: "gh-pages"
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.6
|
||||
- name: Merge changes from 3.0 branch
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git merge origin/3.0 -X theirs
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||
- name: Install GNS3 server
|
||||
run: |
|
||||
python setup.py install
|
||||
- name: Generate the API documentation
|
||||
run: |
|
||||
cd scripts
|
||||
python3 publish_api_documentation.py
|
||||
- name: Publish the API documentation
|
||||
run: |
|
||||
git add docs
|
||||
git status
|
||||
git commit -m "Publish API documentation"
|
||||
git push
|
||||
@@ -1,5 +1,50 @@
|
||||
# Change Log
|
||||
|
||||
## 2.2.18 16/02/2021
|
||||
|
||||
* SIGHUP: remove projects with an empty project directory.
|
||||
* Release Web UI 2.2.18
|
||||
* Catch OSError exception in psutil. Fixes https://github.com/GNS3/gns3-gui/issues/3127
|
||||
* Expose 'auto_open' and 'auto_start' properties in API when creating project. Fixes https://github.com/GNS3/gns3-gui/issues/3119
|
||||
* Add mtools package information. Ref https://github.com/GNS3/gns3-gui/issues/3076
|
||||
* Fix warning: 'ide-drive' is deprecated when using recent version of Qemu. Fixes https://github.com/GNS3/gns3-gui/issues/3101
|
||||
* Fix bug when starting of vpcs stopped with "quit". Fixes https://github.com/GNS3/gns3-gui/issues/3110
|
||||
* Fix WinError 0 handling
|
||||
* Stop uBridge if VPCS node has been terminated. Ref https://github.com/GNS3/gns3-gui/issues/3110
|
||||
* Allow cloned QEMU disk images to be resized before the node starts, by cloning the disk image in response to a resize request instead of waiting until the node starts.
|
||||
* Fix(readme): update python version from 3.5.3 to 3.6
|
||||
* Use HDD disk image as startup QEMU config disk
|
||||
* Create config disk property false by default for Qemu templates
|
||||
* Set default disk interface type to "none".
|
||||
* Add explicit option to automatically create or not the config disk. Off by default.
|
||||
* QEMU config disk support
|
||||
|
||||
|
||||
## 2.2.17 04/12/2020
|
||||
|
||||
* Close and remove projects deleted from disks after SIGHUP signal is received.
|
||||
* Release Web Ui 2.2.17
|
||||
* New config file options to configure the VNC console port range.
|
||||
* Use asyncio.all_tasks instead of deprecated method for Python 3.9 compatibility.
|
||||
|
||||
## 2.2.16 05/11/2020
|
||||
|
||||
* Option to allocate or not the vCPUs and RAM settings for the GNS3 VM. Fixes https://github.com/GNS3/gns3-gui/issues/3069
|
||||
* Release Web UI version 2.2.16
|
||||
* Fix wrong defaults for images_path, configs_path, appliances_path. Fixes #1829
|
||||
* Use EnvironmentFile for Systemd service. Ref https://github.com/GNS3/gns3-gui/issues/3048
|
||||
* Fix SSL support for controller and local compute. Fixes #1826
|
||||
* Prevent WIC to be added/removed while Dynamips router is running. Fixes https://github.com/GNS3/gns3-gui/issues/3082
|
||||
* Fix bug with application id allocation for IOU nodes. Fixes #3079
|
||||
* Allow commas in image paths and VM name for Qemu VMs. Fixes https://github.com/GNS3/gns3-gui/issues/3065
|
||||
|
||||
## 2.2.15 07/10/2020
|
||||
|
||||
* Fix symbol retrieval issue. Ref #1824
|
||||
* Fixes update() missing 2 required positional arguments: 'name' and 'value'. Fixes #1821 #1825
|
||||
* Fix Hyper-V based GNS3 VM WMI issue. Fixes #1822
|
||||
* Release Web-Ui version 2020.4.0-beta.1
|
||||
|
||||
## 2.2.14 14/09/2020
|
||||
|
||||
* Release Web-Ui version 2020.3.0-beta.4
|
||||
|
||||
@@ -24,8 +24,9 @@ In addition of Python dependencies listed in a section below, other software may
|
||||
* `Dynamips <https://github.com/GNS3/dynamips/>`_ is required for running IOS routers (using real IOS images) as well as the internal switches and hubs.
|
||||
* `VPCS <https://github.com/GNS3/vpcs/>`_ is recommended, it is a builtin node simulating a very simple computer to perform connectitivy tests using ping, traceroute etc.
|
||||
* Qemu is strongly recommended on Linux, as most node types are based on Qemu, for example Cisco IOSv and Arista vEOS.
|
||||
* libvirt is recommended (Linux only), as it's needed for the NAT cloud
|
||||
* libvirt is recommended (Linux only), as it's needed for the NAT cloud.
|
||||
* Docker is optional (Linux only), some nodes are based on Docker.
|
||||
* mtools is recommended to support data transfer to/from QEMU VMs using virtual disks.
|
||||
* i386-libraries of libc and libcrypto are optional (Linux only), they are only needed to run IOU based nodes.
|
||||
|
||||
Branches
|
||||
@@ -59,7 +60,7 @@ You must be connected to the Internet in order to install the dependencies.
|
||||
|
||||
Dependencies:
|
||||
|
||||
- Python 3.5.3, setuptools and the ones listed `here <https://github.com/GNS3/gns3-server/blob/master/requirements.txt>`_
|
||||
- Python 3.6, setuptools and the ones listed `here <https://github.com/GNS3/gns3-server/blob/master/requirements.txt>`_
|
||||
|
||||
The following commands will install some of these dependencies:
|
||||
|
||||
|
||||
@@ -28,10 +28,19 @@ report_errors = True
|
||||
console_start_port_range = 5000
|
||||
; Last console port of the range allocated to devices
|
||||
console_end_port_range = 10000
|
||||
|
||||
; First VNC console port of the range allocated to devices.
|
||||
; The value MUST BE >= 5900 and <= 65535
|
||||
vnc_console_start_port_range = 5900
|
||||
; Last VNC console port of the range allocated to devices
|
||||
; The value MUST BE >= 5900 and <= 65535
|
||||
vnc_console_end_port_range = 10000
|
||||
|
||||
; First port of the range allocated for inter-device communication. Two ports are allocated per link.
|
||||
udp_start_port_range = 20000
|
||||
; Last port of the range allocated for inter-device communication. Two ports are allocated per link
|
||||
udp_end_port_range = 30000
|
||||
|
||||
; uBridge executable location, default: search in PATH
|
||||
;ubridge_path = ubridge
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "IP Cop",
|
||||
"category": "firewall",
|
||||
"description": "The IPCop Firewall is a Linux firewall distribution. It is geared towards home and SOHO users. The IPCop web-interface is very user-friendly and makes usage easy.",
|
||||
"vendor_name": "IP Cop",
|
||||
"vendor_url": "https://www.kali.org/",
|
||||
"documentation_url": "http://www.ipcop.org/docs.html",
|
||||
"product_name": "IP Cop",
|
||||
"registry_version": 3,
|
||||
"status": "stable",
|
||||
"maintainer": "Brent Stewart",
|
||||
"maintainer_email": "brent@stewart.tc",
|
||||
"usage": "",
|
||||
"symbol": "shieldedtux.png",
|
||||
"port_name_format": "eth{0}",
|
||||
"qemu": {
|
||||
"adapter_type": "e1000",
|
||||
"adapters": 3,
|
||||
"ram": 1024,
|
||||
"arch": "x86_64",
|
||||
"console_type": "vnc",
|
||||
"kvm": "require"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "ipcop-2.1.8-install-cd.i486.iso",
|
||||
"version": "2.1.9",
|
||||
"md5sum": "1394a7bd4e5c6fe8db70007278826101",
|
||||
"filesize": 65011712,
|
||||
"download_url": "http://www.ipcop.org/download.html",
|
||||
"direct_download_url": "https://sourceforge.net/projects/ipcop/files/IPCop/IPCop%202.1.8/ipcop-2.1.8-install-cd.i486.iso"
|
||||
},
|
||||
{
|
||||
"filename": "empty8G.qcow2",
|
||||
"version": "1.0",
|
||||
"md5sum": "f1d2c25b6990f99bd05b433ab603bdb4",
|
||||
"filesize": 197120,
|
||||
"download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/",
|
||||
"direct_download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "2.1.9",
|
||||
"images": {
|
||||
"hda_disk_image": "empty8G.qcow2",
|
||||
"cdrom_image": "ipcop-2.1.8-install-cd.i486.iso"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "Raspian",
|
||||
"category": "guest",
|
||||
"description": "Raspberry Pi Desktop comes pre-installed with plenty of software for education, programming and general use; including Python, Scratch, Sonic Pi, Java, and more. Appliance created to demonstrate new_appliance.py - read more at https://nextpertise.net.",
|
||||
"vendor_name": "Raspberry Pi Foundation",
|
||||
"vendor_url": "https://www.raspberrypi.org",
|
||||
"product_name": "Raspberry Pi Desktop",
|
||||
"product_url": "https://www.raspberrypi.org/downloads/raspberry-pi-desktop/",
|
||||
"registry_version": 3,
|
||||
"status": "stable",
|
||||
"availability": "free",
|
||||
"maintainer": "Brent Stewart",
|
||||
"maintainer_email": "brent@stewart.tc",
|
||||
"usage": "Default password is raspberry",
|
||||
"symbol": "rpi.png",
|
||||
"qemu": {
|
||||
"adapter_type": "virtio",
|
||||
"adapters": 1,
|
||||
"ram": 1024,
|
||||
"hda_disk_interface": "sata",
|
||||
"arch": "x86_64",
|
||||
"console_type": "vnc",
|
||||
"kvm": "disable"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "2020-02-12-rpd-x86-buster.iso",
|
||||
"version": "2020-02-12",
|
||||
"md5sum": "98f34fb53086752b4c9c452094f30740",
|
||||
"filesize": 3128147968,
|
||||
"download_url": "https://www.raspberrypi.org/downloads/raspberry-pi-desktop/"
|
||||
},
|
||||
{
|
||||
"filename": "empty8G.qcow2",
|
||||
"version": "1",
|
||||
"md5sum": "f1d2c25b6990f99bd05b433ab603bdb4",
|
||||
"filesize": 197120,
|
||||
"download_url": "https://sourceforge.net/projects/gns-3/files/Empty%20Qemu%20disk/empty8G.qcow2/download"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "2020-02-12",
|
||||
"images": {
|
||||
"hda_disk_image": "empty8G.qcow2",
|
||||
"cdrom_image": "2020-02-12-rpd-x86-buster.iso"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -27,10 +27,17 @@
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "vEOS-lab-4.25.0FX-LDP-RSVP.vmdk",
|
||||
"version": "4.25.0FX",
|
||||
"md5sum": "b7c2efdbe48301a78f124db989710346",
|
||||
"filesize": 468647936,
|
||||
"filename": "vEOS-lab-4.25.0F.vmdk",
|
||||
"version": "4.25.0F",
|
||||
"md5sum": "d420763fdf3bc50e7e5b88418bd9d1fd",
|
||||
"filesize": 468779008,
|
||||
"download_url": "https://www.arista.com/en/support/software-download"
|
||||
},
|
||||
{
|
||||
"filename": "vEOS-lab-4.24.3M.vmdk",
|
||||
"version": "4.24.3M",
|
||||
"md5sum": "0a28e44c7ce4a8965f24a4a463a89b7d",
|
||||
"filesize": 455213056,
|
||||
"download_url": "https://www.arista.com/en/support/software-download"
|
||||
},
|
||||
{
|
||||
@@ -204,10 +211,17 @@
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "4.25.0FX",
|
||||
"name": "4.25.0F",
|
||||
"images": {
|
||||
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
|
||||
"hdb_disk_image": "vEOS-lab-4.25.0FX-LDP-RSVP.vmdk"
|
||||
"hdb_disk_image": "vEOS-lab-4.25.0F.vmdk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "4.24.3M",
|
||||
"images": {
|
||||
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
|
||||
"hdb_disk_image": "vEOS-lab-4.24.3M.vmdk"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"options": "-smp 2"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "dcnm-va.11.4.1.iso",
|
||||
"version": "11.4.1",
|
||||
"md5sum": "37b30d7a13b2fd436478e0e3049e4da6",
|
||||
"filesize": 5378867680,
|
||||
"download_url": "https://software.cisco.com/download/home/281722751/type/282088134/release/11.4%25281%2529"
|
||||
},
|
||||
{
|
||||
"filename": "dcnm-va.11.2.1.iso",
|
||||
"version": "11.2.1",
|
||||
@@ -56,6 +63,13 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "11.4.1",
|
||||
"images": {
|
||||
"hda_disk_image": "empty100G.qcow2",
|
||||
"cdrom_image": "dcnm-va.11.4.1.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "11.2.1",
|
||||
"images": {
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
"hda_disk_interface": "virtio",
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
"kvm": "require"
|
||||
"kvm": "require",
|
||||
"options": "-machine pc-q35-4.2"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"options": "-smp 4 -cpu host"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "xrv9k-fullk9-x-7.1.1.qcow2",
|
||||
"version": "7.1.1",
|
||||
"md5sum": "dcf241e3f8df0151fec2c7bfac9d96ac",
|
||||
"filesize": 1443758080,
|
||||
"download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/7.1.1"
|
||||
},
|
||||
{
|
||||
"filename": "xrv9k-fullk9-x-7.0.1.qcow2",
|
||||
"version": "7.0.1",
|
||||
@@ -97,6 +104,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "7.1.1",
|
||||
"images": {
|
||||
"hda_disk_image": "xrv9k-fullk9-x-7.1.1.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.1",
|
||||
"images": {
|
||||
|
||||
@@ -26,6 +26,13 @@
|
||||
"options": "-nographic"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "VOSSGNS3.8.2.0.0.qcow2",
|
||||
"version": "v8.2.0.0",
|
||||
"md5sum": "9a0cd77c08644abbf3a69771c125c011",
|
||||
"filesize": 331808768,
|
||||
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_VOSS/VOSSGNS3.8.2.0.0.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "VOSSGNS3.8.1.5.0.qcow2",
|
||||
"version": "8.1.5.0",
|
||||
@@ -56,6 +63,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "v8.2.0.0",
|
||||
"images": {
|
||||
"hda_disk_image": "VOSSGNS3.8.2.0.0.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "8.1.5.0",
|
||||
"images": {
|
||||
|
||||
@@ -27,6 +27,20 @@
|
||||
"options": "-smp 2 -cpu host"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "BIGIP-16.0.0.1-0.0.3.qcow2",
|
||||
"version": "16.0.0.1",
|
||||
"md5sum": "95ff618b7d0b53c4252299cd49b0e564",
|
||||
"filesize": 5393088512,
|
||||
"download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v16.x/16.0.0/english/16.0.0.1_virtual-edition/&sw=BIG-IP&pro=big-ip_v16.x&ver=16.0.0&container=16.0.0.1_Virtual-Edition&file=BIGIP-16.0.0.1-0.0.3.ALL.qcow2.zip"
|
||||
},
|
||||
{
|
||||
"filename": "BIGIP-16.0.0-0.0.12.qcow2",
|
||||
"version": "16.0.0",
|
||||
"md5sum": "c49cd2513e386f3259eb0ee6fe3bb502",
|
||||
"filesize": 5344722944,
|
||||
"download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-ip/big-ip_v16.x/16.0.0/english/16.0.0_virtual-edition/&sw=BIG-IP&pro=big-ip_v16.x&ver=16.0.0&container=16.0.0_Virtual-Edition&file=BIGIP-16.0.0-0.0.12.ALL.qcow2.zip"
|
||||
},
|
||||
{
|
||||
"filename": "BIGIP-15.1.0.2-0.0.9.qcow2",
|
||||
"version": "15.1.0.2",
|
||||
@@ -163,6 +177,20 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "16.0.0.1",
|
||||
"images": {
|
||||
"hda_disk_image": "BIGIP-16.0.0.1-0.0.3.qcow2",
|
||||
"hdb_disk_image": "empty100G.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "16.0.0",
|
||||
"images": {
|
||||
"hda_disk_image": "BIGIP-16.0.0-0.0.12.qcow2",
|
||||
"hdb_disk_image": "empty100G.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "15.1.0.2",
|
||||
"images": {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"options": "-nographic -enable-kvm"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
{
|
||||
"filename": "junos-vmx-x86-64-20.2R1.10.qcow2",
|
||||
"version": "20.2R1.10-KVM",
|
||||
"md5sum": "182484474accf07bd403ef17fa2959a9",
|
||||
@@ -357,7 +357,7 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
{
|
||||
"name": "20.2R1.10-KVM",
|
||||
"images": {
|
||||
"hda_disk_image": "junos-vmx-x86-64-20.2R1.10.qcow2",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"options": "-nographic -enable-kvm -smp cpus=3"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
{
|
||||
"filename": "vFPC-20200526.img",
|
||||
"version": "20.2R1.10-KVM",
|
||||
"md5sum": "400652d7e450b0bf8ad4cc37db46b78c",
|
||||
@@ -154,7 +154,7 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
{
|
||||
"name": "20.2R1.10-KVM",
|
||||
"images": {
|
||||
"hda_disk_image": "vFPC-20200526.img"
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"options": "-nographic"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "vqfx-20.2R1-2019010209-pfe-qemu.qcow",
|
||||
"version": "20.2R1",
|
||||
"md5sum": "d8b68ba6b8c987717f5298ba9292d3a4",
|
||||
"filesize": 762839040,
|
||||
"download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/"
|
||||
},
|
||||
{
|
||||
"filename": "cosim-18.4R1.8_20180212.qcow2",
|
||||
"version": "17.4R1 & 18.4R1",
|
||||
@@ -41,6 +48,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "20.2R1",
|
||||
"images": {
|
||||
"hda_disk_image": "vqfx-20.2R1-2019010209-pfe-qemu.qcow"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "17.4R1 & 18.4R1",
|
||||
"images": {
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"options": "-nographic -smp 2"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "vqfx-20.2R1.10-re-qemu.qcow2",
|
||||
"version": "20.2R1",
|
||||
"md5sum": "20220bfa3d387184fce957936eeeb4ec",
|
||||
"filesize": 675020800,
|
||||
"download_url": "https://www.juniper.net/us/en/dm/free-vqfx-trial/"
|
||||
},
|
||||
{
|
||||
"filename": "jinstall-vqfx-10-f-18.4R1.8.qcow2",
|
||||
"version": "18.4R1",
|
||||
@@ -48,6 +55,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "20.2R1",
|
||||
"images": {
|
||||
"hda_disk_image": "vqfx-20.2R1.10-re-qemu.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "18.4R1",
|
||||
"images": {
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "Juniper vRR",
|
||||
"category": "router",
|
||||
"description": "The vRR is a full-featured, carrier-grade virtual route reflector software that extends 15+ years of Juniper Networks edge routing expertise to the virtual realm.",
|
||||
"vendor_name": "Juniper",
|
||||
"vendor_url": "https://www.juniper.net/us/en/",
|
||||
"documentation_url": "https://www.juniper.net/documentation/product/en_US/virtual-route-reflector",
|
||||
"product_name": "Juniper vRR",
|
||||
"product_url": "https://www.juniper.net/us/en/products-services/nos/junos/",
|
||||
"registry_version": 3,
|
||||
"status": "experimental",
|
||||
"maintainer": "none",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"usage": "Initial username is root, no password.\n\nUSAGE INSTRUCTIONS\n\nConnect the first interface (em0) to your admin VLAN.",
|
||||
"symbol": "juniper-vmx.svg",
|
||||
"first_port_name": "em0",
|
||||
"port_name_format": "em{port1}",
|
||||
"qemu": {
|
||||
"adapter_type": "e1000",
|
||||
"adapters": 2,
|
||||
"ram": 8192,
|
||||
"hda_disk_interface": "ide",
|
||||
"hdb_disk_interface": "ide",
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
"kvm": "require",
|
||||
"options": "-nographic -enable-kvm"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "junos-x86-64-20.3R1.8.img",
|
||||
"version": "20.3R1.8-KVM",
|
||||
"md5sum": "5cd41a792daae2b3fefac1928f2a1894",
|
||||
"filesize": 2761162752
|
||||
},
|
||||
{
|
||||
"filename": "metadata.img",
|
||||
"version": "20.3R1.8-KVM",
|
||||
"md5sum": "ae4e3562aa389929476d82420c79d511",
|
||||
"filesize": 393216
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "20.3R1.8-KVM",
|
||||
"images": {
|
||||
"hda_disk_image": "junos-x86-64-20.3R1.8.img",
|
||||
"hdb_disk_image": "metadata.img"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -22,6 +22,15 @@
|
||||
"kvm": "allow"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "openwrt-19.07.4-x86-64-combined-ext4.img",
|
||||
"version": "19.07.4",
|
||||
"md5sum": "e8bde404ab527ab40ef9643bca9f7432",
|
||||
"filesize": 285736960,
|
||||
"download_url": "https://downloads.openwrt.org/releases/19.07.4/targets/x86/64/",
|
||||
"direct_download_url": "https://downloads.openwrt.org/releases/19.07.4/targets/x86/64/openwrt-19.07.4-x86-64-combined-ext4.img.gz",
|
||||
"compression": "gzip"
|
||||
},
|
||||
{
|
||||
"filename": "openwrt-19.07.3-x86-64-combined-ext4.img",
|
||||
"version": "19.07.3",
|
||||
@@ -132,6 +141,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "19.07.4",
|
||||
"images": {
|
||||
"hda_disk_image": "openwrt-19.07.4-x86-64-combined-ext4.img"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "19.07.3",
|
||||
"images": {
|
||||
|
||||
@@ -25,31 +25,31 @@
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "OPNsense-18.1.6-OpenSSL-nano-amd64.img",
|
||||
"version": "18.1.6",
|
||||
"md5sum": "042f328380ad0c8008759c43435e8843",
|
||||
"filesize": 272003136,
|
||||
"download_url": "https://opnsense.c0urier.net/releases/18.1/"
|
||||
"filename": "OPNsense-20.7-OpenSSL-nano-amd64.img",
|
||||
"version": "20.7",
|
||||
"md5sum": "453e505e9526d4a0a3d5208efdd13b1a",
|
||||
"filesize": 3221225472,
|
||||
"download_url": "https://opnsense.c0urier.net/releases/20.7/"
|
||||
},
|
||||
{
|
||||
"filename": "OPNsense-17.7.5-OpenSSL-nano-amd64.img",
|
||||
"version": "17.7.5",
|
||||
"md5sum": "6ec5b7f99cc727f904bbf2aaadcab0b8",
|
||||
"filesize": 237038601,
|
||||
"download_url": "https://opnsense.c0urier.net/releases/17.7/"
|
||||
"filename": "OPNsense-19.7-OpenSSL-nano-amd64.img",
|
||||
"version": "19.7",
|
||||
"md5sum": "a15a00cfa2de45791d6bc230d8469dc7",
|
||||
"filesize": 3221225472,
|
||||
"download_url": "https://opnsense.c0urier.net/releases/19.7/"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "18.1.6",
|
||||
"name": "20.7",
|
||||
"images": {
|
||||
"hda_disk_image": "OPNsense-18.1.6-OpenSSL-nano-amd64.img"
|
||||
"hda_disk_image": "OPNsense-20.7-OpenSSL-nano-amd64.img"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "17.7.5",
|
||||
"name": "19.7",
|
||||
"images": {
|
||||
"hda_disk_image": "OPNsense-17.7.5-OpenSSL-nano-amd64.img"
|
||||
"hda_disk_image": "OPNsense-19.7-OpenSSL-nano-amd64.img"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
"status": "stable",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"usage": "Credentials: SSH ---> username: root ---> password: 1234 MySQL DB: ---> username: root --> password: tacacs Web interface: ---> username: tacgui ---> password: abc123",
|
||||
"usage": "Credentials:\nSSH ---> username: root ---> password: 1234\nMySQL DB: ---> username: root --> password: tacacs\nWeb interface: ---> username: tacgui ---> password: abc123\n\nDefault for 0.9.82 or above:\nIP Address: 10.0.0.254\nNetmask: 255.0.0.0\nGateway: 10.0.0.1",
|
||||
"port_name_format": "Port{port1}",
|
||||
"qemu": {
|
||||
"adapter_type": "e1000",
|
||||
"adapters": 1,
|
||||
"ram": 1024,
|
||||
"ram": 4096,
|
||||
"hda_disk_interface": "ide",
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
@@ -24,6 +24,13 @@
|
||||
"kvm": "allow"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "tacgui-0.9.82-20201008.qcow2",
|
||||
"version": "0.9.82",
|
||||
"md5sum": "dc0c84aa61d8960a23bf3b309a826f3f",
|
||||
"filesize": 2914844672,
|
||||
"download_url": "https://drive.google.com/open?id=1tlDSyoD5dAWgJu6I76CgYV7BkwhScWSS"
|
||||
},
|
||||
{
|
||||
"filename": "tac_plus.qcow2",
|
||||
"version": "201710201114",
|
||||
@@ -33,6 +40,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "0.9.82",
|
||||
"images": {
|
||||
"hda_disk_image": "tacgui-0.9.82-20201008.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "201710201114",
|
||||
"images": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Tiny Core Linux",
|
||||
"category": "guest",
|
||||
"description": "Core Linux is a smaller variant of Tiny Core without a graphical desktop.\n\nIt's provide a complete Linux system in few MB.",
|
||||
"description": "Core Linux is a smaller variant of Tiny Core without a graphical desktop.\n\nIt provides a complete Linux system using only a few MiB." ,
|
||||
"vendor_name": "Team Tiny Core",
|
||||
"vendor_url": "http://distro.ibiblio.org/tinycorelinux",
|
||||
"documentation_url": "http://wiki.tinycorelinux.net/",
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"options": "-vga virtio"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "Ubuntu 20.04 (64bit).vmdk",
|
||||
"version": "20.04",
|
||||
"md5sum": "cf619dfe9bb8d89e2b18b067f02e57a0",
|
||||
"filesize": 6629883904,
|
||||
"download_url": "http://www.osboxes.org/ubuntu/"
|
||||
},
|
||||
{
|
||||
"filename": "Ubuntu 19.04 (64bit).vmdk",
|
||||
"version": "19.04",
|
||||
@@ -55,6 +62,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "20.04",
|
||||
"images": {
|
||||
"hda_disk_image": "Ubuntu 20.04 (64bit).vmdk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "19.04",
|
||||
"images": {
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"kvm": "allow"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "vyos-1.2.6-amd64.iso",
|
||||
"version": "1.2.6",
|
||||
"md5sum": "dbf5335c16967cd5f768d1ca927666db",
|
||||
"filesize": 428867584,
|
||||
"download_url": "https://downloads.vyos.io/?dir=release/current/1.2.6"
|
||||
},
|
||||
{
|
||||
"filename": "vyos-1.3-rolling-202005040117-amd64.iso",
|
||||
"version": "1.3-rolling-202005040117",
|
||||
@@ -75,6 +82,13 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "1.2.6",
|
||||
"images": {
|
||||
"hda_disk_image": "empty8G.qcow2",
|
||||
"cdrom_image": "vyos-1.2.6-amd64.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "1.3-rolling-202005040117",
|
||||
"images": {
|
||||
|
||||
@@ -83,8 +83,13 @@ class BaseNode:
|
||||
|
||||
if self._console is not None:
|
||||
if console_type == "vnc":
|
||||
# VNC is a special case and the range must be 5900-6000
|
||||
self._console = self._manager.port_manager.reserve_tcp_port(self._console, self._project, port_range_start=5900, port_range_end=6000)
|
||||
vnc_console_start_port_range, vnc_console_end_port_range = self._get_vnc_console_port_range()
|
||||
self._console = self._manager.port_manager.reserve_tcp_port(
|
||||
self._console,
|
||||
self._project,
|
||||
port_range_start=vnc_console_start_port_range,
|
||||
port_range_end=vnc_console_end_port_range,
|
||||
)
|
||||
elif console_type == "none":
|
||||
self._console = None
|
||||
else:
|
||||
@@ -96,8 +101,11 @@ class BaseNode:
|
||||
|
||||
if self._console is None:
|
||||
if console_type == "vnc":
|
||||
# VNC is a special case and the range must be 5900-6000
|
||||
self._console = self._manager.port_manager.get_free_tcp_port(self._project, port_range_start=5900, port_range_end=6000)
|
||||
vnc_console_start_port_range, vnc_console_end_port_range = self._get_vnc_console_port_range()
|
||||
self._console = self._manager.port_manager.get_free_tcp_port(
|
||||
self._project,
|
||||
port_range_start=vnc_console_start_port_range,
|
||||
port_range_end=vnc_console_end_port_range)
|
||||
elif console_type != "none":
|
||||
self._console = self._manager.port_manager.get_free_tcp_port(self._project)
|
||||
|
||||
@@ -338,6 +346,25 @@ class BaseNode:
|
||||
self._closed = True
|
||||
return True
|
||||
|
||||
def _get_vnc_console_port_range(self):
|
||||
"""
|
||||
Returns the VNC console port range.
|
||||
"""
|
||||
|
||||
server_config = self._manager.config.get_section_config("Server")
|
||||
vnc_console_start_port_range = server_config.getint("vnc_console_start_port_range", 5900)
|
||||
vnc_console_end_port_range = server_config.getint("vnc_console_end_port_range", 10000)
|
||||
|
||||
if not 5900 <= vnc_console_start_port_range <= 65535:
|
||||
raise NodeError("The VNC console start port range must be between 5900 and 65535")
|
||||
if not 5900 <= vnc_console_end_port_range <= 65535:
|
||||
raise NodeError("The VNC console start port range must be between 5900 and 65535")
|
||||
if vnc_console_start_port_range >= vnc_console_end_port_range:
|
||||
raise NodeError(f"The VNC console start port range value ({vnc_console_start_port_range}) "
|
||||
f"cannot be above or equal to the end value ({vnc_console_end_port_range})")
|
||||
|
||||
return vnc_console_start_port_range, vnc_console_end_port_range
|
||||
|
||||
async def start_wrap_console(self):
|
||||
"""
|
||||
Start a telnet proxy for the console allowing multiple telnet clients
|
||||
@@ -502,7 +529,13 @@ class BaseNode:
|
||||
self._console = None
|
||||
if console is not None:
|
||||
if self.console_type == "vnc":
|
||||
self._console = self._manager.port_manager.reserve_tcp_port(console, self._project, port_range_start=5900, port_range_end=6000)
|
||||
vnc_console_start_port_range, vnc_console_end_port_range = self._get_vnc_console_port_range()
|
||||
self._console = self._manager.port_manager.reserve_tcp_port(
|
||||
console,
|
||||
self._project,
|
||||
port_range_start=vnc_console_start_port_range,
|
||||
port_range_end=vnc_console_end_port_range
|
||||
)
|
||||
else:
|
||||
self._console = self._manager.port_manager.reserve_tcp_port(console, self._project)
|
||||
|
||||
|
||||
@@ -1182,13 +1182,17 @@ class Router(BaseNode):
|
||||
if not adapter.wic_slot_available(wic_slot_number):
|
||||
raise DynamipsError("WIC slot {wic_slot_number} is already occupied by another WIC".format(wic_slot_number=wic_slot_number))
|
||||
|
||||
if await self.is_running():
|
||||
raise DynamipsError('WIC "{wic}" cannot be added while router "{name}" is running'.format(wic=wic,
|
||||
name=self._name))
|
||||
|
||||
# Dynamips WICs slot IDs start on a multiple of 16
|
||||
# WIC1 = 16, WIC2 = 32 and WIC3 = 48
|
||||
internal_wic_slot_number = 16 * (wic_slot_number + 1)
|
||||
await self._hypervisor.send('vm slot_add_binding "{name}" {slot_number} {wic_slot_number} {wic}'.format(name=self._name,
|
||||
slot_number=slot_number,
|
||||
wic_slot_number=internal_wic_slot_number,
|
||||
wic=wic))
|
||||
slot_number=slot_number,
|
||||
wic_slot_number=internal_wic_slot_number,
|
||||
wic=wic))
|
||||
|
||||
log.info('Router "{name}" [{id}]: {wic} inserted into WIC slot {wic_slot_number}'.format(name=self._name,
|
||||
id=self._id,
|
||||
@@ -1217,12 +1221,16 @@ class Router(BaseNode):
|
||||
if adapter.wic_slot_available(wic_slot_number):
|
||||
raise DynamipsError("No WIC is installed in WIC slot {wic_slot_number}".format(wic_slot_number=wic_slot_number))
|
||||
|
||||
if await self.is_running():
|
||||
raise DynamipsError('WIC cannot be removed from slot {wic_slot_number} while router "{name}" is running'.format(wic_slot_number=wic_slot_number,
|
||||
name=self._name))
|
||||
|
||||
# Dynamips WICs slot IDs start on a multiple of 16
|
||||
# WIC1 = 16, WIC2 = 32 and WIC3 = 48
|
||||
internal_wic_slot_number = 16 * (wic_slot_number + 1)
|
||||
await self._hypervisor.send('vm slot_remove_binding "{name}" {slot_number} {wic_slot_number}'.format(name=self._name,
|
||||
slot_number=slot_number,
|
||||
wic_slot_number=internal_wic_slot_number))
|
||||
slot_number=slot_number,
|
||||
wic_slot_number=internal_wic_slot_number))
|
||||
|
||||
log.info('Router "{name}" [{id}]: {wic} removed from WIC slot {wic_slot_number}'.format(name=self._name,
|
||||
id=self._id,
|
||||
|
||||
@@ -27,10 +27,13 @@ import re
|
||||
import subprocess
|
||||
|
||||
from ...utils.asyncio import subprocess_check_output
|
||||
from ...utils.get_resource import get_resource
|
||||
from ..base_manager import BaseManager
|
||||
from ..error import NodeError, ImageMissingError
|
||||
from .qemu_error import QemuError
|
||||
from .qemu_vm import QemuVM
|
||||
from .utils.guest_cid import get_next_guest_cid
|
||||
from .utils.ziputils import unpack_zip
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -45,6 +48,8 @@ class Qemu(BaseManager):
|
||||
|
||||
super().__init__()
|
||||
self._guest_cid_lock = asyncio.Lock()
|
||||
self.config_disk = "config.img"
|
||||
self._init_config_disk()
|
||||
|
||||
async def create_node(self, *args, **kwargs):
|
||||
"""
|
||||
@@ -343,3 +348,21 @@ class Qemu(BaseManager):
|
||||
log.info("Qemu disk '{}' extended by {} MB".format(path, extend))
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
raise QemuError("Could not update disk image {}:{}".format(path, e))
|
||||
|
||||
def _init_config_disk(self):
|
||||
"""
|
||||
Initialize the default config disk
|
||||
"""
|
||||
|
||||
try:
|
||||
self.get_abs_image_path(self.config_disk)
|
||||
except (NodeError, ImageMissingError):
|
||||
config_disk_zip = get_resource("compute/qemu/resources/{}.zip".format(self.config_disk))
|
||||
if config_disk_zip and os.path.exists(config_disk_zip):
|
||||
directory = self.get_images_directory()
|
||||
try:
|
||||
unpack_zip(config_disk_zip, directory)
|
||||
except OSError as e:
|
||||
log.warning("Config disk creation: {}".format(e))
|
||||
else:
|
||||
log.warning("Config disk: image '{}' missing".format(self.config_disk))
|
||||
@@ -26,6 +26,7 @@ import re
|
||||
import shlex
|
||||
import math
|
||||
import shutil
|
||||
import struct
|
||||
import asyncio
|
||||
import socket
|
||||
import gns3server
|
||||
@@ -37,7 +38,9 @@ from gns3server.utils import parse_version, shlex_quote
|
||||
from gns3server.utils.asyncio import subprocess_check_output, cancellable_wait_run_in_executor
|
||||
from .qemu_error import QemuError
|
||||
from .utils.qcow2 import Qcow2, Qcow2Error
|
||||
from .utils.ziputils import pack_zip, unpack_zip
|
||||
from ..adapters.ethernet_adapter import EthernetAdapter
|
||||
from ..error import NodeError, ImageMissingError
|
||||
from ..nios.nio_udp import NIOUDP
|
||||
from ..nios.nio_tap import NIOTAP
|
||||
from ..base_node import BaseNode
|
||||
@@ -101,10 +104,10 @@ class QemuVM(BaseNode):
|
||||
self._hdb_disk_image = ""
|
||||
self._hdc_disk_image = ""
|
||||
self._hdd_disk_image = ""
|
||||
self._hda_disk_interface = "ide"
|
||||
self._hdb_disk_interface = "ide"
|
||||
self._hdc_disk_interface = "ide"
|
||||
self._hdd_disk_interface = "ide"
|
||||
self._hda_disk_interface = "none"
|
||||
self._hdb_disk_interface = "none"
|
||||
self._hdc_disk_interface = "none"
|
||||
self._hdd_disk_interface = "none"
|
||||
self._cdrom_image = ""
|
||||
self._bios_image = ""
|
||||
self._boot_priority = "c"
|
||||
@@ -119,12 +122,28 @@ class QemuVM(BaseNode):
|
||||
self._kernel_command_line = ""
|
||||
self._legacy_networking = False
|
||||
self._replicate_network_connection_state = True
|
||||
self._create_config_disk = False
|
||||
self._on_close = "power_off"
|
||||
self._cpu_throttling = 0 # means no CPU throttling
|
||||
self._process_priority = "low"
|
||||
|
||||
self.mac_address = "" # this will generate a MAC address
|
||||
self.adapters = 1 # creates 1 adapter by default
|
||||
|
||||
# config disk
|
||||
self.config_disk_name = self.manager.config_disk
|
||||
self.config_disk_image = ""
|
||||
if self.config_disk_name:
|
||||
if not shutil.which("mcopy"):
|
||||
log.warning("Config disk: 'mtools' are not installed.")
|
||||
self.config_disk_name = ""
|
||||
else:
|
||||
try:
|
||||
self.config_disk_image = self.manager.get_abs_image_path(self.config_disk_name)
|
||||
except (NodeError, ImageMissingError):
|
||||
log.warning("Config disk: image '{}' missing".format(self.config_disk_name))
|
||||
self.config_disk_name = ""
|
||||
|
||||
log.info('QEMU VM "{name}" [{id}] has been created'.format(name=self._name, id=self._id))
|
||||
|
||||
@property
|
||||
@@ -445,7 +464,7 @@ class QemuVM(BaseNode):
|
||||
else:
|
||||
self._cdrom_image = ""
|
||||
|
||||
async def update(self, name, value):
|
||||
async def update_property(self, name, value):
|
||||
"""
|
||||
Update Qemu VM properties.
|
||||
"""
|
||||
@@ -652,6 +671,30 @@ class QemuVM(BaseNode):
|
||||
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 create_config_disk(self):
|
||||
"""
|
||||
Returns whether a config disk is automatically created on HDD disk interface (secondary slave)
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
return self._create_config_disk
|
||||
|
||||
@create_config_disk.setter
|
||||
def create_config_disk(self, create_config_disk):
|
||||
"""
|
||||
Sets whether a config disk is automatically created on HDD disk interface (secondary slave)
|
||||
|
||||
:param replicate_network_connection_state: boolean
|
||||
"""
|
||||
|
||||
if create_config_disk:
|
||||
log.info('QEMU VM "{name}" [{id}] has enabled the config disk creation feature'.format(name=self._name, id=self._id))
|
||||
else:
|
||||
log.info('QEMU VM "{name}" [{id}] has disabled the config disk creation feature'.format(name=self._name, id=self._id))
|
||||
self._create_config_disk = create_config_disk
|
||||
|
||||
@property
|
||||
def on_close(self):
|
||||
"""
|
||||
@@ -1115,6 +1158,7 @@ class QemuVM(BaseNode):
|
||||
self._stop_cpulimit()
|
||||
if self.on_close != "save_vm_state":
|
||||
await self._clear_save_vm_stated()
|
||||
await self._export_config()
|
||||
await super().stop()
|
||||
|
||||
async def _open_qemu_monitor_connection_vm(self, timeout=10):
|
||||
@@ -1627,6 +1671,139 @@ class QemuVM(BaseNode):
|
||||
log.info("{} returned with {}".format(self._get_qemu_img(), retcode))
|
||||
return retcode
|
||||
|
||||
async def _create_linked_clone(self, disk_name, disk_image, disk):
|
||||
try:
|
||||
qemu_img_path = self._get_qemu_img()
|
||||
command = [qemu_img_path, "create", "-o", "backing_file={}".format(disk_image), "-f", "qcow2", disk]
|
||||
retcode = await self._qemu_img_exec(command)
|
||||
if retcode:
|
||||
stdout = self.read_qemu_img_stdout()
|
||||
raise QemuError("Could not create '{}' disk image: qemu-img returned with {}\n{}".format(disk_name,
|
||||
retcode,
|
||||
stdout))
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
stdout = self.read_qemu_img_stdout()
|
||||
raise QemuError("Could not create '{}' disk image: {}\n{}".format(disk_name, e, stdout))
|
||||
|
||||
async def _mcopy(self, image, *args):
|
||||
try:
|
||||
# read offset of first partition from MBR
|
||||
with open(image, "rb") as img_file:
|
||||
mbr = img_file.read(512)
|
||||
part_type, offset, signature = struct.unpack("<450xB3xL52xH", mbr)
|
||||
if signature != 0xAA55:
|
||||
raise OSError("{}: invalid MBR".format(image))
|
||||
if part_type not in (1, 4, 6, 11, 12, 14):
|
||||
raise OSError("{}: invalid partition type {:02X}"
|
||||
.format(image, part_type))
|
||||
part_image = image + "@@{}S".format(offset)
|
||||
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
"mcopy", "-i", part_image, *args,
|
||||
stdin=subprocess.DEVNULL,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
|
||||
cwd=self.working_dir)
|
||||
(stdout, _) = await process.communicate()
|
||||
retcode = process.returncode
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
raise OSError("mcopy failure: {}".format(e))
|
||||
if retcode != 0:
|
||||
stdout = stdout.decode("utf-8").rstrip()
|
||||
if stdout:
|
||||
raise OSError("mcopy failure: {}".format(stdout))
|
||||
else:
|
||||
raise OSError("mcopy failure: return code {}".format(retcode))
|
||||
|
||||
async def _export_config(self):
|
||||
disk_name = getattr(self, "config_disk_name")
|
||||
if not disk_name:
|
||||
return
|
||||
disk = os.path.join(self.working_dir, disk_name)
|
||||
if not os.path.exists(disk):
|
||||
return
|
||||
config_dir = os.path.join(self.working_dir, "configs")
|
||||
zip_file = os.path.join(self.working_dir, "config.zip")
|
||||
try:
|
||||
os.mkdir(config_dir)
|
||||
await self._mcopy(disk, "-s", "-m", "-n", "--", "::/", config_dir)
|
||||
if os.path.exists(zip_file):
|
||||
os.remove(zip_file)
|
||||
pack_zip(zip_file, config_dir)
|
||||
except OSError as e:
|
||||
log.warning("Can't export config: {}".format(e))
|
||||
self.project.emit("log.warning", {"message": "{}: Can't export config: {}".format(self._name, e)})
|
||||
shutil.rmtree(config_dir, ignore_errors=True)
|
||||
|
||||
async def _import_config(self):
|
||||
disk_name = getattr(self, "config_disk_name")
|
||||
if not disk_name:
|
||||
return
|
||||
disk = os.path.join(self.working_dir, disk_name)
|
||||
zip_file = os.path.join(self.working_dir, "config.zip")
|
||||
startup_config = self.hdd_disk_image
|
||||
if startup_config and startup_config.lower().endswith(".zip") and \
|
||||
not os.path.exists(zip_file) and not os.path.exists(disk):
|
||||
try:
|
||||
shutil.copyfile(startup_config, zip_file)
|
||||
except OSError as e:
|
||||
log.warning("Can't access startup config: {}".format(e))
|
||||
self.project.emit("log.warning", {"message": "{}: Can't access startup config: {}".format(self._name, e)})
|
||||
if not os.path.exists(zip_file):
|
||||
return
|
||||
config_dir = os.path.join(self.working_dir, "configs")
|
||||
disk_tmp = disk + ".tmp"
|
||||
try:
|
||||
os.mkdir(config_dir)
|
||||
shutil.copyfile(getattr(self, "config_disk_image"), disk_tmp)
|
||||
unpack_zip(zip_file, config_dir)
|
||||
config_files = [os.path.join(config_dir, fname)
|
||||
for fname in os.listdir(config_dir)]
|
||||
if config_files:
|
||||
await self._mcopy(disk_tmp, "-s", "-m", "-o", "--", *config_files, "::/")
|
||||
os.replace(disk_tmp, disk)
|
||||
except OSError as e:
|
||||
log.warning("Can't import config: {}".format(e))
|
||||
self.project.emit("log.warning", {"message": "{}: Can't import config: {}".format(self._name, e)})
|
||||
if os.path.exists(disk_tmp):
|
||||
os.remove(disk_tmp)
|
||||
os.remove(zip_file)
|
||||
shutil.rmtree(config_dir, ignore_errors=True)
|
||||
|
||||
async def _disk_interface_options(self, disk, disk_index, interface, format=None):
|
||||
options = []
|
||||
extra_drive_options = ""
|
||||
if format:
|
||||
extra_drive_options += ",format={}".format(format)
|
||||
|
||||
# From Qemu man page: if the filename contains comma, you must double it
|
||||
# (for instance, "file=my,,file" to use file "my,file").
|
||||
disk = disk.replace(",", ",,")
|
||||
|
||||
if interface == "sata":
|
||||
# special case, sata controller doesn't exist in Qemu
|
||||
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, extra_drive_options)])
|
||||
qemu_version = await self.manager.get_qemu_version(self.qemu_path)
|
||||
if qemu_version and parse_version(qemu_version) >= parse_version("4.2.0"):
|
||||
# The ‘ide-drive’ device is deprecated since version 4.2.0
|
||||
# https://qemu.readthedocs.io/en/latest/system/deprecated.html#ide-drive-since-4-2
|
||||
options.extend(["-device", 'ide-hd,drive=drive{},bus=ahci{}.0,id=drive{}'.format(disk_index, disk_index, disk_index)])
|
||||
else:
|
||||
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, extra_drive_options)])
|
||||
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, extra_drive_options)])
|
||||
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, extra_drive_options)])
|
||||
# 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, extra_drive_options)])
|
||||
return options
|
||||
|
||||
async def _disk_options(self):
|
||||
options = []
|
||||
qemu_img_path = self._get_qemu_img()
|
||||
@@ -1634,14 +1811,21 @@ class QemuVM(BaseNode):
|
||||
drives = ["a", "b", "c", "d"]
|
||||
|
||||
for disk_index, drive in enumerate(drives):
|
||||
disk_image = getattr(self, "_hd{}_disk_image".format(drive))
|
||||
interface = getattr(self, "hd{}_disk_interface".format(drive))
|
||||
# prioritize config disk over harddisk d
|
||||
if drive == 'd' and self._create_config_disk:
|
||||
continue
|
||||
|
||||
disk_image = getattr(self, "_hd{}_disk_image".format(drive))
|
||||
if not disk_image:
|
||||
continue
|
||||
|
||||
disk_name = "hd" + drive
|
||||
interface = getattr(self, "hd{}_disk_interface".format(drive))
|
||||
# fail-safe: use "ide" if there is a disk image and no interface type has been explicitly configured
|
||||
if interface == "none":
|
||||
interface = "ide"
|
||||
setattr(self, "hd{}_disk_interface".format(drive), interface)
|
||||
|
||||
disk_name = "hd" + drive
|
||||
if not os.path.isfile(disk_image) or not os.path.exists(disk_image):
|
||||
if os.path.islink(disk_image):
|
||||
raise QemuError("{} disk image '{}' linked to '{}' is not accessible".format(disk_name, disk_image, os.path.realpath(disk_image)))
|
||||
@@ -1669,17 +1853,7 @@ class QemuVM(BaseNode):
|
||||
disk = os.path.join(self.working_dir, "{}_disk.qcow2".format(disk_name))
|
||||
if not os.path.exists(disk):
|
||||
# create the disk
|
||||
try:
|
||||
command = [qemu_img_path, "create", "-o", "backing_file={}".format(disk_image), "-f", "qcow2", disk]
|
||||
retcode = await self._qemu_img_exec(command)
|
||||
if retcode:
|
||||
stdout = self.read_qemu_img_stdout()
|
||||
raise QemuError("Could not create '{}' disk image: qemu-img returned with {}\n{}".format(disk_name,
|
||||
retcode,
|
||||
stdout))
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
stdout = self.read_qemu_img_stdout()
|
||||
raise QemuError("Could not create '{}' disk image: {}\n{}".format(disk_name, e, stdout))
|
||||
await self._create_linked_clone(disk_name, disk_image, disk)
|
||||
else:
|
||||
# The disk exists we check if the clone works
|
||||
try:
|
||||
@@ -1691,23 +1865,26 @@ class QemuVM(BaseNode):
|
||||
else:
|
||||
disk = disk_image
|
||||
|
||||
if interface == "sata":
|
||||
# special case, sata controller doesn't exist in Qemu
|
||||
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)])
|
||||
options.extend(await self._disk_interface_options(disk, disk_index, interface))
|
||||
|
||||
# config disk
|
||||
disk_image = getattr(self, "config_disk_image")
|
||||
if disk_image and self._create_config_disk:
|
||||
disk_name = getattr(self, "config_disk_name")
|
||||
disk = os.path.join(self.working_dir, disk_name)
|
||||
if self.hdd_disk_interface == "none":
|
||||
# use the HDA interface type if none has been configured for HDD
|
||||
self.hdd_disk_interface = getattr(self, "hda_disk_interface", "none")
|
||||
await self._import_config()
|
||||
disk_exists = os.path.exists(disk)
|
||||
if not disk_exists:
|
||||
try:
|
||||
shutil.copyfile(disk_image, disk)
|
||||
disk_exists = True
|
||||
except OSError as e:
|
||||
log.warning("Could not create '{}' disk image: {}".format(disk_name, e))
|
||||
if disk_exists:
|
||||
options.extend(await self._disk_interface_options(disk, 3, self.hdd_disk_interface, "raw"))
|
||||
|
||||
return options
|
||||
|
||||
@@ -1718,6 +1895,9 @@ class QemuVM(BaseNode):
|
||||
|
||||
if self.linked_clone:
|
||||
disk_image_path = os.path.join(self.working_dir, "{}_disk.qcow2".format(drive_name))
|
||||
if not os.path.exists(disk_image_path):
|
||||
disk_image = getattr(self, "_{}_disk_image".format(drive_name))
|
||||
await self._create_linked_clone(drive_name, disk_image, disk_image_path)
|
||||
else:
|
||||
disk_image_path = getattr(self, "{}_disk_image".format(drive_name))
|
||||
|
||||
@@ -1737,7 +1917,7 @@ class QemuVM(BaseNode):
|
||||
raise QemuError("cdrom image '{}' is not accessible".format(self._cdrom_image))
|
||||
if self._hdc_disk_image:
|
||||
raise QemuError("You cannot use a disk image on hdc disk and a CDROM image at the same time")
|
||||
options.extend(["-cdrom", self._cdrom_image])
|
||||
options.extend(["-cdrom", self._cdrom_image.replace(",", ",,")])
|
||||
return options
|
||||
|
||||
def _bios_option(self):
|
||||
@@ -1749,7 +1929,7 @@ class QemuVM(BaseNode):
|
||||
raise QemuError("bios image '{}' linked to '{}' is not accessible".format(self._bios_image, os.path.realpath(self._bios_image)))
|
||||
else:
|
||||
raise QemuError("bios image '{}' is not accessible".format(self._bios_image))
|
||||
options.extend(["-bios", self._bios_image])
|
||||
options.extend(["-bios", self._bios_image.replace(",", ",,")])
|
||||
return options
|
||||
|
||||
def _linux_boot_options(self):
|
||||
@@ -1761,14 +1941,14 @@ class QemuVM(BaseNode):
|
||||
raise QemuError("initrd file '{}' linked to '{}' is not accessible".format(self._initrd, os.path.realpath(self._initrd)))
|
||||
else:
|
||||
raise QemuError("initrd file '{}' is not accessible".format(self._initrd))
|
||||
options.extend(["-initrd", self._initrd])
|
||||
options.extend(["-initrd", self._initrd.replace(",", ",,")])
|
||||
if self._kernel_image:
|
||||
if not os.path.isfile(self._kernel_image) or not os.path.exists(self._kernel_image):
|
||||
if os.path.islink(self._kernel_image):
|
||||
raise QemuError("kernel image '{}' linked to '{}' is not accessible".format(self._kernel_image, os.path.realpath(self._kernel_image)))
|
||||
else:
|
||||
raise QemuError("kernel image '{}' is not accessible".format(self._kernel_image))
|
||||
options.extend(["-kernel", self._kernel_image])
|
||||
options.extend(["-kernel", self._kernel_image.replace(",", ",,")])
|
||||
if self._kernel_command_line:
|
||||
options.extend(["-append", self._kernel_command_line])
|
||||
|
||||
@@ -2008,7 +2188,7 @@ class QemuVM(BaseNode):
|
||||
log.info('QEMU VM "{name}" [{id}] VM saved state detected (snapshot name: {snapshot})'.format(name=self._name,
|
||||
id=self.id,
|
||||
snapshot=snapshot_name))
|
||||
return ["-loadvm", snapshot_name]
|
||||
return ["-loadvm", snapshot_name.replace(",", ",,")]
|
||||
|
||||
except subprocess.SubprocessError as e:
|
||||
raise QemuError("Error while looking for the Qemu VM saved state snapshot: {}".format(e))
|
||||
@@ -2020,16 +2200,18 @@ class QemuVM(BaseNode):
|
||||
(to be passed to subprocess.Popen())
|
||||
"""
|
||||
|
||||
vm_name = self._name.replace(",", ",,")
|
||||
project_path = self.project.path.replace(",", ",,")
|
||||
additional_options = self._options.strip()
|
||||
additional_options = additional_options.replace("%vm-name%", '"' + self._name.replace('"', '\\"') + '"')
|
||||
additional_options = additional_options.replace("%vm-name%", '"' + vm_name.replace('"', '\\"') + '"')
|
||||
additional_options = additional_options.replace("%vm-id%", self._id)
|
||||
additional_options = additional_options.replace("%project-id%", self.project.id)
|
||||
additional_options = additional_options.replace("%project-path%", '"' + self.project.path.replace('"', '\\"') + '"')
|
||||
additional_options = additional_options.replace("%project-path%", '"' + project_path.replace('"', '\\"') + '"')
|
||||
additional_options = additional_options.replace("%guest-cid%", str(self._guest_cid))
|
||||
if self._console_type != "none" and self._console:
|
||||
additional_options = additional_options.replace("%console-port%", str(self._console))
|
||||
command = [self.qemu_path]
|
||||
command.extend(["-name", self._name])
|
||||
command.extend(["-name", vm_name])
|
||||
command.extend(["-m", "{}M".format(self._ram)])
|
||||
command.extend(["-smp", "cpus={},sockets=1".format(self._cpus)])
|
||||
if await self._run_with_hardware_acceleration(self.qemu_path, self._options):
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2020 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# 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 os
|
||||
import time
|
||||
import shutil
|
||||
import zipfile
|
||||
|
||||
def pack_zip(filename, root_dir=None, base_dir=None):
|
||||
"""Create a zip archive"""
|
||||
|
||||
if filename[-4:].lower() == ".zip":
|
||||
filename = filename[:-4]
|
||||
shutil.make_archive(filename, 'zip', root_dir, base_dir)
|
||||
|
||||
def unpack_zip(filename, extract_dir=None):
|
||||
"""Unpack a zip archive"""
|
||||
|
||||
dirs = []
|
||||
if not extract_dir:
|
||||
extract_dir = os.getcwd()
|
||||
|
||||
try:
|
||||
with zipfile.ZipFile(filename, 'r') as zfile:
|
||||
for zinfo in zfile.infolist():
|
||||
fname = os.path.join(extract_dir, zinfo.filename)
|
||||
date_time = time.mktime(zinfo.date_time + (0, 0, -1))
|
||||
zfile.extract(zinfo, extract_dir)
|
||||
|
||||
# update timestamp
|
||||
if zinfo.is_dir():
|
||||
dirs.append((fname, date_time))
|
||||
else:
|
||||
os.utime(fname, (date_time, date_time))
|
||||
# update timestamp of directories
|
||||
for fname, date_time in reversed(dirs):
|
||||
os.utime(fname, (date_time, date_time))
|
||||
except zipfile.BadZipFile:
|
||||
raise shutil.ReadError("%s is not a zip file" % filename)
|
||||
@@ -251,7 +251,7 @@ class VPCSVM(BaseNode):
|
||||
log.error("Could not start VPCS {}: {}\n{}".format(self._vpcs_path(), e, vpcs_stdout))
|
||||
raise VPCSError("Could not start VPCS {}: {}\n{}".format(self._vpcs_path(), e, vpcs_stdout))
|
||||
|
||||
def _termination_callback(self, returncode):
|
||||
async def _termination_callback(self, returncode):
|
||||
"""
|
||||
Called when the process has stopped.
|
||||
|
||||
@@ -263,6 +263,8 @@ class VPCSVM(BaseNode):
|
||||
self._started = False
|
||||
self.status = "stopped"
|
||||
self._process = None
|
||||
await self._stop_ubridge()
|
||||
await super().stop()
|
||||
if returncode != 0:
|
||||
self.project.emit("log.error", {"message": "VPCS process has stopped, return code: {}\n{}".format(returncode, self.read_vpcs_stdout())})
|
||||
|
||||
|
||||
@@ -81,16 +81,23 @@ class Controller:
|
||||
name = "Main server"
|
||||
|
||||
computes = self._load_controller_settings()
|
||||
from gns3server.web.web_server import WebServer
|
||||
ssl_context = WebServer.instance(host=host, port=port).ssl_context()
|
||||
protocol = server_config.get("protocol", "http")
|
||||
if ssl_context and protocol != "https":
|
||||
log.warning("Protocol changed to 'https' for local compute because SSL is enabled".format(port))
|
||||
protocol = "https"
|
||||
try:
|
||||
self._local_server = await self.add_compute(compute_id="local",
|
||||
name=name,
|
||||
protocol=server_config.get("protocol", "http"),
|
||||
protocol=protocol,
|
||||
host=host,
|
||||
console_host=console_host,
|
||||
port=port,
|
||||
user=server_config.get("user", ""),
|
||||
password=server_config.get("password", ""),
|
||||
force=True)
|
||||
force=True,
|
||||
ssl_context=ssl_context)
|
||||
except aiohttp.web.HTTPConflict:
|
||||
log.fatal("Cannot access to the local server, make sure something else is not running on the TCP port {}".format(port))
|
||||
sys.exit(1)
|
||||
@@ -138,6 +145,14 @@ class Controller:
|
||||
|
||||
log.info("Controller is reloading")
|
||||
self._load_controller_settings()
|
||||
|
||||
# remove all projects deleted from disk.
|
||||
for project in self._projects.copy().values():
|
||||
if not os.path.exists(project.path) or not os.listdir(project.path):
|
||||
log.info(f"Project '{project.name}' doesn't exist on the disk anymore, closing...")
|
||||
await project.close()
|
||||
self.remove_project(project)
|
||||
|
||||
await self.load_projects()
|
||||
|
||||
def check_can_write_config(self):
|
||||
@@ -266,7 +281,7 @@ class Controller:
|
||||
"""
|
||||
|
||||
server_config = Config.instance().get_section_config("Server")
|
||||
images_path = os.path.expanduser(server_config.get("images_path", "~/GNS3/projects"))
|
||||
images_path = os.path.expanduser(server_config.get("images_path", "~/GNS3/images"))
|
||||
os.makedirs(images_path, exist_ok=True)
|
||||
return images_path
|
||||
|
||||
@@ -276,9 +291,9 @@ class Controller:
|
||||
"""
|
||||
|
||||
server_config = Config.instance().get_section_config("Server")
|
||||
images_path = os.path.expanduser(server_config.get("configs_path", "~/GNS3/projects"))
|
||||
os.makedirs(images_path, exist_ok=True)
|
||||
return images_path
|
||||
configs_path = os.path.expanduser(server_config.get("configs_path", "~/GNS3/configs"))
|
||||
os.makedirs(configs_path, exist_ok=True)
|
||||
return configs_path
|
||||
|
||||
async def add_compute(self, compute_id=None, name=None, force=False, connect=True, **kwargs):
|
||||
"""
|
||||
|
||||
@@ -70,7 +70,7 @@ class ApplianceManager:
|
||||
"""
|
||||
|
||||
server_config = Config.instance().get_section_config("Server")
|
||||
appliances_path = os.path.expanduser(server_config.get("appliances_path", "~/GNS3/projects"))
|
||||
appliances_path = os.path.expanduser(server_config.get("appliances_path", "~/GNS3/appliances"))
|
||||
os.makedirs(appliances_path, exist_ok=True)
|
||||
return appliances_path
|
||||
|
||||
|
||||
@@ -57,7 +57,8 @@ class Compute:
|
||||
A GNS3 compute.
|
||||
"""
|
||||
|
||||
def __init__(self, compute_id, controller=None, protocol="http", host="localhost", port=3080, user=None, password=None, name=None, console_host=None):
|
||||
def __init__(self, compute_id, controller=None, protocol="http", host="localhost",
|
||||
port=3080, user=None, password=None, name=None, console_host=None, ssl_context=None):
|
||||
self._http_session = None
|
||||
assert controller is not None
|
||||
log.info("Create compute %s", compute_id)
|
||||
@@ -81,6 +82,7 @@ class Compute:
|
||||
self._cpu_usage_percent = None
|
||||
self._memory_usage_percent = None
|
||||
self._last_error = None
|
||||
self._ssl_context = ssl_context
|
||||
self._capabilities = {
|
||||
"version": None,
|
||||
"node_types": []
|
||||
@@ -92,7 +94,9 @@ class Compute:
|
||||
|
||||
def _session(self):
|
||||
if self._http_session is None or self._http_session.closed is True:
|
||||
self._http_session = aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=None, force_close=True))
|
||||
self._http_session = aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=None,
|
||||
force_close=True,
|
||||
ssl_context=self._ssl_context))
|
||||
return self._http_session
|
||||
|
||||
#def __del__(self):
|
||||
|
||||
@@ -49,6 +49,7 @@ class GNS3VM:
|
||||
"headless": False,
|
||||
"enable": False,
|
||||
"engine": "vmware",
|
||||
"allocate_vcpus_ram": True,
|
||||
"ram": 2048,
|
||||
"vcpus": 1,
|
||||
"port": 80,
|
||||
@@ -311,6 +312,7 @@ class GNS3VM:
|
||||
if self._settings["vmname"] is None:
|
||||
return
|
||||
log.info("Start the GNS3 VM")
|
||||
engine.allocate_vcpus_ram = self._settings["allocate_vcpus_ram"]
|
||||
engine.vmname = self._settings["vmname"]
|
||||
engine.ram = self._settings["ram"]
|
||||
engine.vcpus = self._settings["vcpus"]
|
||||
|
||||
@@ -30,6 +30,7 @@ class BaseGNS3VM:
|
||||
self._ip_address = None
|
||||
self._port = 80 # value not used, will be overwritten
|
||||
self._headless = False
|
||||
self._allocate_vcpus_ram = True
|
||||
self._vcpus = 1
|
||||
self._ram = 1024
|
||||
self._user = ""
|
||||
@@ -203,6 +204,26 @@ class BaseGNS3VM:
|
||||
|
||||
self._headless = value
|
||||
|
||||
@property
|
||||
def allocate_vcpus_ram(self):
|
||||
"""
|
||||
Returns whether VCPUs and RAM settings should be configured for the GNS3 VM.
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
return self._allocate_vcpus_ram
|
||||
|
||||
@allocate_vcpus_ram.setter
|
||||
def allocate_vcpus_ram(self, value):
|
||||
"""
|
||||
Sets whether VCPUs and RAM settings should be configured for the GNS3 VM.
|
||||
|
||||
:param value: boolean
|
||||
"""
|
||||
|
||||
self._allocate_vcpus_ram = value
|
||||
|
||||
@property
|
||||
def vcpus(self):
|
||||
"""
|
||||
|
||||
@@ -223,6 +223,24 @@ class HyperVGNS3VM(BaseGNS3VM):
|
||||
elif ret != 0 or ret != 32775:
|
||||
raise GNS3VMError("Failed to change state to {}".format(state))
|
||||
|
||||
async def _is_vm_network_active(self):
|
||||
"""
|
||||
Check if WMI is updated with VM virtual network adapters
|
||||
and wait until their count becomes > 0
|
||||
ProtocolIFType Unknown (0)
|
||||
Other (1)
|
||||
IPv4 (4096)
|
||||
IPv6 (4097)
|
||||
IPv4/v6 (4098)
|
||||
"""
|
||||
|
||||
wql = "SELECT * FROM Msvm_GuestNetworkAdapterConfiguration WHERE InstanceID like \
|
||||
'Microsoft:GuestNetwork\\" + self._vm.Name + "%' and ProtocolIFType > 0 "
|
||||
nic_count = len(self._conn.query(wql))
|
||||
while nic_count == 0:
|
||||
await asyncio.sleep(0.1) # 100ms
|
||||
nic_count = len(self._conn.query(wql))
|
||||
|
||||
async def start(self):
|
||||
"""
|
||||
Starts the GNS3 VM.
|
||||
@@ -233,9 +251,10 @@ class HyperVGNS3VM(BaseGNS3VM):
|
||||
raise GNS3VMError("Could not find Hyper-V VM {}".format(self.vmname))
|
||||
|
||||
if not self._is_running():
|
||||
log.info("Update GNS3 VM settings (CPU and RAM)")
|
||||
# set the number of vCPUs and amount of RAM
|
||||
self._set_vcpus_ram(self.vcpus, self.ram)
|
||||
if self.allocate_vcpus_ram:
|
||||
log.info("Update GNS3 VM settings (CPU and RAM)")
|
||||
# set the number of vCPUs and amount of RAM
|
||||
self._set_vcpus_ram(self.vcpus, self.ram)
|
||||
|
||||
# start the VM
|
||||
try:
|
||||
@@ -244,6 +263,9 @@ class HyperVGNS3VM(BaseGNS3VM):
|
||||
raise GNS3VMError("Failed to start the GNS3 VM: {}".format(e))
|
||||
log.info("GNS3 VM has been started")
|
||||
|
||||
# check if VM network is active
|
||||
await self._is_vm_network_active()
|
||||
|
||||
# Get the guest IP address
|
||||
# LIS (Linux Integration Services) must be installed on the guest
|
||||
# See https://oitibs.com/hyper-v-lis-on-ubuntu-18-04/ for details.
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
# 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 asyncio
|
||||
|
||||
from .base_gns3_vm import BaseGNS3VM
|
||||
from .gns3_vm_error import GNS3VMError
|
||||
|
||||
|
||||
@@ -259,9 +259,12 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
log.info('"{}" state is {}'.format(self._vmname, vm_state))
|
||||
|
||||
if vm_state == "poweroff":
|
||||
log.info("Update GNS3 VM settings (CPU, RAM and Hardware Virtualization)")
|
||||
await self.set_vcpus(self.vcpus)
|
||||
await self.set_ram(self.ram)
|
||||
if self.allocate_vcpus_ram:
|
||||
log.info("Update GNS3 VM vCPUs and RAM settings")
|
||||
await self.set_vcpus(self.vcpus)
|
||||
await self.set_ram(self.ram)
|
||||
|
||||
log.info("Update GNS3 VM Hardware Virtualization setting")
|
||||
await self.enable_nested_hw_virt()
|
||||
|
||||
if vm_state in ("poweroff", "saved"):
|
||||
|
||||
@@ -148,9 +148,12 @@ class VMwareGNS3VM(BaseGNS3VM):
|
||||
except VMwareError as e:
|
||||
raise GNS3VMError("Could not list VMware VMs: {}".format(str(e)))
|
||||
if not running:
|
||||
log.info("Update GNS3 VM settings (CPU, RAM and Hardware Virtualization)")
|
||||
# set the number of vCPUs and amount of RAM
|
||||
await self._set_vcpus_ram(self.vcpus, self.ram)
|
||||
if self.allocate_vcpus_ram:
|
||||
log.info("Update GNS3 VM vCPUs and RAM settings")
|
||||
await self._set_vcpus_ram(self.vcpus, self.ram)
|
||||
|
||||
log.info("Update GNS3 VM Hardware Virtualization setting")
|
||||
await self._set_extra_options()
|
||||
|
||||
# start the VM
|
||||
|
||||
@@ -174,6 +174,7 @@ class Project:
|
||||
self._links = {}
|
||||
self._drawings = {}
|
||||
self._snapshots = {}
|
||||
self._computes = []
|
||||
|
||||
# List the available snapshots
|
||||
snapshot_dir = os.path.join(self.path, "snapshots")
|
||||
@@ -564,6 +565,9 @@ class Project:
|
||||
if node_id in self._nodes:
|
||||
return self._nodes[node_id]
|
||||
|
||||
if compute.id not in self._computes:
|
||||
self._computes.append(compute.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
|
||||
@@ -571,10 +575,10 @@ class Project:
|
||||
# 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)
|
||||
kwargs.get("properties")["application_id"] = get_next_application_id(self._controller.projects, self._computes)
|
||||
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)
|
||||
kwargs["application_id"] = get_next_application_id(self._controller.projects, self._computes)
|
||||
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)
|
||||
@@ -604,6 +608,8 @@ class Project:
|
||||
self.remove_allocated_node_name(node.name)
|
||||
del self._nodes[node.id]
|
||||
await node.destroy()
|
||||
# refresh the compute IDs list
|
||||
self._computes = [n.compute.id for n in self.nodes.values()]
|
||||
self.dump()
|
||||
self.emit_notification("node.deleted", node.__json__())
|
||||
|
||||
@@ -931,6 +937,14 @@ class Project:
|
||||
topology = project_data["topology"]
|
||||
for compute in topology.get("computes", []):
|
||||
await self.controller.add_compute(**compute)
|
||||
|
||||
# Get all compute used in the project
|
||||
# used to allocate application IDs for IOU nodes.
|
||||
for node in topology.get("nodes", []):
|
||||
compute_id = node.get("compute_id")
|
||||
if compute_id not in self._computes:
|
||||
self._computes.append(compute_id)
|
||||
|
||||
for node in topology.get("nodes", []):
|
||||
compute = self.controller.get_compute(node.pop("compute_id"))
|
||||
name = node.pop("name")
|
||||
|
||||
@@ -132,7 +132,7 @@ class Symbols:
|
||||
return symbol
|
||||
else:
|
||||
# return the default computer symbol
|
||||
log.warning("Could not retrieve symbol '{}'".format(symbol_id))
|
||||
log.warning("Could not retrieve symbol '{}', returning default symbol...".format(symbol_id))
|
||||
return self._symbols_path[":/symbols/classic/computer.svg"]
|
||||
|
||||
def get_size(self, symbol_id):
|
||||
|
||||
@@ -58,7 +58,7 @@ class CrashReport:
|
||||
Report crash to a third party service
|
||||
"""
|
||||
|
||||
DSN = "https://451594d76eaa42d08e1133e52df65616:2a7c754170b847dda3e559e59c13aa86@o19455.ingest.sentry.io/38482"
|
||||
DSN = "https://741e8d41a14c49be8c511c4c73bbbb78:55b37fa1ed5c4c11bc736ed4ac590945@o19455.ingest.sentry.io/38482"
|
||||
_instance = None
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@@ -124,7 +124,7 @@ class QEMUHandler:
|
||||
vm.console = request.json.pop("console", vm.console)
|
||||
for name, value in request.json.items():
|
||||
if hasattr(vm, name) and getattr(vm, name) != value:
|
||||
await vm.update(name, value)
|
||||
await vm.update_property(name, value)
|
||||
vm.updated()
|
||||
response.json(vm)
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ Processus:
|
||||
try:
|
||||
psinfo = proc.as_dict(attrs=["name", "exe"])
|
||||
data += "* {} {}\n".format(psinfo["name"], psinfo["exe"])
|
||||
except psutil.NoSuchProcess:
|
||||
except (OSError, psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
pass
|
||||
|
||||
data += "\n\nProjects"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
import os
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import urllib.parse
|
||||
|
||||
from gns3server.web.route import Route
|
||||
from gns3server.controller import Controller
|
||||
@@ -52,8 +53,9 @@ class SymbolHandler:
|
||||
async def raw(request, response):
|
||||
|
||||
controller = Controller.instance()
|
||||
symbol_id = urllib.parse.unquote(request.match_info["symbol_id"])
|
||||
try:
|
||||
await response.stream_file(controller.symbols.get_path(request.match_info["symbol_id"]))
|
||||
await response.stream_file(controller.symbols.get_path(symbol_id))
|
||||
except (KeyError, OSError) as e:
|
||||
log.warning("Could not get symbol file: {}".format(e))
|
||||
response.set_status(404)
|
||||
@@ -66,8 +68,10 @@ class SymbolHandler:
|
||||
},
|
||||
raw=True)
|
||||
async def upload(request, response):
|
||||
|
||||
controller = Controller.instance()
|
||||
path = os.path.join(controller.symbols.symbols_path(), os.path.basename(request.match_info["symbol_id"]))
|
||||
symbol_id = urllib.parse.unquote(request.match_info["symbol_id"])
|
||||
path = os.path.join(controller.symbols.symbols_path(), os.path.basename(symbol_id))
|
||||
try:
|
||||
with open(path, "wb") as f:
|
||||
while True:
|
||||
|
||||
@@ -195,7 +195,7 @@ def kill_ghosts():
|
||||
if name in detect_process:
|
||||
proc.kill()
|
||||
log.warning("Killed ghost process %s", name)
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
except (OSError, psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
pass
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ def run():
|
||||
server.run()
|
||||
except OSError as e:
|
||||
# This is to ignore OSError: [WinError 0] The operation completed successfully exception on Windows.
|
||||
if not sys.platform.startswith("win") and not e.winerror == 0:
|
||||
if not sys.platform.startswith("win") or not e.winerror == 0:
|
||||
raise
|
||||
except Exception as e:
|
||||
log.critical("Critical error while running the server: {}".format(e), exc_info=1)
|
||||
|
||||
@@ -41,6 +41,10 @@ GNS3VM_SETTINGS_SCHEMA = {
|
||||
"description": "The engine to use for the VM. Null to disable",
|
||||
"enum": ["vmware", "virtualbox", None]
|
||||
},
|
||||
"allocate_vcpus_ram": {
|
||||
"description": "Allocate vCPUS and RAM settings",
|
||||
"type": "boolean"
|
||||
},
|
||||
"vcpus": {
|
||||
"description": "Number of vCPUS affected to the VM",
|
||||
"type": "integer"
|
||||
|
||||
@@ -72,6 +72,14 @@ PROJECT_CREATE_SCHEMA = {
|
||||
"description": "Project auto close",
|
||||
"type": "boolean"
|
||||
},
|
||||
"auto_open": {
|
||||
"description": "Project open when GNS3 start",
|
||||
"type": "boolean"
|
||||
},
|
||||
"auto_start": {
|
||||
"description": "Project start when opened",
|
||||
"type": "boolean"
|
||||
},
|
||||
"project_id": {
|
||||
"description": "Project UUID",
|
||||
"type": ["string", "null"],
|
||||
|
||||
@@ -190,6 +190,10 @@ QEMU_CREATE_SCHEMA = {
|
||||
"description": "Replicate the network connection state for links in Qemu",
|
||||
"type": ["boolean", "null"],
|
||||
},
|
||||
"create_config_disk": {
|
||||
"description": "Automatically create a config disk on HDD disk interface (secondary slave)",
|
||||
"type": ["boolean", "null"],
|
||||
},
|
||||
"on_close": {
|
||||
"description": "Action to execute on the VM is closed",
|
||||
"enum": ["power_off", "shutdown_signal", "save_vm_state"],
|
||||
@@ -380,6 +384,10 @@ QEMU_UPDATE_SCHEMA = {
|
||||
"description": "Replicate the network connection state for links in Qemu",
|
||||
"type": ["boolean", "null"],
|
||||
},
|
||||
"create_config_disk": {
|
||||
"description": "Automatically create a config disk on HDD disk interface (secondary slave)",
|
||||
"type": ["boolean", "null"],
|
||||
},
|
||||
"on_close": {
|
||||
"description": "Action to execute on the VM is closed",
|
||||
"enum": ["power_off", "shutdown_signal", "save_vm_state"],
|
||||
@@ -583,6 +591,10 @@ QEMU_OBJECT_SCHEMA = {
|
||||
"description": "Replicate the network connection state for links in Qemu",
|
||||
"type": "boolean",
|
||||
},
|
||||
"create_config_disk": {
|
||||
"description": "Automatically create a config disk on HDD disk interface (secondary slave)",
|
||||
"type": ["boolean", "null"],
|
||||
},
|
||||
"on_close": {
|
||||
"description": "Action to execute on the VM is closed",
|
||||
"enum": ["power_off", "shutdown_signal", "save_vm_state"],
|
||||
@@ -653,6 +665,7 @@ QEMU_OBJECT_SCHEMA = {
|
||||
"kernel_command_line",
|
||||
"legacy_networking",
|
||||
"replicate_network_connection_state",
|
||||
"create_config_disk",
|
||||
"on_close",
|
||||
"cpu_throttling",
|
||||
"process_priority",
|
||||
|
||||
@@ -116,7 +116,7 @@ QEMU_TEMPLATE_PROPERTIES = {
|
||||
"hda_disk_interface": {
|
||||
"description": "QEMU hda interface",
|
||||
"enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"],
|
||||
"default": "ide"
|
||||
"default": "none"
|
||||
},
|
||||
"hdb_disk_image": {
|
||||
"description": "QEMU hdb disk image path",
|
||||
@@ -126,7 +126,7 @@ QEMU_TEMPLATE_PROPERTIES = {
|
||||
"hdb_disk_interface": {
|
||||
"description": "QEMU hdb interface",
|
||||
"enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"],
|
||||
"default": "ide"
|
||||
"default": "none"
|
||||
},
|
||||
"hdc_disk_image": {
|
||||
"description": "QEMU hdc disk image path",
|
||||
@@ -136,7 +136,7 @@ QEMU_TEMPLATE_PROPERTIES = {
|
||||
"hdc_disk_interface": {
|
||||
"description": "QEMU hdc interface",
|
||||
"enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"],
|
||||
"default": "ide"
|
||||
"default": "none"
|
||||
},
|
||||
"hdd_disk_image": {
|
||||
"description": "QEMU hdd disk image path",
|
||||
@@ -146,7 +146,7 @@ QEMU_TEMPLATE_PROPERTIES = {
|
||||
"hdd_disk_interface": {
|
||||
"description": "QEMU hdd interface",
|
||||
"enum": ["ide", "sata", "nvme", "scsi", "sd", "mtd", "floppy", "pflash", "virtio", "none"],
|
||||
"default": "ide"
|
||||
"default": "none"
|
||||
},
|
||||
"cdrom_image": {
|
||||
"description": "QEMU cdrom image path",
|
||||
@@ -183,6 +183,11 @@ QEMU_TEMPLATE_PROPERTIES = {
|
||||
"type": "boolean",
|
||||
"default": True
|
||||
},
|
||||
"create_config_disk": {
|
||||
"description": "Automatically create a config disk on HDD disk interface (secondary slave)",
|
||||
"type": "boolean",
|
||||
"default": False
|
||||
},
|
||||
"on_close": {
|
||||
"description": "Action to execute on the VM is closed",
|
||||
"enum": ["power_off", "shutdown_signal", "save_vm_state"],
|
||||
|
||||
@@ -23,6 +23,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
@angular-react/core
|
||||
MIT
|
||||
|
||||
@angular/animations
|
||||
MIT
|
||||
|
||||
@@ -30,7 +33,7 @@ MIT
|
||||
MIT
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2020 Google LLC.
|
||||
Copyright (c) 2021 Google LLC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -67,7 +70,7 @@ MIT
|
||||
MIT
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2020 Google LLC.
|
||||
Copyright (c) 2021 Google LLC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -418,31 +421,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
angular2-hotkeys
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Nick Richardson
|
||||
|
||||
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.
|
||||
|
||||
|
||||
angular2-indexeddb
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
@@ -467,23 +445,12 @@ 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.
|
||||
|
||||
array-from
|
||||
MIT
|
||||
Copyright © 2015-2016 Studio B12 GmbH
|
||||
|
||||
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.
|
||||
|
||||
|
||||
bootstrap
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2020 Twitter, Inc.
|
||||
Copyright (c) 2011-2020 The Bootstrap Authors
|
||||
Copyright (c) 2011-2021 Twitter, Inc.
|
||||
Copyright (c) 2011-2021 The Bootstrap Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -504,6 +471,31 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
classnames
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Jed Watson
|
||||
|
||||
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.
|
||||
|
||||
|
||||
core-js
|
||||
MIT
|
||||
Copyright (c) 2014-2020 Denis Pushkarev
|
||||
@@ -527,31 +519,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
create-point-cb
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Quentin Engles
|
||||
|
||||
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.
|
||||
|
||||
|
||||
css-loader
|
||||
MIT
|
||||
Copyright JS Foundation and other contributors
|
||||
@@ -576,6 +543,31 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
css-to-style
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Jacob Buck
|
||||
|
||||
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.
|
||||
|
||||
|
||||
css-tree
|
||||
MIT
|
||||
Copyright (C) 2016-2019 by Roman Dvornov
|
||||
@@ -599,6 +591,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
d
|
||||
ISC
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2013-2019, Mariusz Nowak, @medikoo, medikoo.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
d3-array
|
||||
BSD-3-Clause
|
||||
Copyright 2010-2016 Mike Bostock
|
||||
@@ -1676,11 +1687,11 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
dom-mousemove-dispatcher
|
||||
dom-helpers
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Quentin Engles
|
||||
Copyright (c) 2015 Jason Quense
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -1700,76 +1711,64 @@ 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.
|
||||
|
||||
|
||||
dom-plane
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Quentin Engles
|
||||
|
||||
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.
|
||||
|
||||
|
||||
dom-set
|
||||
WTFPL
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2016 Quentin Engles <hollowdoor99@gmail.com>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
|
||||
|
||||
is-array
|
||||
eev
|
||||
MIT
|
||||
|
||||
iselement
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
es5-ext
|
||||
ISC
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2016 Riki Fridrich
|
||||
Copyright (c) 2011-2019, Mariusz Nowak, @medikoo, medikoo.com
|
||||
|
||||
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:
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
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" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS 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.
|
||||
|
||||
es6-symbol
|
||||
ISC
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2013-2019, Mariusz Nowak, @medikoo, medikoo.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
ext
|
||||
ISC
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2011-2019, Mariusz Nowak, @medikoo, medikoo.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
mousetrap
|
||||
@@ -1978,29 +1977,6 @@ ngx-childprocess
|
||||
MIT
|
||||
|
||||
ngx-device-detector
|
||||
MIT
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2016 Ahsan Ayaz
|
||||
|
||||
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.
|
||||
|
||||
|
||||
ngx-electron
|
||||
MIT
|
||||
@@ -2211,6 +2187,157 @@ Apache-2.0
|
||||
limitations under the License.
|
||||
|
||||
|
||||
object-assign
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
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.
|
||||
|
||||
|
||||
prop-types
|
||||
MIT
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-present, Facebook, Inc.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
prop-types-extra
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 react-bootstrap
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
react
|
||||
MIT
|
||||
MIT License
|
||||
|
||||
Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
react-bootstrap
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-present Stephen J. Collings, Matthew Honnibal, Pieter Vanderwerff
|
||||
|
||||
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.
|
||||
|
||||
|
||||
react-dom
|
||||
MIT
|
||||
MIT License
|
||||
|
||||
Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
regenerator-runtime
|
||||
MIT
|
||||
MIT License
|
||||
@@ -2674,6 +2801,31 @@ THE SOFTWARE.
|
||||
|
||||
|
||||
|
||||
scheduler
|
||||
MIT
|
||||
MIT License
|
||||
|
||||
Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
source-map
|
||||
BSD-3-Clause
|
||||
|
||||
@@ -2706,6 +2858,48 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
spark-md5
|
||||
WTFPL
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2015 André Cruz <amdfcruz@gmail.com>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
|
||||
stylenames
|
||||
MIT
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Kevin
|
||||
|
||||
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.
|
||||
|
||||
|
||||
svg-crowbar
|
||||
MIT
|
||||
Copyright (c) 2013 The New York Times
|
||||
@@ -2732,11 +2926,30 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
type-func
|
||||
type
|
||||
ISC
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2019, Mariusz Nowak, @medikoo, medikoo.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
uuid
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Quentin Engles
|
||||
Copyright (c) 2010-2016 Robert Kieffer 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
|
||||
@@ -2757,11 +2970,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
uuid
|
||||
warning
|
||||
MIT
|
||||
The MIT License (MIT)
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2010-2016 Robert Kieffer and other contributors
|
||||
Copyright (c) 2013-present, Facebook, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
|
After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
@@ -1,5 +1,18 @@
|
||||
GNS3 WebUI is web implementation of user interface for GNS3 software.
|
||||
|
||||
Current version: 2.2.18
|
||||
|
||||
Current version: 2020.4.0-beta.1
|
||||
|
||||
Bug Fixes & enhancements
|
||||
- symbol is not properly selected in change symbol dialog
|
||||
- issue when using the scroll wheel on the web console
|
||||
- missing settings for Docker nodes
|
||||
- error on servers page
|
||||
|
||||
What's new
|
||||
- double click nodes to open the console
|
||||
|
||||
Current version: 2020.3.0-beta.3
|
||||
|
||||
Bug Fixes & enhancements
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta charset="utf-8"/>
|
||||
<title>GNS3 Web UI</title>
|
||||
<!-- It's important to have base here because of the script below //-->
|
||||
<base href="/static/web-ui/">
|
||||
<base href="/static/web-ui/"/>
|
||||
|
||||
<script>
|
||||
var userAgent = navigator.userAgent.toLowerCase();
|
||||
@@ -20,8 +20,8 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="assets/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<link rel="icon" type="image/x-icon" href="assets/favicon.ico"/>
|
||||
|
||||
<script type="application/javascript">
|
||||
// Github Pages redirection
|
||||
@@ -33,12 +33,12 @@
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<link rel="stylesheet" href="styles.9197b66183f89522181b.css"></head>
|
||||
<link rel="stylesheet" href="styles.2067bd0f504703e2aa7c.css"><link rel="stylesheet" href="theme-default-dark.1f2e91a1c127fc1f87b5.css"><link rel="stylesheet" href="theme-default.69f8588c10246d5cabef.css"></head>
|
||||
<!-- <body class="mat-app-background" oncontextmenu="return false;"> -->
|
||||
<body class="mat-app-background" oncontextmenu="return false;">
|
||||
<app-root></app-root>
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-5D6FZL9923"></script>
|
||||
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-5D6FZL9923"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag()
|
||||
@@ -48,5 +48,5 @@
|
||||
|
||||
gtag('config', 'G-5D6FZL9923');
|
||||
</script>
|
||||
<script src="runtime.c51bd5b1c616d9ffddc1.js" defer></script><script src="polyfills-es5.fa7ed98c2915002d6a80.js" nomodule defer></script><script src="polyfills.e3de9c33e285997df00a.js" defer></script><script src="main.e7b089d7c8fa292097fb.js" defer></script></body>
|
||||
<script src="runtime.7425f237727658da0a30.js" defer></script><script src="polyfills-es5.b186ac526f152db6b6ba.js" nomodule defer></script><script src="polyfills.4fe1bb939733274d40c5.js" defer></script><script src="main.247c9bb34f8d82bc75ef.js" defer></script></body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{"+/L5":function(e,t,n){var r=n("t1UP").isCustomProperty,i=n("vd7W").TYPE,o=n("4njK").mode,a=i.Ident,s=i.Hash,c=i.Colon,l=i.Semicolon,u=i.Delim;function h(e){return this.Raw(e,o.exclamationMarkOrSemicolon,!0)}function d(e){return this.Raw(e,o.exclamationMarkOrSemicolon,!1)}function f(){var e=this.scanner.tokenIndex,t=this.Value();return"Raw"!==t.type&&!1===this.scanner.eof&&this.scanner.tokenType!==l&&!1===this.scanner.isDelim(33)&&!1===this.scanner.isBalanceEdge(e)&&this.error(),t}function p(){var e=this.scanner.tokenStart;if(this.scanner.tokenType===u)switch(this.scanner.source.charCodeAt(this.scanner.tokenStart)){case 42:case 36:case 43:case 35:case 38:this.scanner.next();break;case 47:this.scanner.next(),this.scanner.isDelim(47)&&this.scanner.next()}return this.eat(this.scanner.tokenType===s?s:a),this.scanner.substrToCursor(e)}function m(){this.eat(u),this.scanner.skipSC();var e=this.consume(a);return"important"===e||e}e.exports={name:"Declaration",structure:{important:[Boolean,String],property:String,value:["Value","Raw"]},parse:function(){var e,t=this.scanner.tokenStart,n=this.scanner.tokenIndex,i=p.call(this),o=r(i),a=o?this.parseCustomProperty:this.parseValue,s=o?d:h,u=!1;return this.scanner.skipSC(),this.eat(c),o||this.scanner.skipSC(),e=a?this.parseWithFallback(f,s):s.call(this,this.scanner.tokenIndex),this.scanner.isDelim(33)&&(u=m.call(this),this.scanner.skipSC()),!1===this.scanner.eof&&this.scanner.tokenType!==l&&!1===this.scanner.isBalanceEdge(n)&&this.error(),{type:"Declaration",loc:this.getLocation(t,this.scanner.tokenStart),important:u,property:i,value:e}},generate:function(e){this.chunk(e.property),this.chunk(":"),this.node(e.value),e.important&&this.chunk(!0===e.important?"!important":"!"+e.important)},walkContext:"declaration"}},"+4/i":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n("qCKp"),i=n("odkN");r.Observable.prototype.let=i.letProto,r.Observable.prototype.letBind=i.letProto},"+EXs":function(e,t,n){"use strict";function r(e){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}n.d(t,"a",function(){return o});var i=n("JL25");function o(e,t){return!t||"object"!==r(t)&&"function"!=typeof t?Object(i.a)(e):t}},"+Kd2":function(e,t,n){var r=n("vd7W").TYPE,i=n("4njK").mode,o=r.Comma;e.exports=function(){var e=this.createList();return this.scanner.skipSC(),e.push(this.Identifier()),this.scanner.skipSC(),this.scanner.tokenType===o&&(e.push(this.Operator()),e.push(this.parseCustomProperty?this.Value(null):this.Raw(this.scanner.tokenIndex,i.exclamationMarkOrSemicolon,!1))),e}},"+Wds":function(e,t,n){"use strict";var r=String.prototype.indexOf;e.exports=function(e){return r.call(this,e,arguments[1])>-1}},"+XMV":function(e,t,n){"use strict";e.exports=n("GOzd")()?String.prototype.contains:n("+Wds")},"+oeQ":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n("qCKp"),i=n("H+DX");r.Observable.prototype.observeOn=i.observeOn},"+psR":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n("qCKp"),i=n("16Oq");r.Observable.prototype.retry=i.retry},"+qxJ":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n("qCKp"),i=n("GsYY");r.Observable.prototype.distinctUntilChanged=i.distinctUntilChanged},"+v8i":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n("qCKp");r.Observable.concat=r.concat},"+wdc":function(e,t,n){"use strict";var r,i,o,a;if("object"==typeof performance&&"function"==typeof performance.now){var s=performance;t.unstable_now=function(){return s.now()}}else{var c=Date,l=c.now();t.unstable_now=function(){return c.now()-l}}if("undefined"==typeof window||"function"!=typeof MessageChannel){var u=null,h=null,d=function e(){if(null!==u)try{var n=t.unstable_now();u(!0,n),u=null}catch(r){throw setTimeout(e,0),r}};r=function(e){null!==u?setTimeout(r,0,e):(u=e,setTimeout(d,0))},i=function(e,t){h=setTimeout(e,t)},o=function(){clearTimeout(h)},t.unstable_shouldYield=function(){return!1},a=t.unstable_forceFrameRate=function(){}}else{var f=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var m=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"),"function"!=typeof m&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills")}var g=!1,v=null,b=-1,y=5,_=0;t.unstable_shouldYield=function(){return t.unstable_now()>=_},a=function(){},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a posiLine truncated
|
||||
@@ -1 +0,0 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{"+/L5":function(t,e,n){var i=n("t1UP").isCustomProperty,r=n("vd7W").TYPE,o=n("4njK").mode,a=r.Ident,s=r.Hash,c=r.Colon,l=r.Semicolon,u=r.Delim;function h(t){return this.Raw(t,o.exclamationMarkOrSemicolon,!0)}function d(t){return this.Raw(t,o.exclamationMarkOrSemicolon,!1)}function f(){var t=this.scanner.tokenIndex,e=this.Value();return"Raw"!==e.type&&!1===this.scanner.eof&&this.scanner.tokenType!==l&&!1===this.scanner.isDelim(33)&&!1===this.scanner.isBalanceEdge(t)&&this.error(),e}function p(){var t=this.scanner.tokenStart;if(this.scanner.tokenType===u)switch(this.scanner.source.charCodeAt(this.scanner.tokenStart)){case 42:case 36:case 43:case 35:case 38:this.scanner.next();break;case 47:this.scanner.next(),this.scanner.isDelim(47)&&this.scanner.next()}return this.eat(this.scanner.tokenType===s?s:a),this.scanner.substrToCursor(t)}function m(){this.eat(u),this.scanner.skipSC();var t=this.consume(a);return"important"===t||t}t.exports={name:"Declaration",structure:{important:[Boolean,String],property:String,value:["Value","Raw"]},parse:function(){var t,e=this.scanner.tokenStart,n=this.scanner.tokenIndex,r=p.call(this),o=i(r),a=o?this.parseCustomProperty:this.parseValue,s=o?d:h,u=!1;return this.scanner.skipSC(),this.eat(c),o||this.scanner.skipSC(),t=a?this.parseWithFallback(f,s):s.call(this,this.scanner.tokenIndex),this.scanner.isDelim(33)&&(u=m.call(this),this.scanner.skipSC()),!1===this.scanner.eof&&this.scanner.tokenType!==l&&!1===this.scanner.isBalanceEdge(n)&&this.error(),{type:"Declaration",loc:this.getLocation(e,this.scanner.tokenStart),important:u,property:r,value:t}},generate:function(t){this.chunk(t.property),this.chunk(":"),this.node(t.value),t.important&&this.chunk(!0===t.important?"!important":"!"+t.important)},walkContext:"declaration"}},"+4/i":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n("qCKp"),r=n("odkN");i.Observable.prototype.let=r.letProto,i.Observable.prototype.letBind=r.letProto},"+Kd2":function(t,e,n){var i=n("vd7W").TYPE,r=n("4njK").mode,o=i.Comma;t.exports=function(){var t=this.createList();return this.scanner.skipSC(),t.push(this.Identifier()),this.scanner.skipSC(),this.scanner.tokenType===o&&(t.push(this.Operator()),t.push(this.parseCustomProperty?this.Value(null):this.Raw(this.scanner.tokenIndex,r.exclamationMarkOrSemicolon,!1))),t}},"+oeQ":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n("qCKp"),r=n("H+DX");i.Observable.prototype.observeOn=r.observeOn},"+psR":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n("qCKp"),r=n("16Oq");i.Observable.prototype.retry=r.retry},"+qxJ":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n("qCKp"),r=n("GsYY");i.Observable.prototype.distinctUntilChanged=r.distinctUntilChanged},"+v8i":function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=n("qCKp");i.Observable.concat=i.concat},"/+5V":function(t,e){function n(t){function e(t){return null!==t&&("Type"===t.type||"Property"===t.type||"Keyword"===t.type)}var n=null;return null!==this.matched&&function i(r){if(Array.isArray(r.match)){for(var o=0;o<r.match.length;o++)if(i(r.match[o]))return e(r.syntax)&&n.unshift(r.syntax),!0}else if(r.node===t)return n=e(r.syntax)?[r.syntax]:[],!0;return!1}(this.matched),n}function i(t,e,i){var r=n.call(t,e);return null!==r&&r.some(i)}t.exports={getTrace:n,isType:function(t,e){return i(this,t,(function(t){return"Type"===t.type&&t.name===e}))},isProperty:function(t,e){return i(this,t,(function(t){return"Property"===t.type&&t.name===e}))},isKeyword:function(t){return i(this,t,(function(t){return"Keyword"===t.type}))}}},"/BcF":function(t,e){t.exports={name:"Selector",structure:{children:[["TypeSelector","IdSelector","ClassSelector","AttributeSelector","PseudoClassSelector","PseudoElementSelector","Combinator","WhiteSpace"]]},parse:function(){var t=this.readSequence(this.scope.Selector);return null===this.getFirstListNode(t)&&this.error("Selector is expected"),{type:"Selector",loc:this.getLocationFromList(t),children:t}},generate:function(t){this.children(t)}}},"/POA":function(t,e,n){window,t.exports=function(t){var e={};function n(i){if(e[i])return e[i].exports;var r=e[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(i,r,(function(e){return t[e]}).bind(null,r));return i},n.n=function(t){var e=t&&t.__esModuleLine truncated
|
||||
@@ -0,0 +1 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{"+5Eg":function(t,e,n){var r=n("wA6s"),o=n("6XUM"),i=n("M7Xk").onFreeze,a=n("cZY6"),c=n("rG8t"),u=Object.seal;r({target:"Object",stat:!0,forced:c(function(){u(1)}),sham:!a},{seal:function(t){return u&&o(t)?u(i(t)):t}})},"+IJR":function(t,e,n){n("wA6s")({target:"Number",stat:!0},{isNaN:function(t){return t!=t}})},"/AsP":function(t,e,n){var r=n("yIiL"),o=n("SDMg"),i=r("keys");t.exports=function(t){return i[t]||(i[t]=o(t))}},"/Ybd":function(t,e,n){var r=n("T69T"),o=n("XdSI"),i=n("F26l"),a=n("LdO1"),c=Object.defineProperty;e.f=r?c:function(t,e,n){if(i(t),e=a(e,!0),i(n),o)try{return c(t,e,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},"0Ds2":function(t,e,n){var r=n("m41k")("match");t.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[r]=!1,"/./"[t](e)}catch(o){}}return!1}},"0TWp":function(t,e,n){var r,o;void 0===(o="function"==typeof(r=function(){"use strict";!function(t){var e=t.performance;function n(t){e&&e.mark&&e.mark(t)}function r(t,n){e&&e.measure&&e.measure(t,n)}n("Zone");var o=t.__Zone_symbol_prefix||"__zone_symbol__";function i(t){return o+t}var a=!0===t[i("forceDuplicateZoneCheck")];if(t.Zone){if(a||"function"!=typeof t.Zone.__symbol__)throw new Error("Zone already loaded.");return t.Zone}var c=function(){function e(t,e){this._parent=t,this._name=e?e.name||"unnamed":"<root>",this._properties=e&&e.properties||{},this._zoneDelegate=new f(this,this._parent&&this._parent._zoneDelegate,e)}return e.assertZonePatched=function(){if(t.Promise!==M.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(e,"root",{get:function(){for(var t=e.current;t.parent;)t=t.parent;return t},enumerable:!1,configurable:!0}),Object.defineProperty(e,"current",{get:function(){return P.zone},enumerable:!1,configurable:!0}),Object.defineProperty(e,"currentTask",{get:function(){return I},enumerable:!1,configurable:!0}),e.__load_patch=function(o,i){if(M.hasOwnProperty(o)){if(a)throw Error("Already loaded patch: "+o)}else if(!t["__Zone_disable_"+o]){var c="Zone:"+o;n(c),M[o]=i(t,e,j),r(c,c)}},Object.defineProperty(e.prototype,"parent",{get:function(){return this._parent},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"name",{get:function(){return this._name},enumerable:!1,configurable:!0}),e.prototype.get=function(t){var e=this.getZoneWith(t);if(e)return e._properties[t]},e.prototype.getZoneWith=function(t){for(var e=this;e;){if(e._properties.hasOwnProperty(t))return e;e=e._parent}return null},e.prototype.fork=function(t){if(!t)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,t)},e.prototype.wrap=function(t,e){if("function"!=typeof t)throw new Error("Expecting function got: "+t);var n=this._zoneDelegate.intercept(this,t,e),r=this;return function(){return r.runGuarded(n,this,arguments,e)}},e.prototype.run=function(t,e,n,r){P={parent:P,zone:this};try{return this._zoneDelegate.invoke(this,t,e,n,r)}finally{P=P.parent}},e.prototype.runGuarded=function(t,e,n,r){void 0===e&&(e=null),P={parent:P,zone:this};try{try{return this._zoneDelegate.invoke(this,t,e,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{P=P.parent}},e.prototype.runTask=function(t,e,n){if(t.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(t.zone||b).name+"; Execution: "+this.name+")");if(t.state!==w||t.type!==A&&t.type!==O){var r=t.state!=x;r&&t._transitionTo(x,E),t.runCount++;var o=I;I=t,P={parent:P,zone:this};try{t.type==O&&t.data&&!t.data.isPeriodic&&(t.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,t,e,n)}catch(i){if(this._zoneDelegate.handleError(this,i))throw i}}finally{t.state!==w&&t.state!==_&&(t.type==A||t.data&&t.data.isPeriodic?r&&t._transitionTo(E,x):(t.runCount=0,this._updateTaskCount(t,-1),r&&t._transitionTo(w,x,w))),P=P.parent,I=o}}},e.prototype.scheduleTask=function(t){if(t.zone&&t.zone!==this)for(var e=this;e;){if(e===t.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+t.zone.name);e=e.parent}t._transitionTo(k,w);var n=[];t._zoneDelegates=n,t._zone=this;try{t=this._zoneDelegate.scheduleTask(this,t)}catch(r){throw t._transitionTo(_,k,w),this._zoneDelegate.handleError(this,r),r}return t._zoneDelegates===n&&this._updateTaskCount(t,1),t.state==k&&t._transitionTo(E,k),t},e.prototype.scheduleMicroTask=function(t,e,n,r){return this.scheduleTask(new l(T,t,e,n,r,void 0))},e.prototype.scheduleMacroTask=function(t,e,n,r,o){return this.scheduleTask(new l(O,t,e,n,r,o))},e.prototype.scheduleEventTask=function(t,e,n,r,o){return this.scheduleTask(new l(A,t,e,n,r,o))},e.protoLine truncated
|
||||
@@ -1 +0,0 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{"+5Eg":function(t,e,n){var r=n("wA6s"),o=n("6XUM"),i=n("M7Xk").onFreeze,a=n("cZY6"),c=n("rG8t"),u=Object.seal;r({target:"Object",stat:!0,forced:c((function(){u(1)})),sham:!a},{seal:function(t){return u&&o(t)?u(i(t)):t}})},"+IJR":function(t,e,n){n("wA6s")({target:"Number",stat:!0},{isNaN:function(t){return t!=t}})},"/AsP":function(t,e,n){var r=n("yIiL"),o=n("SDMg"),i=r("keys");t.exports=function(t){return i[t]||(i[t]=o(t))}},"/Ybd":function(t,e,n){var r=n("T69T"),o=n("XdSI"),i=n("F26l"),a=n("LdO1"),c=Object.defineProperty;e.f=r?c:function(t,e,n){if(i(t),e=a(e,!0),i(n),o)try{return c(t,e,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},"0Ds2":function(t,e,n){var r=n("m41k")("match");t.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[r]=!1,"/./"[t](e)}catch(o){}}return!1}},"0TWp":function(t,e,n){var r,o;void 0===(o="function"==typeof(r=function(){"use strict";!function(t){var e=t.performance;function n(t){e&&e.mark&&e.mark(t)}function r(t,n){e&&e.measure&&e.measure(t,n)}n("Zone");var o=t.__Zone_symbol_prefix||"__zone_symbol__";function i(t){return o+t}var a=!0===t[i("forceDuplicateZoneCheck")];if(t.Zone){if(a||"function"!=typeof t.Zone.__symbol__)throw new Error("Zone already loaded.");return t.Zone}var c=function(){function e(t,e){this._parent=t,this._name=e?e.name||"unnamed":"<root>",this._properties=e&&e.properties||{},this._zoneDelegate=new f(this,this._parent&&this._parent._zoneDelegate,e)}return e.assertZonePatched=function(){if(t.Promise!==M.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(e,"root",{get:function(){for(var t=e.current;t.parent;)t=t.parent;return t},enumerable:!0,configurable:!0}),Object.defineProperty(e,"current",{get:function(){return P.zone},enumerable:!0,configurable:!0}),Object.defineProperty(e,"currentTask",{get:function(){return I},enumerable:!0,configurable:!0}),e.__load_patch=function(o,i){if(M.hasOwnProperty(o)){if(a)throw Error("Already loaded patch: "+o)}else if(!t["__Zone_disable_"+o]){var c="Zone:"+o;n(c),M[o]=i(t,e,j),r(c,c)}},Object.defineProperty(e.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"name",{get:function(){return this._name},enumerable:!0,configurable:!0}),e.prototype.get=function(t){var e=this.getZoneWith(t);if(e)return e._properties[t]},e.prototype.getZoneWith=function(t){for(var e=this;e;){if(e._properties.hasOwnProperty(t))return e;e=e._parent}return null},e.prototype.fork=function(t){if(!t)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,t)},e.prototype.wrap=function(t,e){if("function"!=typeof t)throw new Error("Expecting function got: "+t);var n=this._zoneDelegate.intercept(this,t,e),r=this;return function(){return r.runGuarded(n,this,arguments,e)}},e.prototype.run=function(t,e,n,r){P={parent:P,zone:this};try{return this._zoneDelegate.invoke(this,t,e,n,r)}finally{P=P.parent}},e.prototype.runGuarded=function(t,e,n,r){void 0===e&&(e=null),P={parent:P,zone:this};try{try{return this._zoneDelegate.invoke(this,t,e,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{P=P.parent}},e.prototype.runTask=function(t,e,n){if(t.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(t.zone||b).name+"; Execution: "+this.name+")");if(t.state!==w||t.type!==A&&t.type!==O){var r=t.state!=x;r&&t._transitionTo(x,E),t.runCount++;var o=I;I=t,P={parent:P,zone:this};try{t.type==O&&t.data&&!t.data.isPeriodic&&(t.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,t,e,n)}catch(i){if(this._zoneDelegate.handleError(this,i))throw i}}finally{t.state!==w&&t.state!==_&&(t.type==A||t.data&&t.data.isPeriodic?r&&t._transitionTo(E,x):(t.runCount=0,this._updateTaskCount(t,-1),r&&t._transitionTo(w,x,w))),P=P.parent,I=o}}},e.prototype.scheduleTask=function(t){if(t.zone&&t.zone!==this)for(var e=this;e;){if(e===t.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+t.zone.name);e=e.parent}t._transitionTo(k,w);var n=[];t._zoneDelegates=n,t._zone=this;try{t=this._zoneDelegate.scheduleTask(this,t)}catch(r){throw t._transitionTo(_,k,w),this._zoneDelegate.handleError(this,r),r}return t._zoneDelegates===n&&this._updateTaskCount(t,1),t.state==k&&t._transitionTo(E,k),t},e.prototype.scheduleMicroTask=function(t,e,n,r){return this.scheduleTask(new l(T,t,e,n,r,void 0))},e.prototype.scheduleMacroTask=function(t,e,n,r,o){return this.scheduleTask(new l(O,t,e,n,r,o))},e.prototype.scheduleEventTask=function(t,e,n,r,o){return this.scheduleTask(new l(A,t,e,n,r,o))},e.proLine truncated
|
||||
@@ -0,0 +1 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{"0TWp":function(e,t,n){var r,o;void 0===(o="function"==typeof(r=function(){"use strict";!function(e){var t=e.performance;function n(e){t&&t.mark&&t.mark(e)}function r(e,n){t&&t.measure&&t.measure(e,n)}n("Zone");var o=e.__Zone_symbol_prefix||"__zone_symbol__";function a(e){return o+e}var i=!0===e[a("forceDuplicateZoneCheck")];if(e.Zone){if(i||"function"!=typeof e.Zone.__symbol__)throw new Error("Zone already loaded.");return e.Zone}var c=function(){function t(e,t){this._parent=e,this._name=t?t.name||"unnamed":"<root>",this._properties=t&&t.properties||{},this._zoneDelegate=new u(this,this._parent&&this._parent._zoneDelegate,t)}return t.assertZonePatched=function(){if(e.Promise!==D.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(t,"root",{get:function(){for(var e=t.current;e.parent;)e=e.parent;return e},enumerable:!1,configurable:!0}),Object.defineProperty(t,"current",{get:function(){return j.zone},enumerable:!1,configurable:!0}),Object.defineProperty(t,"currentTask",{get:function(){return z},enumerable:!1,configurable:!0}),t.__load_patch=function(o,a){if(D.hasOwnProperty(o)){if(i)throw Error("Already loaded patch: "+o)}else if(!e["__Zone_disable_"+o]){var c="Zone:"+o;n(c),D[o]=a(e,t,C),r(c,c)}},Object.defineProperty(t.prototype,"parent",{get:function(){return this._parent},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"name",{get:function(){return this._name},enumerable:!1,configurable:!0}),t.prototype.get=function(e){var t=this.getZoneWith(e);if(t)return t._properties[e]},t.prototype.getZoneWith=function(e){for(var t=this;t;){if(t._properties.hasOwnProperty(e))return t;t=t._parent}return null},t.prototype.fork=function(e){if(!e)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,e)},t.prototype.wrap=function(e,t){if("function"!=typeof e)throw new Error("Expecting function got: "+e);var n=this._zoneDelegate.intercept(this,e,t),r=this;return function(){return r.runGuarded(n,this,arguments,t)}},t.prototype.run=function(e,t,n,r){j={parent:j,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,r)}finally{j=j.parent}},t.prototype.runGuarded=function(e,t,n,r){void 0===t&&(t=null),j={parent:j,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{j=j.parent}},t.prototype.runTask=function(e,t,n){if(e.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(e.zone||m).name+"; Execution: "+this.name+")");if(e.state!==b||e.type!==Z&&e.type!==P){var r=e.state!=E;r&&e._transitionTo(E,T),e.runCount++;var o=z;z=e,j={parent:j,zone:this};try{e.type==P&&e.data&&!e.data.isPeriodic&&(e.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,e,t,n)}catch(a){if(this._zoneDelegate.handleError(this,a))throw a}}finally{e.state!==b&&e.state!==S&&(e.type==Z||e.data&&e.data.isPeriodic?r&&e._transitionTo(T,E):(e.runCount=0,this._updateTaskCount(e,-1),r&&e._transitionTo(b,E,b))),j=j.parent,z=o}}},t.prototype.scheduleTask=function(e){if(e.zone&&e.zone!==this)for(var t=this;t;){if(t===e.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+e.zone.name);t=t.parent}e._transitionTo(k,b);var n=[];e._zoneDelegates=n,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(r){throw e._transitionTo(S,k,b),this._zoneDelegate.handleError(this,r),r}return e._zoneDelegates===n&&this._updateTaskCount(e,1),e.state==k&&e._transitionTo(T,k),e},t.prototype.scheduleMicroTask=function(e,t,n,r){return this.scheduleTask(new p(O,e,t,n,r,void 0))},t.prototype.scheduleMacroTask=function(e,t,n,r,o){return this.scheduleTask(new p(P,e,t,n,r,o))},t.prototype.scheduleEventTask=function(e,t,n,r,o){return this.scheduleTask(new p(Z,e,t,n,r,o))},t.prototype.cancelTask=function(e){if(e.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(e.zone||m).name+"; Execution: "+this.name+")");e._transitionTo(w,T,E);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(S,w),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(b,w),e.runCount=0,e},t.prototype._updateTaskCount=function(e,t){var n=e._zoneDelegates;-1==t&&(e._zoneDelegates=null);for(var r=0;r<n.length;r++)n[r]._updateTaskCount(e.type,t)},t}();c.__symbol__=a;var s,l={name:"",onHasTask:function(e,t,n,r){return e.hasTask(n,r)},onScheduleTask:function(e,t,n,r){return e.scheduleTask(n,r)},onInvokeTask:function(e,t,n,r,o,a){return e.invokeTask(n,r,o,a)},onCancelTask:function(e,t,n,r){return e.cancelTask(n,r)}},u=function(){function e(e,t,n){this._taskCounts=Line truncated
|
||||
@@ -1 +0,0 @@
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{"0TWp":function(e,t,n){var r,o;void 0===(o="function"==typeof(r=function(){"use strict";!function(e){var t=e.performance;function n(e){t&&t.mark&&t.mark(e)}function r(e,n){t&&t.measure&&t.measure(e,n)}n("Zone");var o=e.__Zone_symbol_prefix||"__zone_symbol__";function a(e){return o+e}var i=!0===e[a("forceDuplicateZoneCheck")];if(e.Zone){if(i||"function"!=typeof e.Zone.__symbol__)throw new Error("Zone already loaded.");return e.Zone}var s=function(){function t(e,t){this._parent=e,this._name=t?t.name||"unnamed":"<root>",this._properties=t&&t.properties||{},this._zoneDelegate=new u(this,this._parent&&this._parent._zoneDelegate,t)}return t.assertZonePatched=function(){if(e.Promise!==D.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")},Object.defineProperty(t,"root",{get:function(){for(var e=t.current;e.parent;)e=e.parent;return e},enumerable:!0,configurable:!0}),Object.defineProperty(t,"current",{get:function(){return C.zone},enumerable:!0,configurable:!0}),Object.defineProperty(t,"currentTask",{get:function(){return z},enumerable:!0,configurable:!0}),t.__load_patch=function(o,a){if(D.hasOwnProperty(o)){if(i)throw Error("Already loaded patch: "+o)}else if(!e["__Zone_disable_"+o]){var s="Zone:"+o;n(s),D[o]=a(e,t,j),r(s,s)}},Object.defineProperty(t.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"name",{get:function(){return this._name},enumerable:!0,configurable:!0}),t.prototype.get=function(e){var t=this.getZoneWith(e);if(t)return t._properties[e]},t.prototype.getZoneWith=function(e){for(var t=this;t;){if(t._properties.hasOwnProperty(e))return t;t=t._parent}return null},t.prototype.fork=function(e){if(!e)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,e)},t.prototype.wrap=function(e,t){if("function"!=typeof e)throw new Error("Expecting function got: "+e);var n=this._zoneDelegate.intercept(this,e,t),r=this;return function(){return r.runGuarded(n,this,arguments,t)}},t.prototype.run=function(e,t,n,r){C={parent:C,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,r)}finally{C=C.parent}},t.prototype.runGuarded=function(e,t,n,r){void 0===t&&(t=null),C={parent:C,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{C=C.parent}},t.prototype.runTask=function(e,t,n){if(e.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(e.zone||m).name+"; Execution: "+this.name+")");if(e.state!==b||e.type!==Z&&e.type!==P){var r=e.state!=E;r&&e._transitionTo(E,T),e.runCount++;var o=z;z=e,C={parent:C,zone:this};try{e.type==P&&e.data&&!e.data.isPeriodic&&(e.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,e,t,n)}catch(a){if(this._zoneDelegate.handleError(this,a))throw a}}finally{e.state!==b&&e.state!==S&&(e.type==Z||e.data&&e.data.isPeriodic?r&&e._transitionTo(T,E):(e.runCount=0,this._updateTaskCount(e,-1),r&&e._transitionTo(b,E,b))),C=C.parent,z=o}}},t.prototype.scheduleTask=function(e){if(e.zone&&e.zone!==this)for(var t=this;t;){if(t===e.zone)throw Error("can not reschedule task to "+this.name+" which is descendants of the original zone "+e.zone.name);t=t.parent}e._transitionTo(k,b);var n=[];e._zoneDelegates=n,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(r){throw e._transitionTo(S,k,b),this._zoneDelegate.handleError(this,r),r}return e._zoneDelegates===n&&this._updateTaskCount(e,1),e.state==k&&e._transitionTo(T,k),e},t.prototype.scheduleMicroTask=function(e,t,n,r){return this.scheduleTask(new p(O,e,t,n,r,void 0))},t.prototype.scheduleMacroTask=function(e,t,n,r,o){return this.scheduleTask(new p(P,e,t,n,r,o))},t.prototype.scheduleEventTask=function(e,t,n,r,o){return this.scheduleTask(new p(Z,e,t,n,r,o))},t.prototype.cancelTask=function(e){if(e.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(e.zone||m).name+"; Execution: "+this.name+")");e._transitionTo(w,T,E);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(S,w),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(b,w),e.runCount=0,e},t.prototype._updateTaskCount=function(e,t){var n=e._zoneDelegates;-1==t&&(e._zoneDelegates=null);for(var r=0;r<n.length;r++)n[r]._updateTaskCount(e.type,t)},t}();s.__symbol__=a;var c,l={name:"",onHasTask:function(e,t,n,r){return e.hasTask(n,r)},onScheduleTask:function(e,t,n,r){return e.scheduleTask(n,r)},onInvokeTask:function(e,t,n,r,o,a){return e.invokeTask(n,r,o,a)},onCancelTask:function(e,t,n,r){return e.cancelTask(n,r)}},u=function(){function e(e,t,n){this._taskCounts=Line truncated
|
||||
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap v4.6.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,Liberation Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline-item{display:inLine truncated
|
||||
@@ -1,6 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap v4.5.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]),a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem}.display-1,.display-2{font-weight:300;line-height:1.2}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-3,.display-4{font-weight:300;line-height:1.2}.display-4{font-size:3.5rem}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5Line truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
@font-face{font-family:Material Icons;font-style:normal;font-weight:400;src:url(MaterialIcons-Regular.4674f8ded773cb03e824.eot);src:local("Material Icons"),local("MaterialIcons-Regular"),url(MaterialIcons-Regular.cff684e59ffb052d72cb.woff2) format("woff2"),url(MaterialIcons-Regular.83bebaf37c09c7e1c3ee.woff) format("woff"),url(MaterialIcons-Regular.5e7382c63da0098d634a.ttf) format("truetype")}.material-icons{font-family:Material Icons;font-weight:400;font-style:normal;font-size:24px;display:inline-block;line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:"liga"}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:100;src:local("Roboto Thin "),local("Roboto-Thin"),url(roboto-latin-100.c2aa4ab115bf9c6057cb.woff2) format("woff2"),url(roboto-latin-100.a45108d3b34af91f9113.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:100;src:local("Roboto Thin italic"),local("Roboto-Thinitalic"),url(roboto-latin-100italic.7f839a8652da29745ce4.woff2) format("woff2"),url(roboto-latin-100italic.451d4e559d6f57cdf6a1.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:300;src:local("Roboto Light "),local("Roboto-Light"),url(roboto-latin-300.37a7069dc30fc663c878.woff2) format("woff2"),url(roboto-latin-300.865f928cbabcc9f8f2b5.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:300;src:local("Roboto Light italic"),local("Roboto-Lightitalic"),url(roboto-latin-300italic.c64e7e354c88e613c77c.woff2) format("woff2"),url(roboto-latin-300italic.bd5b7a13f2c52b531a2a.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:400;src:local("Roboto Regular "),local("Roboto-Regular"),url(roboto-latin-400.176f8f5bd5f02b3abfcf.woff2) format("woff2"),url(roboto-latin-400.49ae34d4cc6b98c00c69.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:400;src:local("Roboto Regular italic"),local("Roboto-Regularitalic"),url(roboto-latin-400italic.d022bc70dc1bf7b3425d.woff2) format("woff2"),url(roboto-latin-400italic.b1d9d9904bfca8802a63.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:500;src:local("Roboto Medium "),local("Roboto-Medium"),url(roboto-latin-500.f5b74d7ffcdf85b9dd60.woff2) format("woff2"),url(roboto-latin-500.cea99d3e3e13a3a599a0.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:500;src:local("Roboto Medium italic"),local("Roboto-Mediumitalic"),url(roboto-latin-500italic.0d8bb5b3ee5f5dac9e44.woff2) format("woff2"),url(roboto-latin-500italic.18d00f739ff1e1c52db1.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:700;src:local("Roboto Bold "),local("Roboto-Bold"),url(roboto-latin-700.c18ee39fb002ad58b6dc.woff2) format("woff2"),url(roboto-latin-700.2267169ee7270a22a963.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:700;src:local("Roboto Bold italic"),local("Roboto-Bolditalic"),url(roboto-latin-700italic.7d8125ff7f707231fd89.woff2) format("woff2"),url(roboto-latin-700italic.9360531f9bb817f917f0.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:900;src:local("Roboto Black "),local("Roboto-Black"),url(roboto-latin-900.870c8c1486f76054301a.woff2) format("woff2"),url(roboto-latin-900.bac8362e7a6ea60b6983.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:900;src:local("Roboto Black italic"),local("Roboto-Blackitalic"),url(roboto-latin-900italic.cb5ad999740e9d8a8bd1.woff2) format("woff2"),url(roboto-latin-900italic.c20d916c1a1b094c1cec.woff) format("woff")}.mat-badge-content{font-weight:600;font-size:12px;font-family:Roboto,Helvetica Neue,sans-serif}.mat-badge-small .mat-badge-content{font-size:9px}.mat-badge-large .mat-badge-content{font-size:24px}.mat-h1,.mat-headline,.mat-typography h1{font:400 24px/32px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h2,.mat-title,.mat-typography h2{font:500 20px/32px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h3,.mat-subheading-2,.mat-typography h3{font:400 16px/28px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h4,.mat-subheading-1,.mat-typography h4{font:400 15px/24px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h5,.mat-typography h5{font:400 calc(14px * .83)/20px Roboto,Helvetica Neue,sans-serif;margin:0 0 12px}.mat-h6,.mat-typography h6{font:400 calc(14px * .67)/20px Roboto,Helvetica Neue,sans-serif;margin:0 0 12px}.mat-body-2,.mat-body-strong{font:500 14px/24px Roboto,HeLine truncated
|
||||
/*!*/}@keyframes cdk-text-field-autofill-start{
|
||||
/*!*/}@-webkit-keyframes cdk-text-field-autofill-end{
|
||||
/*!*/}@keyframes cdk-text-field-autofill-end{
|
||||
/*!*/}.cdk-text-field-autofill-monitored:-webkit-autofill{-webkit-animation:cdk-text-field-autofill-start 0s 1ms;animation:cdk-text-field-autofill-start 0s 1ms}.cdk-text-field-autofill-monitored:not(:-webkit-autofill){-webkit-animation:cdk-text-field-autofill-end 0s 1ms;animation:cdk-text-field-autofill-end 0s 1ms}textarea.cdk-textarea-autosize{resize:none}textarea.cdk-textarea-autosize-measuring{padding:2px 0!important;box-sizing:content-box!important;height:auto!important;overflow:hidden!important}textarea.cdk-textarea-autosize-measuring-firefox{padding:2px 0!important;box-sizing:content-box!important;height:0!important}.mat-focus-indicator,.mat-mdc-focus-indicator{position:relative}.mat-ripple-element{background-color:hsla(0,0%,100%,.1)}.mat-option{color:#fff}.mat-option.mat-active,.mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled),.mat-option:focus:not(.mat-option-disabled),.mat-option:hover:not(.mat-option-disabled){background:hsla(0,0%,100%,.04)}.mat-option.mat-active{color:#fff}.mat-option.mat-option-disabled{color:hsla(0,0%,100%,.5)}.mat-primary .mat-option.mat-selected:not(.mat-option-disabled){color:#0097a7}.mat-accent .mat-option.mat-selected:not(.mat-option-disabled){color:#b0bec5}.mat-warn .mat-option.mat-selected:not(.mat-option-disabled){color:#f44336}.mat-optgroup-label{color:hsla(0,0%,100%,.7)}.mat-optgroup-disabled .mat-optgroup-label{color:hsla(0,0%,100%,.5)}.mat-pseudo-checkbox{color:hsla(0,0%,100%,.7)}.mat-pseudo-checkbox:after{color:#263238}.mat-pseudo-checkbox-disabled{color:#686868}.mat-primary .mat-pseudo-checkbox-checked,.mat-primary .mat-pseudo-checkbox-indeterminate{background:#0097a7}.mat-accent .mat-pseudo-checkbox-checked,.mat-accent .mat-pseudo-checkbox-indeterminate,.mat-pseudo-checkbox-checked,.mat-pseudo-checkbox-indeterminate{background:#b0bec5}.mat-warn .mat-pseudo-checkbox-checked,.mat-warn .mat-pseudo-checkbox-indeterminate{background:#f44336}.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-disabled,.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-disabled{background:#686868}.mat-app-background{background-color:#263238;color:#fff}.mat-elevation-z0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.mat-elevation-z1{box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12)}.mat-elevation-z2{box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)}.mat-elevation-z3{box-shadow:0 3px 3px -2px rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.14),0 1px 8px 0 rgba(0,0,0,.12)}.mat-elevation-z4{box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}.mat-elevation-z5{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 5px 8px 0 rgba(0,0,0,.14),0 1px 14px 0 rgba(0,0,0,.12)}.mat-elevation-z6{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12)}.mat-elevation-z7{box-shadow:0 4px 5px -2px rgba(0,0,0,.2),0 7px 10px 1px rgba(0,0,0,.14),0 2px 16px 1px rgba(0,0,0,.12)}.mat-elevation-z8{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.mat-elevation-z9{box-shadow:0 5px 6px -3px rgba(0,0,0,.2),0 9px 12px 1px rgba(0,0,0,.14),0 3px 16px 2px rgba(0,0,0,.12)}.mat-elevation-z10{box-shadow:0 6px 6px -3px rgba(0,0,0,.2),0 10px 14px 1px rgba(0,0,0,.14),0 4px 18px 3px rgba(0,0,0,.12)}.mat-elevation-z11{box-shadow:0 6px 7px -4px rgba(0,0,0,.2),0 11px 15px 1px rgba(0,0,0,.14),0 4px 20px 3px rgba(0,0,0,.12)}.mat-elevation-z12{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 12px 17px 2px rgba(0,0,0,.14),0 5px 22px 4px rgba(0,0,0,.12)}.mat-elevation-z13{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 13px 19px 2px rgba(0,0,0,.14),0 5px 24px 4px rgba(0,0,0,.12)}.mat-elevation-z14{box-shadow:0 7px 9px -4px rgba(0,0,0,.2),0 14px 21px 2px rgba(0,0,0,.14),0 5px 26px 4px rgba(0,0,0,.12)}.mat-elevation-z15{box-shadow:0 8px 9px -5px rgba(0,0,0,.2),0 15px 22px 2px rgba(0,0,0,.14),0 6px 28px 5px rgba(0,0,0,.12)}.mat-elevation-z16{box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}.mat-elevation-z17{box-shadow:0 8px 11px -5px rgba(0,0,0,.2),0 17px 26px 2px rgba(0,0,0,.14),0 6px 32px 5px rgba(0,0,0,.12)}.mat-elevation-z18{box-shadow:0 9px 11px -5px rgba(0,0,0,.2),0 18px 28px 2px rgba(0,0,0,.14),0 7px 34px 6px rgba(0,0,0,.12)}.mat-elevation-z19{box-shadow:0 9px 12px -6px rgba(0,0,0,.2),0 19px 29px 2px rgba(0,0,0,.14),0 7px 36px 6px rgba(0,0,0,.12)}.mat-elevation-z20{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 20px 31px 3px rgba(0,0,0,.14),0 8px 38px 7px rgba(0,0,0,.12)}.mat-elevation-z21{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 21px 33px 3px rgba(0,0,0,.14),0 8px 40px 7px rgba(0,0,0,.12)}.mat-elevation-z22{box-shadow:0 10px 14px -6px rgba(0,0,0,.2),0 22px 35px 3px rgba(0,0,0,.14),0 8px 42px 7px rgba(0,0,0,.12)}.mat-elevation-z23{box-shadow:0 11px 14px -7px rgba(0,0,0,.2),0 23px 36px 3px rgba(0,0,0,.14),Line truncated
|
||||
@@ -1,5 +0,0 @@
|
||||
@font-face{font-family:Material Icons;font-style:normal;font-weight:400;src:url(MaterialIcons-Regular.4674f8ded773cb03e824.eot);src:local("Material Icons"),local("MaterialIcons-Regular"),url(MaterialIcons-Regular.cff684e59ffb052d72cb.woff2) format("woff2"),url(MaterialIcons-Regular.83bebaf37c09c7e1c3ee.woff) format("woff"),url(MaterialIcons-Regular.5e7382c63da0098d634a.ttf) format("truetype")}.material-icons{font-family:Material Icons;font-weight:400;font-style:normal;font-size:24px;display:inline-block;line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:"liga"}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:100;src:local("Roboto Thin "),local("Roboto-Thin"),url(roboto-latin-100.c2aa4ab115bf9c6057cb.woff2) format("woff2"),url(roboto-latin-100.a45108d3b34af91f9113.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:100;src:local("Roboto Thin italic"),local("Roboto-Thinitalic"),url(roboto-latin-100italic.7f839a8652da29745ce4.woff2) format("woff2"),url(roboto-latin-100italic.451d4e559d6f57cdf6a1.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:300;src:local("Roboto Light "),local("Roboto-Light"),url(roboto-latin-300.37a7069dc30fc663c878.woff2) format("woff2"),url(roboto-latin-300.865f928cbabcc9f8f2b5.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:300;src:local("Roboto Light italic"),local("Roboto-Lightitalic"),url(roboto-latin-300italic.c64e7e354c88e613c77c.woff2) format("woff2"),url(roboto-latin-300italic.bd5b7a13f2c52b531a2a.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:400;src:local("Roboto Regular "),local("Roboto-Regular"),url(roboto-latin-400.176f8f5bd5f02b3abfcf.woff2) format("woff2"),url(roboto-latin-400.49ae34d4cc6b98c00c69.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:400;src:local("Roboto Regular italic"),local("Roboto-Regularitalic"),url(roboto-latin-400italic.d022bc70dc1bf7b3425d.woff2) format("woff2"),url(roboto-latin-400italic.b1d9d9904bfca8802a63.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:500;src:local("Roboto Medium "),local("Roboto-Medium"),url(roboto-latin-500.f5b74d7ffcdf85b9dd60.woff2) format("woff2"),url(roboto-latin-500.cea99d3e3e13a3a599a0.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:500;src:local("Roboto Medium italic"),local("Roboto-Mediumitalic"),url(roboto-latin-500italic.0d8bb5b3ee5f5dac9e44.woff2) format("woff2"),url(roboto-latin-500italic.18d00f739ff1e1c52db1.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:700;src:local("Roboto Bold "),local("Roboto-Bold"),url(roboto-latin-700.c18ee39fb002ad58b6dc.woff2) format("woff2"),url(roboto-latin-700.2267169ee7270a22a963.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:700;src:local("Roboto Bold italic"),local("Roboto-Bolditalic"),url(roboto-latin-700italic.7d8125ff7f707231fd89.woff2) format("woff2"),url(roboto-latin-700italic.9360531f9bb817f917f0.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:900;src:local("Roboto Black "),local("Roboto-Black"),url(roboto-latin-900.870c8c1486f76054301a.woff2) format("woff2"),url(roboto-latin-900.bac8362e7a6ea60b6983.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:900;src:local("Roboto Black italic"),local("Roboto-Blackitalic"),url(roboto-latin-900italic.cb5ad999740e9d8a8bd1.woff2) format("woff2"),url(roboto-latin-900italic.c20d916c1a1b094c1cec.woff) format("woff")}.mat-badge-content{font-weight:600;font-size:12px;font-family:Roboto,Helvetica Neue,sans-serif}.mat-badge-small .mat-badge-content{font-size:9px}.mat-badge-large .mat-badge-content{font-size:24px}.mat-h1,.mat-headline,.mat-typography h1{font:400 24px/32px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h2,.mat-title,.mat-typography h2{font:500 20px/32px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h3,.mat-subheading-2,.mat-typography h3{font:400 16px/28px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h4,.mat-subheading-1,.mat-typography h4{font:400 15px/24px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h5,.mat-typography h5{font:400 calc(14px * .83)/20px Roboto,Helvetica Neue,sans-serif;margin:0 0 12px}.mat-h6,.mat-typography h6{font:400 calc(14px * .67)/20px Roboto,Helvetica Neue,sans-serif;margin:0 0 12px}.mat-body-2,.mat-body-strong{font:500 14px/24px Roboto,HeLine truncated
|
||||
/*!*/}@keyframes cdk-text-field-autofill-start{
|
||||
/*!*/}@-webkit-keyframes cdk-text-field-autofill-end{
|
||||
/*!*/}@keyframes cdk-text-field-autofill-end{
|
||||
/*!*/}.cdk-text-field-autofill-monitored:-webkit-autofill{-webkit-animation:cdk-text-field-autofill-start 0s 1ms;animation:cdk-text-field-autofill-start 0s 1ms}.cdk-text-field-autofill-monitored:not(:-webkit-autofill){-webkit-animation:cdk-text-field-autofill-end 0s 1ms;animation:cdk-text-field-autofill-end 0s 1ms}textarea.cdk-textarea-autosize{resize:none}textarea.cdk-textarea-autosize-measuring{padding:2px 0!important;box-sizing:content-box!important;height:auto!important;overflow:hidden!important}textarea.cdk-textarea-autosize-measuring-firefox{padding:2px 0!important;box-sizing:content-box!important;height:0!important}.mat-focus-indicator,.mat-mdc-focus-indicator{position:relative}.mat-ripple-element{background-color:hsla(0,0%,100%,.1)}.mat-option{color:#fff}.mat-option.mat-active,.mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled),.mat-option:focus:not(.mat-option-disabled),.mat-option:hover:not(.mat-option-disabled){background:hsla(0,0%,100%,.04)}.mat-option.mat-active{color:#fff}.mat-option.mat-option-disabled{color:hsla(0,0%,100%,.5)}.mat-primary .mat-option.mat-selected:not(.mat-option-disabled){color:#0097a7}.mat-accent .mat-option.mat-selected:not(.mat-option-disabled){color:#b0bec5}.mat-warn .mat-option.mat-selected:not(.mat-option-disabled){color:#f44336}.mat-optgroup-label{color:hsla(0,0%,100%,.7)}.mat-optgroup-disabled .mat-optgroup-label{color:hsla(0,0%,100%,.5)}.mat-pseudo-checkbox{color:hsla(0,0%,100%,.7)}.mat-pseudo-checkbox:after{color:#263238}.mat-pseudo-checkbox-disabled{color:#686868}.mat-primary .mat-pseudo-checkbox-checked,.mat-primary .mat-pseudo-checkbox-indeterminate{background:#0097a7}.mat-accent .mat-pseudo-checkbox-checked,.mat-accent .mat-pseudo-checkbox-indeterminate,.mat-pseudo-checkbox-checked,.mat-pseudo-checkbox-indeterminate{background:#b0bec5}.mat-warn .mat-pseudo-checkbox-checked,.mat-warn .mat-pseudo-checkbox-indeterminate{background:#f44336}.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-disabled,.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-disabled{background:#686868}.mat-app-background{background-color:#263238;color:#fff}.mat-elevation-z0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.mat-elevation-z1{box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12)}.mat-elevation-z2{box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)}.mat-elevation-z3{box-shadow:0 3px 3px -2px rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.14),0 1px 8px 0 rgba(0,0,0,.12)}.mat-elevation-z4{box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}.mat-elevation-z5{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 5px 8px 0 rgba(0,0,0,.14),0 1px 14px 0 rgba(0,0,0,.12)}.mat-elevation-z6{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12)}.mat-elevation-z7{box-shadow:0 4px 5px -2px rgba(0,0,0,.2),0 7px 10px 1px rgba(0,0,0,.14),0 2px 16px 1px rgba(0,0,0,.12)}.mat-elevation-z8{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.mat-elevation-z9{box-shadow:0 5px 6px -3px rgba(0,0,0,.2),0 9px 12px 1px rgba(0,0,0,.14),0 3px 16px 2px rgba(0,0,0,.12)}.mat-elevation-z10{box-shadow:0 6px 6px -3px rgba(0,0,0,.2),0 10px 14px 1px rgba(0,0,0,.14),0 4px 18px 3px rgba(0,0,0,.12)}.mat-elevation-z11{box-shadow:0 6px 7px -4px rgba(0,0,0,.2),0 11px 15px 1px rgba(0,0,0,.14),0 4px 20px 3px rgba(0,0,0,.12)}.mat-elevation-z12{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 12px 17px 2px rgba(0,0,0,.14),0 5px 22px 4px rgba(0,0,0,.12)}.mat-elevation-z13{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 13px 19px 2px rgba(0,0,0,.14),0 5px 24px 4px rgba(0,0,0,.12)}.mat-elevation-z14{box-shadow:0 7px 9px -4px rgba(0,0,0,.2),0 14px 21px 2px rgba(0,0,0,.14),0 5px 26px 4px rgba(0,0,0,.12)}.mat-elevation-z15{box-shadow:0 8px 9px -5px rgba(0,0,0,.2),0 15px 22px 2px rgba(0,0,0,.14),0 6px 28px 5px rgba(0,0,0,.12)}.mat-elevation-z16{box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}.mat-elevation-z17{box-shadow:0 8px 11px -5px rgba(0,0,0,.2),0 17px 26px 2px rgba(0,0,0,.14),0 6px 32px 5px rgba(0,0,0,.12)}.mat-elevation-z18{box-shadow:0 9px 11px -5px rgba(0,0,0,.2),0 18px 28px 2px rgba(0,0,0,.14),0 7px 34px 6px rgba(0,0,0,.12)}.mat-elevation-z19{box-shadow:0 9px 12px -6px rgba(0,0,0,.2),0 19px 29px 2px rgba(0,0,0,.14),0 7px 36px 6px rgba(0,0,0,.12)}.mat-elevation-z20{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 20px 31px 3px rgba(0,0,0,.14),0 8px 38px 7px rgba(0,0,0,.12)}.mat-elevation-z21{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 21px 33px 3px rgba(0,0,0,.14),0 8px 40px 7px rgba(0,0,0,.12)}.mat-elevation-z22{box-shadow:0 10px 14px -6px rgba(0,0,0,.2),0 22px 35px 3px rgba(0,0,0,.14),0 8px 42px 7px rgba(0,0,0,.12)}.mat-elevation-z23{box-shadow:0 11px 14px -7px rgba(0,0,0,.2),0 23px 36px 3px rgba(0,0,0,.14),Line truncated
|
||||
@@ -0,0 +1,5 @@
|
||||
@font-face{font-family:Material Icons;font-style:normal;font-weight:400;src:url(MaterialIcons-Regular.4674f8ded773cb03e824.eot);src:local("Material Icons"),local("MaterialIcons-Regular"),url(MaterialIcons-Regular.cff684e59ffb052d72cb.woff2) format("woff2"),url(MaterialIcons-Regular.83bebaf37c09c7e1c3ee.woff) format("woff"),url(MaterialIcons-Regular.5e7382c63da0098d634a.ttf) format("truetype")}.material-icons{font-family:Material Icons;font-weight:400;font-style:normal;font-size:24px;display:inline-block;line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:"liga"}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:100;src:local("Roboto Thin "),local("Roboto-Thin"),url(roboto-latin-100.c2aa4ab115bf9c6057cb.woff2) format("woff2"),url(roboto-latin-100.a45108d3b34af91f9113.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:100;src:local("Roboto Thin italic"),local("Roboto-Thinitalic"),url(roboto-latin-100italic.7f839a8652da29745ce4.woff2) format("woff2"),url(roboto-latin-100italic.451d4e559d6f57cdf6a1.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:300;src:local("Roboto Light "),local("Roboto-Light"),url(roboto-latin-300.37a7069dc30fc663c878.woff2) format("woff2"),url(roboto-latin-300.865f928cbabcc9f8f2b5.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:300;src:local("Roboto Light italic"),local("Roboto-Lightitalic"),url(roboto-latin-300italic.c64e7e354c88e613c77c.woff2) format("woff2"),url(roboto-latin-300italic.bd5b7a13f2c52b531a2a.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:400;src:local("Roboto Regular "),local("Roboto-Regular"),url(roboto-latin-400.176f8f5bd5f02b3abfcf.woff2) format("woff2"),url(roboto-latin-400.49ae34d4cc6b98c00c69.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:400;src:local("Roboto Regular italic"),local("Roboto-Regularitalic"),url(roboto-latin-400italic.d022bc70dc1bf7b3425d.woff2) format("woff2"),url(roboto-latin-400italic.b1d9d9904bfca8802a63.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:500;src:local("Roboto Medium "),local("Roboto-Medium"),url(roboto-latin-500.f5b74d7ffcdf85b9dd60.woff2) format("woff2"),url(roboto-latin-500.cea99d3e3e13a3a599a0.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:500;src:local("Roboto Medium italic"),local("Roboto-Mediumitalic"),url(roboto-latin-500italic.0d8bb5b3ee5f5dac9e44.woff2) format("woff2"),url(roboto-latin-500italic.18d00f739ff1e1c52db1.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:700;src:local("Roboto Bold "),local("Roboto-Bold"),url(roboto-latin-700.c18ee39fb002ad58b6dc.woff2) format("woff2"),url(roboto-latin-700.2267169ee7270a22a963.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:700;src:local("Roboto Bold italic"),local("Roboto-Bolditalic"),url(roboto-latin-700italic.7d8125ff7f707231fd89.woff2) format("woff2"),url(roboto-latin-700italic.9360531f9bb817f917f0.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:900;src:local("Roboto Black "),local("Roboto-Black"),url(roboto-latin-900.870c8c1486f76054301a.woff2) format("woff2"),url(roboto-latin-900.bac8362e7a6ea60b6983.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:900;src:local("Roboto Black italic"),local("Roboto-Blackitalic"),url(roboto-latin-900italic.cb5ad999740e9d8a8bd1.woff2) format("woff2"),url(roboto-latin-900italic.c20d916c1a1b094c1cec.woff) format("woff")}.mat-badge-content{font-weight:600;font-size:12px;font-family:Roboto,Helvetica Neue,sans-serif}.mat-badge-small .mat-badge-content{font-size:9px}.mat-badge-large .mat-badge-content{font-size:24px}.mat-h1,.mat-headline,.mat-typography h1{font:400 24px/32px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h2,.mat-title,.mat-typography h2{font:500 20px/32px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h3,.mat-subheading-2,.mat-typography h3{font:400 16px/28px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h4,.mat-subheading-1,.mat-typography h4{font:400 15px/24px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h5,.mat-typography h5{font:400 calc(14px * .83)/20px Roboto,Helvetica Neue,sans-serif;margin:0 0 12px}.mat-h6,.mat-typography h6{font:400 calc(14px * .67)/20px Roboto,Helvetica Neue,sans-serif;margin:0 0 12px}.mat-body-2,.mat-body-strong{font:500 14px/24px Roboto,HeLine truncated
|
||||
/*!*/}@keyframes cdk-text-field-autofill-start{
|
||||
/*!*/}@-webkit-keyframes cdk-text-field-autofill-end{
|
||||
/*!*/}@keyframes cdk-text-field-autofill-end{
|
||||
/*!*/}.cdk-text-field-autofill-monitored:-webkit-autofill{-webkit-animation:cdk-text-field-autofill-start 0s 1ms;animation:cdk-text-field-autofill-start 0s 1ms}.cdk-text-field-autofill-monitored:not(:-webkit-autofill){-webkit-animation:cdk-text-field-autofill-end 0s 1ms;animation:cdk-text-field-autofill-end 0s 1ms}textarea.cdk-textarea-autosize{resize:none}textarea.cdk-textarea-autosize-measuring{padding:2px 0!important;box-sizing:content-box!important;height:auto!important;overflow:hidden!important}textarea.cdk-textarea-autosize-measuring-firefox{padding:2px 0!important;box-sizing:content-box!important;height:0!important}.mat-focus-indicator,.mat-mdc-focus-indicator{position:relative}.mat-ripple-element{background-color:rgba(0,0,0,.1)}.mat-option{color:rgba(0,0,0,.87)}.mat-option.mat-active,.mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled),.mat-option:focus:not(.mat-option-disabled),.mat-option:hover:not(.mat-option-disabled){background:hsla(0,0%,100%,.04)}.mat-option.mat-active{color:rgba(0,0,0,.87)}.mat-option.mat-option-disabled{color:rgba(0,0,0,.38)}.mat-primary .mat-option.mat-selected:not(.mat-option-disabled){color:#0097a7}.mat-accent .mat-option.mat-selected:not(.mat-option-disabled){color:#448aff}.mat-warn .mat-option.mat-selected:not(.mat-option-disabled){color:#f44336}.mat-optgroup-label{color:rgba(0,0,0,.54)}.mat-optgroup-disabled .mat-optgroup-label{color:rgba(0,0,0,.38)}.mat-pseudo-checkbox{color:rgba(0,0,0,.54)}.mat-pseudo-checkbox:after{color:#fff}.mat-pseudo-checkbox-disabled{color:#b0b0b0}.mat-primary .mat-pseudo-checkbox-checked,.mat-primary .mat-pseudo-checkbox-indeterminate{background:#0097a7}.mat-accent .mat-pseudo-checkbox-checked,.mat-accent .mat-pseudo-checkbox-indeterminate,.mat-pseudo-checkbox-checked,.mat-pseudo-checkbox-indeterminate{background:#448aff}.mat-warn .mat-pseudo-checkbox-checked,.mat-warn .mat-pseudo-checkbox-indeterminate{background:#f44336}.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-disabled,.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-disabled{background:#b0b0b0}.mat-app-background{background-color:#fff;color:rgba(0,0,0,.87)}.mat-elevation-z0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.mat-elevation-z1{box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12)}.mat-elevation-z2{box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)}.mat-elevation-z3{box-shadow:0 3px 3px -2px rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.14),0 1px 8px 0 rgba(0,0,0,.12)}.mat-elevation-z4{box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}.mat-elevation-z5{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 5px 8px 0 rgba(0,0,0,.14),0 1px 14px 0 rgba(0,0,0,.12)}.mat-elevation-z6{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12)}.mat-elevation-z7{box-shadow:0 4px 5px -2px rgba(0,0,0,.2),0 7px 10px 1px rgba(0,0,0,.14),0 2px 16px 1px rgba(0,0,0,.12)}.mat-elevation-z8{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.mat-elevation-z9{box-shadow:0 5px 6px -3px rgba(0,0,0,.2),0 9px 12px 1px rgba(0,0,0,.14),0 3px 16px 2px rgba(0,0,0,.12)}.mat-elevation-z10{box-shadow:0 6px 6px -3px rgba(0,0,0,.2),0 10px 14px 1px rgba(0,0,0,.14),0 4px 18px 3px rgba(0,0,0,.12)}.mat-elevation-z11{box-shadow:0 6px 7px -4px rgba(0,0,0,.2),0 11px 15px 1px rgba(0,0,0,.14),0 4px 20px 3px rgba(0,0,0,.12)}.mat-elevation-z12{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 12px 17px 2px rgba(0,0,0,.14),0 5px 22px 4px rgba(0,0,0,.12)}.mat-elevation-z13{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 13px 19px 2px rgba(0,0,0,.14),0 5px 24px 4px rgba(0,0,0,.12)}.mat-elevation-z14{box-shadow:0 7px 9px -4px rgba(0,0,0,.2),0 14px 21px 2px rgba(0,0,0,.14),0 5px 26px 4px rgba(0,0,0,.12)}.mat-elevation-z15{box-shadow:0 8px 9px -5px rgba(0,0,0,.2),0 15px 22px 2px rgba(0,0,0,.14),0 6px 28px 5px rgba(0,0,0,.12)}.mat-elevation-z16{box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}.mat-elevation-z17{box-shadow:0 8px 11px -5px rgba(0,0,0,.2),0 17px 26px 2px rgba(0,0,0,.14),0 6px 32px 5px rgba(0,0,0,.12)}.mat-elevation-z18{box-shadow:0 9px 11px -5px rgba(0,0,0,.2),0 18px 28px 2px rgba(0,0,0,.14),0 7px 34px 6px rgba(0,0,0,.12)}.mat-elevation-z19{box-shadow:0 9px 12px -6px rgba(0,0,0,.2),0 19px 29px 2px rgba(0,0,0,.14),0 7px 36px 6px rgba(0,0,0,.12)}.mat-elevation-z20{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 20px 31px 3px rgba(0,0,0,.14),0 8px 38px 7px rgba(0,0,0,.12)}.mat-elevation-z21{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 21px 33px 3px rgba(0,0,0,.14),0 8px 40px 7px rgba(0,0,0,.12)}.mat-elevation-z22{box-shadow:0 10px 14px -6px rgba(0,0,0,.2),0 22px 35px 3px rgba(0,0,0,.14),0 8px 42px 7px rgba(0,0,0,.12)}.mat-elevation-z23{box-shadow:0 11px 14px -7px rgba(0,0,0,.2),0 23px 36px 3px rgba(Line truncated
|
||||
@@ -1,5 +0,0 @@
|
||||
@font-face{font-family:Material Icons;font-style:normal;font-weight:400;src:url(MaterialIcons-Regular.4674f8ded773cb03e824.eot);src:local("Material Icons"),local("MaterialIcons-Regular"),url(MaterialIcons-Regular.cff684e59ffb052d72cb.woff2) format("woff2"),url(MaterialIcons-Regular.83bebaf37c09c7e1c3ee.woff) format("woff"),url(MaterialIcons-Regular.5e7382c63da0098d634a.ttf) format("truetype")}.material-icons{font-family:Material Icons;font-weight:400;font-style:normal;font-size:24px;display:inline-block;line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:"liga"}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:100;src:local("Roboto Thin "),local("Roboto-Thin"),url(roboto-latin-100.c2aa4ab115bf9c6057cb.woff2) format("woff2"),url(roboto-latin-100.a45108d3b34af91f9113.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:100;src:local("Roboto Thin italic"),local("Roboto-Thinitalic"),url(roboto-latin-100italic.7f839a8652da29745ce4.woff2) format("woff2"),url(roboto-latin-100italic.451d4e559d6f57cdf6a1.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:300;src:local("Roboto Light "),local("Roboto-Light"),url(roboto-latin-300.37a7069dc30fc663c878.woff2) format("woff2"),url(roboto-latin-300.865f928cbabcc9f8f2b5.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:300;src:local("Roboto Light italic"),local("Roboto-Lightitalic"),url(roboto-latin-300italic.c64e7e354c88e613c77c.woff2) format("woff2"),url(roboto-latin-300italic.bd5b7a13f2c52b531a2a.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:400;src:local("Roboto Regular "),local("Roboto-Regular"),url(roboto-latin-400.176f8f5bd5f02b3abfcf.woff2) format("woff2"),url(roboto-latin-400.49ae34d4cc6b98c00c69.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:400;src:local("Roboto Regular italic"),local("Roboto-Regularitalic"),url(roboto-latin-400italic.d022bc70dc1bf7b3425d.woff2) format("woff2"),url(roboto-latin-400italic.b1d9d9904bfca8802a63.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:500;src:local("Roboto Medium "),local("Roboto-Medium"),url(roboto-latin-500.f5b74d7ffcdf85b9dd60.woff2) format("woff2"),url(roboto-latin-500.cea99d3e3e13a3a599a0.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:500;src:local("Roboto Medium italic"),local("Roboto-Mediumitalic"),url(roboto-latin-500italic.0d8bb5b3ee5f5dac9e44.woff2) format("woff2"),url(roboto-latin-500italic.18d00f739ff1e1c52db1.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:700;src:local("Roboto Bold "),local("Roboto-Bold"),url(roboto-latin-700.c18ee39fb002ad58b6dc.woff2) format("woff2"),url(roboto-latin-700.2267169ee7270a22a963.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:700;src:local("Roboto Bold italic"),local("Roboto-Bolditalic"),url(roboto-latin-700italic.7d8125ff7f707231fd89.woff2) format("woff2"),url(roboto-latin-700italic.9360531f9bb817f917f0.woff) format("woff")}@font-face{font-family:Roboto;font-style:normal;font-display:swap;font-weight:900;src:local("Roboto Black "),local("Roboto-Black"),url(roboto-latin-900.870c8c1486f76054301a.woff2) format("woff2"),url(roboto-latin-900.bac8362e7a6ea60b6983.woff) format("woff")}@font-face{font-family:Roboto;font-style:italic;font-display:swap;font-weight:900;src:local("Roboto Black italic"),local("Roboto-Blackitalic"),url(roboto-latin-900italic.cb5ad999740e9d8a8bd1.woff2) format("woff2"),url(roboto-latin-900italic.c20d916c1a1b094c1cec.woff) format("woff")}.mat-badge-content{font-weight:600;font-size:12px;font-family:Roboto,Helvetica Neue,sans-serif}.mat-badge-small .mat-badge-content{font-size:9px}.mat-badge-large .mat-badge-content{font-size:24px}.mat-h1,.mat-headline,.mat-typography h1{font:400 24px/32px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h2,.mat-title,.mat-typography h2{font:500 20px/32px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h3,.mat-subheading-2,.mat-typography h3{font:400 16px/28px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h4,.mat-subheading-1,.mat-typography h4{font:400 15px/24px Roboto,Helvetica Neue,sans-serif;letter-spacing:normal;margin:0 0 16px}.mat-h5,.mat-typography h5{font:400 calc(14px * .83)/20px Roboto,Helvetica Neue,sans-serif;margin:0 0 12px}.mat-h6,.mat-typography h6{font:400 calc(14px * .67)/20px Roboto,Helvetica Neue,sans-serif;margin:0 0 12px}.mat-body-2,.mat-body-strong{font:500 14px/24px Roboto,HeLine truncated
|
||||
/*!*/}@keyframes cdk-text-field-autofill-start{
|
||||
/*!*/}@-webkit-keyframes cdk-text-field-autofill-end{
|
||||
/*!*/}@keyframes cdk-text-field-autofill-end{
|
||||
/*!*/}.cdk-text-field-autofill-monitored:-webkit-autofill{-webkit-animation:cdk-text-field-autofill-start 0s 1ms;animation:cdk-text-field-autofill-start 0s 1ms}.cdk-text-field-autofill-monitored:not(:-webkit-autofill){-webkit-animation:cdk-text-field-autofill-end 0s 1ms;animation:cdk-text-field-autofill-end 0s 1ms}textarea.cdk-textarea-autosize{resize:none}textarea.cdk-textarea-autosize-measuring{padding:2px 0!important;box-sizing:content-box!important;height:auto!important;overflow:hidden!important}textarea.cdk-textarea-autosize-measuring-firefox{padding:2px 0!important;box-sizing:content-box!important;height:0!important}.mat-focus-indicator,.mat-mdc-focus-indicator{position:relative}.mat-ripple-element{background-color:rgba(0,0,0,.1)}.mat-option{color:rgba(0,0,0,.87)}.mat-option.mat-active,.mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled),.mat-option:focus:not(.mat-option-disabled),.mat-option:hover:not(.mat-option-disabled){background:hsla(0,0%,100%,.04)}.mat-option.mat-active{color:rgba(0,0,0,.87)}.mat-option.mat-option-disabled{color:rgba(0,0,0,.38)}.mat-primary .mat-option.mat-selected:not(.mat-option-disabled){color:#0097a7}.mat-accent .mat-option.mat-selected:not(.mat-option-disabled){color:#448aff}.mat-warn .mat-option.mat-selected:not(.mat-option-disabled){color:#f44336}.mat-optgroup-label{color:rgba(0,0,0,.54)}.mat-optgroup-disabled .mat-optgroup-label{color:rgba(0,0,0,.38)}.mat-pseudo-checkbox{color:rgba(0,0,0,.54)}.mat-pseudo-checkbox:after{color:#fff}.mat-pseudo-checkbox-disabled{color:#b0b0b0}.mat-primary .mat-pseudo-checkbox-checked,.mat-primary .mat-pseudo-checkbox-indeterminate{background:#0097a7}.mat-accent .mat-pseudo-checkbox-checked,.mat-accent .mat-pseudo-checkbox-indeterminate,.mat-pseudo-checkbox-checked,.mat-pseudo-checkbox-indeterminate{background:#448aff}.mat-warn .mat-pseudo-checkbox-checked,.mat-warn .mat-pseudo-checkbox-indeterminate{background:#f44336}.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-disabled,.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-disabled{background:#b0b0b0}.mat-app-background{background-color:#fff;color:rgba(0,0,0,.87)}.mat-elevation-z0{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12)}.mat-elevation-z1{box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12)}.mat-elevation-z2{box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12)}.mat-elevation-z3{box-shadow:0 3px 3px -2px rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.14),0 1px 8px 0 rgba(0,0,0,.12)}.mat-elevation-z4{box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}.mat-elevation-z5{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 5px 8px 0 rgba(0,0,0,.14),0 1px 14px 0 rgba(0,0,0,.12)}.mat-elevation-z6{box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12)}.mat-elevation-z7{box-shadow:0 4px 5px -2px rgba(0,0,0,.2),0 7px 10px 1px rgba(0,0,0,.14),0 2px 16px 1px rgba(0,0,0,.12)}.mat-elevation-z8{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.mat-elevation-z9{box-shadow:0 5px 6px -3px rgba(0,0,0,.2),0 9px 12px 1px rgba(0,0,0,.14),0 3px 16px 2px rgba(0,0,0,.12)}.mat-elevation-z10{box-shadow:0 6px 6px -3px rgba(0,0,0,.2),0 10px 14px 1px rgba(0,0,0,.14),0 4px 18px 3px rgba(0,0,0,.12)}.mat-elevation-z11{box-shadow:0 6px 7px -4px rgba(0,0,0,.2),0 11px 15px 1px rgba(0,0,0,.14),0 4px 20px 3px rgba(0,0,0,.12)}.mat-elevation-z12{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 12px 17px 2px rgba(0,0,0,.14),0 5px 22px 4px rgba(0,0,0,.12)}.mat-elevation-z13{box-shadow:0 7px 8px -4px rgba(0,0,0,.2),0 13px 19px 2px rgba(0,0,0,.14),0 5px 24px 4px rgba(0,0,0,.12)}.mat-elevation-z14{box-shadow:0 7px 9px -4px rgba(0,0,0,.2),0 14px 21px 2px rgba(0,0,0,.14),0 5px 26px 4px rgba(0,0,0,.12)}.mat-elevation-z15{box-shadow:0 8px 9px -5px rgba(0,0,0,.2),0 15px 22px 2px rgba(0,0,0,.14),0 6px 28px 5px rgba(0,0,0,.12)}.mat-elevation-z16{box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}.mat-elevation-z17{box-shadow:0 8px 11px -5px rgba(0,0,0,.2),0 17px 26px 2px rgba(0,0,0,.14),0 6px 32px 5px rgba(0,0,0,.12)}.mat-elevation-z18{box-shadow:0 9px 11px -5px rgba(0,0,0,.2),0 18px 28px 2px rgba(0,0,0,.14),0 7px 34px 6px rgba(0,0,0,.12)}.mat-elevation-z19{box-shadow:0 9px 12px -6px rgba(0,0,0,.2),0 19px 29px 2px rgba(0,0,0,.14),0 7px 36px 6px rgba(0,0,0,.12)}.mat-elevation-z20{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 20px 31px 3px rgba(0,0,0,.14),0 8px 38px 7px rgba(0,0,0,.12)}.mat-elevation-z21{box-shadow:0 10px 13px -6px rgba(0,0,0,.2),0 21px 33px 3px rgba(0,0,0,.14),0 8px 40px 7px rgba(0,0,0,.12)}.mat-elevation-z22{box-shadow:0 10px 14px -6px rgba(0,0,0,.2),0 22px 35px 3px rgba(0,0,0,.14),0 8px 42px 7px rgba(0,0,0,.12)}.mat-elevation-z23{box-shadow:0 11px 14px -7px rgba(0,0,0,.2),0 23px 36px 3px rgba(Line truncated
|
||||
@@ -21,26 +21,27 @@ import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_next_application_id(projects, compute):
|
||||
def get_next_application_id(projects, computes):
|
||||
"""
|
||||
Calculates free application_id from given nodes
|
||||
|
||||
:param projects: all projects managed by controller
|
||||
:param compute: Compute instance
|
||||
:param computes: all computes used by the project
|
||||
:raises HTTPConflict when exceeds number
|
||||
:return: integer first free id
|
||||
"""
|
||||
|
||||
nodes = []
|
||||
|
||||
# look for application id for in all nodes across all opened projects that share the same compute
|
||||
# look for application id for in all nodes across all opened projects that share the same computes
|
||||
for project in projects.values():
|
||||
if project.status == "opened" and compute in project.computes:
|
||||
if project.status == "opened":
|
||||
nodes.extend(list(project.nodes.values()))
|
||||
|
||||
used = set([n.properties["application_id"] for n in nodes if n.node_type == "iou"])
|
||||
used = set([n.properties["application_id"] for n in nodes if n.node_type == "iou" and n.compute.id in computes])
|
||||
pool = set(range(1, 512))
|
||||
try:
|
||||
return (pool - used).pop()
|
||||
application_id = (pool - used).pop()
|
||||
return application_id
|
||||
except KeyError:
|
||||
raise aiohttp.web.HTTPConflict(text="Cannot create a new IOU node (limit of 512 nodes across all opened projects using compute {} reached".format(compute.name))
|
||||
raise aiohttp.web.HTTPConflict(text="Cannot create a new IOU node (limit of 512 nodes across all opened projects using the same computes)")
|
||||
@@ -23,8 +23,8 @@
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
|
||||
__version__ = "2.2.14"
|
||||
__version_info__ = (2, 2, 14, 0)
|
||||
__version__ = "2.2.18"
|
||||
__version_info__ = (2, 2, 18, 0)
|
||||
|
||||
if "dev" in __version__:
|
||||
try:
|
||||
|
||||
@@ -64,6 +64,7 @@ class WebServer:
|
||||
self._start_time = time.time()
|
||||
self._running = False
|
||||
self._closing = False
|
||||
self._ssl_context = None
|
||||
|
||||
@staticmethod
|
||||
def instance(host=None, port=None):
|
||||
@@ -88,7 +89,6 @@ class WebServer:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
async def reload_server(self):
|
||||
"""
|
||||
Reload the server.
|
||||
@@ -96,7 +96,6 @@ class WebServer:
|
||||
|
||||
await Controller.instance().reload()
|
||||
|
||||
|
||||
async def shutdown_server(self):
|
||||
"""
|
||||
Cleanly shutdown the server.
|
||||
@@ -138,7 +137,12 @@ class WebServer:
|
||||
if PortManager.instance().udp_ports:
|
||||
log.warning("UDP ports are still used {}".format(PortManager.instance().udp_ports))
|
||||
|
||||
for task in asyncio.Task.all_tasks():
|
||||
try:
|
||||
tasks = asyncio.all_tasks()
|
||||
except AttributeError:
|
||||
tasks = asyncio.Task.all_tasks()
|
||||
|
||||
for task in tasks:
|
||||
task.cancel()
|
||||
try:
|
||||
await asyncio.wait_for(task, 1)
|
||||
@@ -147,6 +151,13 @@ class WebServer:
|
||||
|
||||
self._loop.stop()
|
||||
|
||||
def ssl_context(self):
|
||||
"""
|
||||
Returns the SSL context for the server.
|
||||
"""
|
||||
|
||||
return self._ssl_context
|
||||
|
||||
def _signal_handling(self):
|
||||
|
||||
def signal_handler(signame, *args):
|
||||
@@ -255,12 +266,12 @@ class WebServer:
|
||||
|
||||
server_config = Config.instance().get_section_config("Server")
|
||||
|
||||
ssl_context = None
|
||||
self._ssl_context = None
|
||||
if server_config.getboolean("ssl"):
|
||||
if sys.platform.startswith("win"):
|
||||
log.critical("SSL mode is not supported on Windows")
|
||||
raise SystemExit
|
||||
ssl_context = self._create_ssl_context(server_config)
|
||||
self._ssl_context = self._create_ssl_context(server_config)
|
||||
|
||||
self._loop = asyncio.get_event_loop()
|
||||
|
||||
@@ -307,7 +318,7 @@ class WebServer:
|
||||
log.info("Starting server on {}:{}".format(self._host, self._port))
|
||||
|
||||
self._handler = self._app.make_handler()
|
||||
if self._run_application(self._handler, ssl_context) is False:
|
||||
if self._run_application(self._handler, self._ssl_context) is False:
|
||||
self._loop.stop()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@ Conflicts=shutdown.target
|
||||
User=gns3
|
||||
Group=gns3
|
||||
PermissionsStartOnly=true
|
||||
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
EnvironmentFile=/etc/environment
|
||||
ExecStartPre=/bin/mkdir -p /var/log/gns3 /var/run/gns3
|
||||
ExecStartPre=/bin/chown -R gns3:gns3 /var/log/gns3 /var/run/gns3
|
||||
ExecStart=/usr/bin/gns3server --log /var/log/gns3/gns3.log
|
||||
|
||||
@@ -337,6 +337,7 @@ def test_set_qemu_path_kvm_binary(vm, fake_qemu_binary):
|
||||
|
||||
async def test_set_platform(compute_project, manager):
|
||||
|
||||
manager.config_disk = None # avoids conflict with config.img support
|
||||
with patch("shutil.which", return_value="/bin/qemu-system-x86_64") as which_mock:
|
||||
with patch("gns3server.compute.qemu.QemuVM._check_qemu_path"):
|
||||
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, platform="x86_64")
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
import uuid
|
||||
import os
|
||||
import pytest
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import patch, MagicMock
|
||||
from tests.utils import asyncio_patch
|
||||
|
||||
from gns3server.compute.vpcs import VPCS
|
||||
@@ -41,6 +41,7 @@ async def vpcs(loop, port_manager):
|
||||
async def qemu(loop, port_manager):
|
||||
|
||||
Qemu._instance = None
|
||||
Qemu._init_config_disk = MagicMock() # do not create the config.img image
|
||||
qemu = Qemu.instance()
|
||||
qemu.port_manager = port_manager
|
||||
return qemu
|
||||
|
||||
@@ -117,8 +117,8 @@ def images_dir(config):
|
||||
|
||||
path = config.get_section_config("Server").get("images_path")
|
||||
os.makedirs(path, exist_ok=True)
|
||||
os.makedirs(os.path.join(path, "QEMU"))
|
||||
os.makedirs(os.path.join(path, "IOU"))
|
||||
os.makedirs(os.path.join(path, "QEMU"), exist_ok=True)
|
||||
os.makedirs(os.path.join(path, "IOU"), exist_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
|
||||
@@ -277,9 +277,11 @@ async def test_images(compute_api, fake_qemu_vm):
|
||||
|
||||
response = await compute_api.get("/qemu/images")
|
||||
assert response.status == 200
|
||||
assert response.json == [{"filename": "linux载.img", "path": "linux载.img", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1}]
|
||||
assert response.json == [{'filename': 'config.img', 'filesize': 1048576, 'md5sum': '0ab49056760ae1db6c25376446190b47', 'path': 'config.img'},
|
||||
{"filename": "linux载.img", "path": "linux载.img", "md5sum": "c4ca4238a0b923820dcc509a6f75849b", "filesize": 1}]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Does not work on Windows")
|
||||
async def test_upload_image(compute_api, tmpdir):
|
||||
|
||||
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
|
||||