Compare commits

...
65 Commits
Author SHA1 Message Date
grossmj e58f86e204 Release v2.2.0b2 2019-05-29 17:16:59 +07:00
grossmj a6bc6bc79c Update appliance files. 2019-05-29 16:52:50 +07:00
grossmj 336b77e28a Merging 2.1 into 2.2 branch 2019-05-29 16:50:36 +07:00
grossmj 3dbce3fa40 Development on 2.1.21dev1 2019-05-29 16:37:42 +07:00
grossmj 053a16960c Release v2.1.20 2019-05-29 15:44:25 +07:00
grossmj a860243531 Ignore Unicode errors when reading base config file contents. 2019-05-29 15:43:17 +07:00
grossmj 99886d3f0c Development on 2.1.20dev1 2019-05-28 16:33:43 +07:00
grossmj 6fb613dcff Release v2.1.19 2019-05-28 15:23:35 +07:00
grossmj 4f803ff162 Sync appliances. 2019-05-28 10:37:43 +07:00
grossmj 591d4f29ff Fix minor bugs with log rotation support. Ref #1586 2019-05-28 10:34:27 +07:00
grossmj 87d85c1947 Remove yarl from requirements.txt since it is installed by aiohttp. 2019-05-27 18:10:46 +07:00
grossmj 54c4bd31d4 Remove setup require since we do not use environment makers yet. 2019-05-27 17:57:37 +07:00
grossmj 907807dc53 Drop typing dependency. 2019-05-27 17:38:16 +07:00
grossmj 5cbfafbeb2 Support snapshots for portable projects. Fixes https://github.com/GNS3/gns3-gui/issues/2792 2019-05-27 15:35:47 +07:00
grossmj 6229fadace Fix topology test 2019-05-26 15:55:29 +07:00
grossmj 81a48df9bb Update the GNS3 version in topology file if converted. Ref https://github.com/GNS3/gns3-gui/issues/2798 2019-05-26 15:44:55 +07:00
grossmj 2289fd4a2f Set log max size to 10MB. Ref #1586 2019-05-25 21:33:47 +07:00
grossmj 4ac999461b Support for log rotation and compression. Fixes #1586 2019-05-25 18:23:51 +07:00
grossmj 3b87a19979 Do not start QEMU console if QEMU process is not started. Fixes https://github.com/GNS3/gns3-gui/issues/2712 2019-05-25 15:31:35 +07:00
grossmj a86f881d83 Avoid sending warning message all the time for Ethernet switch. 2019-05-23 15:57:08 +07:00
grossmj 457ae4783f Development on 2.1.19dev1 2019-05-23 14:37:37 +07:00
grossmj 878987a26e Release v2.1.18 2019-05-22 16:13:28 +07:00
grossmj 40d7ae6866 Support to include snapshots in portable projects. 2019-05-22 14:35:37 +07:00
grossmj 39f6f4edd5 Development on 2.2.0dev12 2019-05-21 19:16:19 +07:00
grossmj 5b3be13e73 Release v2.2.0b1 2019-05-21 15:26:54 +07:00
ziajka 16908df8b2 Upgrade GNS3 Web UI to v2019.2.0-alpha.3 2019-05-20 14:23:25 +02:00
grossmj c357d52ba4 Revert "Force aiohttp version to 2.3.10 and aiohttp-cors version to 0.5.3"
Ref https://github.com/GNS3/gns3-server/issues/1583
Ref https://github.com/GNS3/gns3-server/issues/1592

This reverts commit 351ed64de9.
2019-05-20 17:23:26 +07:00
grossmj 44a142e91d Fix tests 2019-05-20 11:02:29 +07:00
grossmj 28004479fd Change behavior when an IOU license is verified. Fixes https://github.com/GNS3/gns3-server/issues/1555 2019-05-20 10:51:24 +07:00
grossmj e8b8554c1a Fix Qemu VM state support after closing a project and check for JSON data returned by qemu-img. Fixes #1591 2019-05-19 17:59:00 +07:00
grossmj 424db843ca Fix Docker extra volumes support 2019-05-19 14:26:03 +07:00
grossmj 0c6749f62b Update Dockerfile to Ubuntu 18.04 2019-05-18 20:19:34 +07:00
Jeremy Grossmann cdae1f9e00 Merge pull request #1584 from kazkansouh/2.2-docker-volumes
Custom persistent docker volumes
2019-05-18 20:17:11 +07:00
grossmj cf0cc8bb87 Ensure Qemu monitor commands are executed. Ref #1582. 2019-05-18 19:31:41 +07:00
grossmj c41c01b95f Fix tests. 2019-05-18 19:19:27 +07:00
grossmj 2340823f53 Update appliance files. 2019-05-18 15:45:28 +07:00
grossmj 470cea327f Fix console variable replacement issue. 2019-05-18 14:31:21 +07:00
grossmj 6edcbd0461 Set console type to "none" by default for Ethernet switches and add a warning if trying to use "telnet". Fixes https://github.com/GNS3/gns3-gui/issues/2776 2019-05-18 14:28:20 +07:00
grossmj a7e449ff0e Bump version to 2.2.0dev11 2019-05-18 14:11:07 +07:00
grossmj e763980dbe Add %console-port% variable for additional Qemu options. Fixes https://github.com/GNS3/gns3-gui/issues/2786 2019-05-18 13:51:00 +07:00
grossmj f1ae3b3778 Merge remote-tracking branch 'origin/2.2' into 2.2 2019-05-18 13:45:57 +07:00
grossmj 9400c49b82 Merge 2.1 branch into 2.2 2019-05-18 13:45:39 +07:00
grossmj 773bad811a Fix invalid reStructuredText for long description in setup.py 2019-05-17 16:14:19 +07:00
grossmj 6b54cc27da Release v2.1.17 2019-05-17 15:10:28 +07:00
grossmj 351ed64de9 Force aiohttp version to 2.3.10 and aiohttp-cors version to 0.5.3
This is to fix build issue for Ubuntu 19.04 package on Launchpad.
Ref #1583 https://github.com/GNS3/gns3-gui/issues/2774
2019-05-17 09:56:16 +07:00
Karim 81ddb0cfe6 Impoved docker volumes user input validation 2019-04-22 12:46:28 +01:00
Karim 0c19bc8d43 Support for additional persistent docker volumes to be specified within appliance configuration 2019-04-22 10:26:41 +01:00
Jeremy Grossmann 264f9da576 Merge pull request #1580 from GNS3/pyup-update-pytest-4.4.0-to-4.4.1
Update pytest to 4.4.1
2019-04-16 20:05:10 +07:00
pyup-bot 30a9ea8675 Update pytest from 4.4.0 to 4.4.1 2019-04-16 03:34:57 +02:00
grossmj 7543d7587c Release v2.2.0a5 2019-04-15 17:05:20 +07:00
grossmj f5ebc6a29a Merge 2.1 into 2.2 2019-04-15 15:54:08 +07:00
grossmj f41158173b Development on 2.1.17dev1 2019-04-15 12:41:40 +07:00
grossmj cb5dc36987 Release v2.1.16 2019-04-15 12:00:18 +07:00
grossmj fb470dd4b5 Back to the major.minor version for config files. Ref https://github.com/GNS3/gns3-gui/issues/2756 2019-04-14 21:31:40 +07:00
grossmj 6dbb992513 Fix templates missing after server restart. Fixes https://github.com/GNS3/gns3-gui/issues/2769 2019-04-14 20:39:55 +07:00
grossmj e962717448 Fix bug when GNS3 VM were not saved. Fix tests. 2019-04-14 17:42:20 +07:00
grossmj 6dc58b28fd Some adjustments with compute WebSocket handling. Ref https://github.com/GNS3/gns3-server/issues/1564 2019-04-14 16:48:12 +07:00
grossmj 6db8cecda5 Merge 2.1 into 2.2 2019-04-13 18:39:06 +07:00
grossmj cc1980ac1c Fix broken embedded console for Ethernet switch. Fixes #1574 2019-04-11 17:57:47 +07:00
grossmj 2af9c9c8ec Prevent locked nodes to be deleted. Fixes https://github.com/GNS3/gns3-gui/issues/2764 2019-04-10 15:43:51 +07:00
grossmj 8cd66cfc02 Remove old unused argument option. Fixes #1569 2019-04-09 19:26:07 +07:00
grossmj 4d222ddc0a Bump version to 2.2.0dev10 2019-04-09 19:20:21 +07:00
grossmj 5c884702e5 Development on 2.2.0dev9 2019-04-05 22:01:35 +08:00
grossmj 645031ee15 Development on 2.1.16dev1 2019-03-21 13:56:11 +08:00
grossmj c70b344133 Release v2.1.15 2019-03-21 11:41:44 +08:00
80 changed files with 2648 additions and 405 deletions

No files matched your search

+61
View File
@@ -1,5 +1,61 @@
# Change Log
## 2.2.0b2 29/05/2019
* Ignore Unicode errors when reading base config file contents.
* Sync appliances.
* Support snapshots for portable projects. Fixes https://github.com/GNS3/gns3-gui/issues/2792
* Update the GNS3 version in topology file if converted. Ref https://github.com/GNS3/gns3-gui/issues/2798
* Support for log rotation and compression. Fixes #1586
* Do not start QEMU console if QEMU process is not started. Fixes https://github.com/GNS3/gns3-gui/issues/2712
* Avoid sending warning message all the time for Ethernet switch.
* Support to include snapshots in portable projects.
## 2.1.20 29/05/2019
* Ignore Unicode errors when reading base config file contents.
## 2.1.19 28/05/2019
* Sync appliances.
* Remove yarl from requirements.txt since it is installed by aiohttp.
* Drop typing dependency.
## 2.1.18 22/05/2019
* Revert "Force aiohttp version to 2.3.10 and aiohttp-cors version to 0.5.3" Ref https://github.com/GNS3/gns3-server/issues/1583 Ref https://github.com/GNS3/gns3-server/issues/1592
* Fix invalid reStructuredText for long description in setup.py
## 2.2.0b1 21/05/2019
* Upgrade GNS3 Web UI to v2019.2.0-alpha.3
* Change behavior when an IOU license is verified. Fixes https://github.com/GNS3/gns3-server/issues/1555
* Fix Qemu VM state support after closing a project and check for JSON data returned by qemu-img. Fixes #1591
* Ensure Qemu monitor commands are executed. Ref #1582.
* Set console type to "none" by default for Ethernet switches and add a warning if trying to use "telnet". Fixes https://github.com/GNS3/gns3-gui/issues/2776
* Add %console-port% variable for additional Qemu options. Fixes https://github.com/GNS3/gns3-gui/issues/2786
* Fix invalid reStructuredText for long description in setup.py
* Support for additional persistent docker volumes
## 2.2.0a5 15/04/2019
* Back to the major.minor version for config files. Ref https://github.com/GNS3/gns3-gui/issues/2756
* Fix templates missing after server restart. Fixes https://github.com/GNS3/gns3-gui/issues/2769
* Fix bug when GNS3 VM were not saved. Fix tests.
* Some adjustments with compute WebSocket handling. Ref https://github.com/GNS3/gns3-server/issues/1564
* Fix broken embedded console for Ethernet switch. Fixes #1574
* Prevent locked nodes to be deleted. Fixes https://github.com/GNS3/gns3-gui/issues/2764
* Remove old unused argument option. Fixes #1569
## 2.1.17 17/05/2019
* Force aiohttp version to 2.3.10 and aiohttp-cors version to 0.5.3 This is to fix build issue for Ubuntu 19.04 package on Launchpad. Ref #1583 https://github.com/GNS3/gns3-gui/issues/2774
## 2.1.16 15/04/2019
* Fix broken embedded console for Ethernet switch. Fixes #1574
* Remove old unused argument option. Fixes #1569
## 2.2.0a4 05/04/2019
* Use the full version number for path to config files. Ref https://github.com/GNS3/gns3-gui/issues/2756
@@ -28,6 +84,11 @@
* Save the GNS3 VM settings even if the GNS3 VM cannot be stopped.
* Fix exception when emitting event from controller. Ref https://github.com/GNS3/gns3-gui/issues/2737
## 2.1.15 21/03/2019
* Fix IOU symlink issue on remote servers.
* Fix vcpus configuration for GNS3 VM on VMware. Ref #2738.
## 2.2.0a2 14/03/2019
* Web-UI v2019.1.0-alpha.1
+1 -1
View File
@@ -1,6 +1,6 @@
# Dockerfile for GNS3 server development
FROM ubuntu:16.04
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND noninteractive
+5 -4
View File
@@ -23,7 +23,7 @@ master is the next stable release, you can test it in your day to day activities
Bug fixes or small improvements pull requests go here.
2.x (2.1 for example)
********
*********************
Next major release
*Never* use this branch for production. Pull requests for major new features go here.
@@ -100,7 +100,7 @@ All the init script require the creation of a GNS3 user. You can change it to an
sudo adduser gns3
upstart
~~~~~~~
-------
For ubuntu < 15.04
@@ -113,7 +113,8 @@ You need to copy init/gns3.conf.upstart to /etc/init/gns3.conf
systemd
~~~~~~~~
-------
You need to copy init/gns3.service.systemd to /lib/systemd/system/gns3.service
.. code:: bash
@@ -219,5 +220,5 @@ If you want test coverage:
Security issues
----------------
Please contact us using contact informations available here:
Please contact us using contact form available here:
http://docs.gns3.com/1ON9JBXSeR7Nt2-Qum2o3ZX0GU86BZwlmNSUgvmqNWGY/index.html
+1 -1
View File
@@ -1,6 +1,6 @@
-rrequirements.txt
sphinx==1.8.3
pytest==4.4.0
pytest==4.4.1
pep8==1.7.1
pytest-timeout==1.3.3
+87 -35
View File
@@ -21,7 +21,6 @@
"ram": 2048,
"arch": "x86_64",
"console_type": "telnet",
"boot_priority": "d",
"kvm": "require"
},
"images": [
@@ -33,10 +32,10 @@
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.20.11M.vmdk",
"version": "4.20.11M",
"md5sum": "19e482a193f237c157ce35c389ca9417",
"filesize": 658178048,
"filename": "vEOS-lab-4.20.10M-combined.vmdk",
"version": "4.20.10M-combined",
"md5sum": "d1f2d650f93dbf24e04fdd2c9d62bd62",
"filesize": 334626816,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
@@ -46,6 +45,34 @@
"filesize": 662044672,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.19.10M-combined.vmdk",
"version": "4.19.10M-combined",
"md5sum": "103daa45c33be4584cbe6adc60de46a3",
"filesize": 324141056,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.19.10M.vmdk",
"version": "4.19.10M",
"md5sum": "665ed14389411ae5f16ba0a2ff84240a",
"filesize": 637337600,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.18.10M-combined.vmdk",
"version": "4.18.10M-combined",
"md5sum": "e33e0ef5b8cecc84c5bb57569b36b9c6",
"filesize": 317652992,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.18.10M.vmdk",
"version": "4.18.10M",
"md5sum": "1d87e9ace37fe3706dbf3e49c8d4d231",
"filesize": 624427008,
"download_url": "https://www.arista.com/en/support/software-download"
},
{
"filename": "vEOS-lab-4.18.5M.vmdk",
"version": "4.18.5M",
@@ -133,101 +160,126 @@
],
"versions": [
{
"name": "4.21.1.1F",
"name": "4.21.1F",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.21.1.1F.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.21.1.1F.vmdk"
}
},
{
"name": "4.20.11M",
"name": "4.20.10M-combined",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.20.11M.vmdk"
"hda_disk_image": "vEOS-lab-4.20.10M-combined.vmdk"
}
},
{
"name": "4.20.1F",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.20.1F.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.20.1F.vmdk"
}
},
{
"name": "4.19.10M-combined",
"images": {
"hda_disk_image": "vEOS-lab-4.19.10M-combined.vmdk"
}
},
{
"name": "4.19.10M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.19.10M.vmdk"
}
},
{
"name": "4.18.10M-combined",
"images": {
"hda_disk_image": "vEOS-lab-4.18.10M-combined.vmdk"
}
},
{
"name": "4.18.10M",
"images": {
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.18.10M.vmdk"
}
},
{
"name": "4.18.5M",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.18.5M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.18.5M.vmdk"
}
},
{
"name": "4.18.1F",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.18.1F.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.18.1F.vmdk"
}
},
{
"name": "4.17.8M",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.17.8M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.17.8M.vmdk"
}
},
{
"name": "4.17.2F",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.17.2F.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.17.2F.vmdk"
}
},
{
"name": "4.16.13M",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.16.13M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.16.13M.vmdk"
}
},
{
"name": "4.16.6M",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.16.6M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.16.6M.vmdk"
}
},
{
"name": "4.15.10M",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.15.10M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.15.10M.vmdk"
}
},
{
"name": "4.15.5M",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.15.5M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.15.5M.vmdk"
}
},
{
"name": "4.14.14M",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.14.14M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.14.14M.vmdk"
}
},
{
"name": "4.13.16M",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.13.16M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.13.16M.vmdk"
}
},
{
"name": "4.13.8M",
"images": {
"cdrom_image": "Aboot-veos-serial-8.0.0.iso",
"hda_disk_image": "vEOS-lab-4.13.8M.vmdk"
"hda_disk_image": "Aboot-veos-serial-8.0.0.iso",
"hdb_disk_image": "vEOS-lab-4.13.8M.vmdk"
}
}
]
+32 -2
View File
@@ -1,11 +1,11 @@
{
"name": "AsteriskNOW",
"name": "AsteriskNOW / FreePBX",
"category": "guest",
"description": "AsteriskNOW makes it easy to create custom telephony solutions by automatically installing the 'plumbing'. It's a complete Linux distribution with Asterisk, the DAHDI driver framework, and, the FreePBX administrative GUI. Much of the complexity of Asterisk and Linux is handled by the installer, the yum package management utility and the administrative GUI. With AsteriskNOW, application developers and integrators can concentrate on building solutions, not maintaining the plumbing.",
"vendor_name": "Digium",
"vendor_url": "http://www.asterisk.org/",
"documentation_url": "https://wiki.asterisk.org/wiki/display/AST/Installing+AsteriskNOW",
"product_name": "AsteriskNOW",
"product_name": "AsteriskNOW / FreePBX",
"product_url": "http://www.asterisk.org/downloads/asterisknow",
"registry_version": 3,
"status": "stable",
@@ -24,6 +24,22 @@
"kvm": "allow"
},
"images": [
{
"filename": "SNG7-FPBX-64bit-1904-2.iso",
"version": "14-1904",
"md5sum": "f37c316bc0ff208682769b6f2d468e93",
"filesize": 2015363072,
"download_url": "https://www.freepbx.org/downloads/",
"direct_download_url": "https://downloads.freepbxdistro.org/ISO/SNG7-FPBX-64bit-1904-2.iso"
},
{
"filename": "SNG7-FPBX-64bit-1805-2.iso",
"version": "14-1805",
"md5sum": "64f0c38c17ce680f7106f94183bc5745",
"filesize": 1755316224,
"download_url": "https://www.freepbx.org/downloads/",
"direct_download_url": "https://downloads.freepbxdistro.org/ISO/SNG7-FPBX-64bit-1805-2.iso"
},
{
"filename": "AsteriskNow-1013-current-64.iso",
"version": "10.13",
@@ -58,6 +74,20 @@
}
],
"versions": [
{
"name": "14-1904",
"images": {
"hda_disk_image": "empty30G.qcow2",
"cdrom_image": "SNG7-FPBX-64bit-1904-2.iso"
}
},
{
"name": "14-1805",
"images": {
"hda_disk_image": "empty30G.qcow2",
"cdrom_image": "SNG7-FPBX-64bit-1805-2.iso"
}
},
{
"name": "10.13",
"images": {
+15
View File
@@ -19,6 +19,15 @@
"kvm": "allow"
},
"images": [
{
"filename": "BSDRP-1.92-full-amd64-serial.img",
"version": "1.92",
"md5sum": "b02f2502188915490bb9756ffca36910",
"filesize": 1000000000,
"download_url": "https://bsdrp.net/downloads",
"direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.92/amd64/BSDRP-1.92-full-amd64-serial.img.xz/download",
"compression": "xz"
},
{
"filename": "BSDRP-1.91-full-amd64-serial.img",
"version": "1.91",
@@ -57,6 +66,12 @@
}
],
"versions": [
{
"name": "1.92",
"images": {
"hda_disk_image": "BSDRP-1.92-full-amd64-serial.img"
}
},
{
"name": "1.91",
"images": {
+30
View File
@@ -27,6 +27,22 @@
},
"images": [
{
"filename": "CentOS 7-18.10 (64bit).vmdk",
"version": "7-1810",
"md5sum": "7307e143c11910f3c782b1e013e6f14f",
"filesize": 4886233088,
"download_url": "http://www.osboxes.org/centos/"
},
{
"filename": "CentOS 7-1804 (64bit).vmdk",
"version": "7-1804",
"md5sum": "eae8dc48bb390c0c2d9a9a0432ced9bc",
"filesize": 4701356032,
"download_url": "http://www.osboxes.org/centos/"
},
{
"filename": "CentOS 7-1611 (64bit).vmdk",
"version": "7-1611",
@@ -36,6 +52,20 @@
}
],
"versions": [
{
"name": "7-1810",
"images": {
"hda_disk_image": "CentOS 7-18.10 (64bit).vmdk"
}
},
{
"name": "7-1804",
"images": {
"hda_disk_image": "CentOS 7-1804 (64bit).vmdk"
}
},
{
"name": "7-1611",
"images": {
-1
View File
@@ -11,7 +11,6 @@
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"dynamips": {
"chassis": "",
"platform": "c3745",
"ram": 256,
"nvram": 256,
+15 -1
View File
@@ -25,12 +25,19 @@
"options": "-smp 2"
},
"images": [
{
"filename": "dcnm-va.11.1.1.iso",
"version": "11.1.1",
"md5sum": "43af970d046d1430d3ec7950dbe4a20a",
"filesize": 4432132096,
"download_url": "https://software.cisco.com/download/home/281722751/type/282088134/release/11.1%25281%2529"
},
{
"filename": "dcnm-va.10.1.1.iso",
"version": "10.1.1",
"md5sum": "4eca14506decaf166251c64e67adb110",
"filesize": 2927532032,
"download_url": "https://software.cisco.com/download/release.html?mdfid=281722751&softwareid=282088134&release=10.1(1)&relind=AVAILABLE&rellifecycle=&reltype=latest"
"download_url": "https://software.cisco.com/download/home/281722751/type/282088134/release/10.1%25281%2529"
},
{
"filename": "empty100G.qcow2",
@@ -42,6 +49,13 @@
}
],
"versions": [
{
"name": "11.1.1",
"images": {
"hda_disk_image": "empty100G.qcow2",
"cdrom_image": "dcnm-va.11.1.1.iso"
}
},
{
"name": "10.1.1",
"images": {
@@ -24,6 +24,13 @@
"options": "-smp 4 -cpu host"
},
"images": [
{
"filename": "xrv9k-fullk9-x-6.5.2.qcow2",
"version": "6.5.2",
"md5sum": "506d9e23dda7365c99dd82b613859697",
"filesize": 1205010432,
"download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.5.1"
},
{
"filename": "xrv9k-fullk9-x-6.5.1.qcow2",
"version": "6.5.1",
@@ -67,6 +74,12 @@
}
],
"versions": [
{
"name": "6.5.2",
"images": {
"hda_disk_image": "xrv9k-fullk9-x-6.5.2.qcow2"
}
},
{
"name": "6.5.1",
"images": {
+30
View File
@@ -21,6 +21,24 @@
"kvm": "allow"
},
"images": [
{
"filename": "coreos_production_qemu_image.img",
"version": "2079.4.0",
"md5sum": "d5e28d68bcadf252ff9c909a159b9504",
"filesize": 970129408,
"download_url": "http://stable.release.core-os.net/amd64-usr/2079.4.0/",
"direct_download_url": "http://stable.release.core-os.net/amd64-usr/2079.4.0/coreos_production_qemu_image.img.bz2",
"compression": "bzip2"
},
{
"filename": "coreos_production_qemu_image.2023.5.0.img",
"version": "2023.5.0",
"md5sum": "f8b12e524aa81220222d06473b3f36dc",
"filesize": 587661312,
"download_url": "http://stable.release.core-os.net/amd64-usr/2023.5.0/",
"direct_download_url": "http://stable.release.core-os.net/amd64-usr/2023.5.0/coreos_production_qemu_image.img.bz2",
"compression": "bzip2"
},
{
"filename": "coreos_production_qemu_image.1911.5.0.img",
"version": "1911.5.0",
@@ -185,6 +203,18 @@
}
],
"versions": [
{
"name": "2079.4.0",
"images": {
"hda_disk_image": "coreos_production_qemu_image.img"
}
},
{
"name": "2023.5.0",
"images": {
"hda_disk_image": "coreos_production_qemu_image.2023.5.0.img"
}
},
{
"name": "1911.5.0",
"images": {
+30 -2
View File
@@ -23,6 +23,22 @@
"kvm": "require"
},
"images": [
{
"filename": "cumulus-linux-3.7.6-vx-amd64-qemu.qcow2",
"version": "3.7.6",
"md5sum": "34de965074332cbc40d51832da7d6a5d",
"filesize": 540278784,
"download_url": "https://cumulusnetworks.com/cumulus-vx/download/",
"direct_download_url": "http://cumulusfiles.s3.amazonaws.com/CumulusLinux-3.7.6/cumulus-linux-3.7.6-vx-amd64-qemu.qcow2"
},
{
"filename": "cumulus-linux-3.7.3-vx-amd64-qemu.qcow2",
"version": "3.7.3",
"md5sum": "e6f438cd44ede841ff290c85dedd127e",
"filesize": 1514340352,
"download_url": "https://cumulusnetworks.com/cumulus-vx/download/",
"direct_download_url": "http://cumulusfiles.s3.amazonaws.com/CumulusLinux-3.7.3/cumulus-linux-3.7.3-vx-amd64-qemu.qcow2"
},
{
"filename": "cumulus-linux-3.7.2-vx-amd64-qemu.qcow2",
"version": "3.7.2",
@@ -42,8 +58,8 @@
{
"filename": "cumulus-linux-3.6.2-vx-amd64.qcow2",
"version": "3.6.2",
"md5sum": "02b0621d68fb2e709b4bcc48748c7b6f",
"filesize": 1150746624,
"md5sum": "fda2cfc556de7b12daf45369bd60d33b",
"filesize": 1157169152,
"download_url": "https://cumulusnetworks.com/cumulus-vx/download/",
"direct_download_url": "https://s3.amazonaws.com/cumulusfiles/CumulusLinux-3.6.2/cumulus-linux-3.6.2-vx-amd64.qcow2"
},
@@ -189,6 +205,18 @@
}
],
"versions": [
{
"name": "3.7.6",
"images": {
"hda_disk_image": "cumulus-linux-3.7.6-vx-amd64-qemu.qcow2"
}
},
{
"name": "3.7.3",
"images": {
"hda_disk_image": "cumulus-linux-3.7.3-vx-amd64-qemu.qcow2"
}
},
{
"name": "3.7.2",
"images": {
+79 -129
View File
@@ -1,189 +1,139 @@
{
"name": "EXOS",
"name": "EXOS VM",
"category": "multilayer_switch",
"description": "ExtremeXOS was designed from the ground up to meet the needs of large cloud and private data centers, service providers, intelligent, converged enterprise edge networks, and everything in between. It provides the high performance and rich features required by these diverse environments.",
"description": "The ExtremeXOS VM is created and maintained by Extreme Networks for users to emulate a network using EXOS switches.",
"vendor_name": "Extreme Networks",
"vendor_url": "http://www.extremenetworks.com/",
"documentation_url": "http://www.extremenetworks.com/support/documentation",
"product_name": "EXOS",
"product_url": "http://www.extremenetworks.com/product/extremexos-network-operating-system",
"vendor_url": "https://www.extremenetworks.com",
"documentation_url": "https://www.extremenetworks.com/support/documentation",
"product_name": "EXOS VM",
"registry_version": 3,
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "You can change the console to telnet after install. Default user: admin (no password set)",
"first_port_name": "Management",
"maintainer": "Extreme Networks",
"maintainer_email": "GitHubscripting@extremenetworks.com",
"usage": "Boot up and login is admin with no password.",
"symbol": "ethernet_switch.svg",
"first_port_name": "Mgmt",
"port_name_format": "Port{port1}",
"qemu": {
"adapter_type": "rtl8139",
"adapters": 13,
"ram": 256,
"ram": 512,
"hda_disk_interface": "ide",
"arch": "x86_64",
"console_type": "telnet",
"boot_priority": "cd",
"kvm": "require",
"options": "-smp 2 -cpu core2duo"
"boot_priority": "dc",
"kvm": "allow",
"options": "-cpu core2duo"
},
"images": [
{
"filename": "exosvm-22.6.1.4.iso",
{
"filename": "EXOS-VM_v30.1.1.4.qcow2",
"version": "30.1.1.4",
"md5sum": "92d3f9b13d750f7bfa804823fa545772",
"filesize": 383385600,
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v30.1.1.4.qcow2"
},
{
"filename": "EXOS-VM_v22.6.1.4.qcow2",
"version": "22.6.1.4",
"md5sum": "66146aba82575b3879431143b6dc8a35",
"filesize": 53706752,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.6.1.4.iso"
"md5sum": "82b31b11b26143a82c8259a4825696fc",
"filesize": 180355072,
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.6.1.4.qcow2"
},
{
"filename": "exosvm-22.5.1.7.iso",
{
"filename": "EXOS-VM_v22.5.1.7.qcow2",
"version": "22.5.1.7",
"md5sum": "132ac87de368ab55d1f496f292338cd4",
"filesize": 51779584,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.5.1.7.iso"
"md5sum": "d2e8ae6783b6ed777ad5cd8cafd83c86",
"filesize": 180289536,
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.5.1.7.qcow2"
},
{
"filename": "exosvm-22.4.1.4.iso",
"filename": "EXOS-VM_v22.4.1.4-disk1.qcow2",
"version": "22.4.1.4",
"md5sum": "2134a511084519a5f8ad00a6f7cd71a9",
"filesize": 49993728,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.4.1.4.iso"
"md5sum": "5f1ee41912d74d423ce8ae57ea413602",
"filesize": 229638144,
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.4.1.4-disk1.qcow2"
},
{
"filename": "exosvm-22.2.1.5.iso",
"filename": "EXOS-VM_v22.3.1.4patch1-4-disk1.qcow2",
"version": "22.3.1.4",
"md5sum": "a4585b6e987ff730f5c044af339fe090",
"filesize": 218431488,
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.3.1.4patch1-4-disk1.qcow2"
},
{
"filename": "EXOS-VM_v22.2.1.5-disk1.qcow2",
"version": "22.2.1.5",
"md5sum": "bf51fd5b3c5e9dab10a616055265bcf2",
"filesize": 44578816,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.2.1.5.iso"
"md5sum": "e3cfe92077addda6ad34185288c90acf",
"filesize": 179568640,
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.2.1.5-disk1.qcow2"
},
{
"filename": "exosvm-22.1.1.5.iso",
"filename": "EXOS-VM_v22.1.1.5-disk1.qcow2",
"version": "22.1.1.5",
"md5sum": "df3897ca2d7c7053582587ed120114fa",
"filesize": 44220416,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/raw/master/vm-22.1.1.5.iso"
"md5sum": "77683060e75d81b776761f6829b15e9b",
"filesize": 179437568,
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v22.1.1.5-disk1.qcow2"
},
{
"filename": "exosvm-21.1.2.14.iso",
"version": "21.1.2.14",
"md5sum": "de0752d56e41d92027ce1fccd604b14b",
"filesize": 41101312,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/vm-21.1.2.14.iso?raw=true"
},
{
"filename": "exosvm-21.1.1.4.iso",
{
"filename": "EXOS-VM_v21.1.1.4-disk1.qcow2",
"version": "21.1.1.4",
"md5sum": "4d5db0e01a39b08775ed6a3e2c8bf663",
"filesize": 41046016,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/vm-21.1.1.4.iso?raw=true"
},
{
"filename": "exospc-16.2.1.6.iso",
"version": "16.2.1.6",
"md5sum": "b4be339afb02c03dcb4349630c1adb4f",
"filesize": 36306944,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.2.1.6.iso?raw=true"
},
{
"filename": "exospc-16.1.3.6.iso",
"version": "16.1.3.6",
"md5sum": "4c17b2bf2a4909527f6c866a68ba406e",
"filesize": 35758080,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.1.3.6.iso?raw=true"
},
{
"filename": "exospc-16.1.2.14.iso",
"version": "16.1.2.14",
"md5sum": "140cdc11f426156ffcbde150b2f46768",
"filesize": 35743744,
"download_url": "https://github.com/extremenetworks/Virtual_EXOS",
"direct_download_url": "https://github.com/extremenetworks/Virtual_EXOS/blob/master/exospc-16.1.2.14.iso?raw=true"
},
{
"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"
"md5sum": "654606809b6fd3bca400377483eb4a79",
"filesize": 117560832,
"direct_download_url": "https://akamai-ep.extremenetworks.com/Extreme_P/github-en/Virtual_EXOS/EXOS-VM_v21.1.1.4-disk1.qcow2"
}
],
"versions": [
{
"name": "22.6.1.4",
"name": "30.1.1.4",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exosvm-22.6.1.4.iso"
"hda_disk_image": "EXOS-VM_v30.1.1.4.qcow2"
}
},
{
{
"name": "22.6.1.4",
"images": {
"hda_disk_image": "EXOS-VM_v22.6.1.4.qcow2"
}
},
{
"name": "22.5.1.7",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exosvm-22.5.1.7.iso"
"hda_disk_image": "EXOS-VM_v22.5.1.7.qcow2"
}
},
{
"name": "22.4.1.4",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exosvm-22.4.1.4.iso"
"hda_disk_image": "EXOS-VM_v22.4.1.4-disk1.qcow2"
}
},
{
"name": "22.3.1.4",
"images": {
"hda_disk_image": "EXOS-VM_v22.3.1.4patch1-4-disk1.qcow2"
}
},
{
"name": "22.2.1.5",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exosvm-22.2.1.5.iso"
"hda_disk_image": "EXOS-VM_v22.2.1.5-disk1.qcow2"
}
},
{
"name": "22.1.1.5",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exosvm-22.1.1.5.iso"
}
},
{
"name": "21.1.2.14",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exosvm-21.1.2.14.iso"
"hda_disk_image": "EXOS-VM_v22.1.1.5-disk1.qcow2"
}
},
{
"name": "21.1.1.4",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exosvm-21.1.1.4.iso"
}
},
{
"name": "16.2.1.6",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exospc-16.2.1.6.iso"
}
},
{
"name": "16.1.3.6",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exospc-16.1.3.6.iso"
}
},
{
"name": "16.1.2.14",
"images": {
"hda_disk_image": "empty8G.qcow2",
"cdrom_image": "exospc-16.1.2.14.iso"
"hda_disk_image": "EXOS-VM_v21.1.1.4-disk1.qcow2"
}
}
]
+14
View File
@@ -34,6 +34,13 @@
"filesize": 30998528,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-V500-build0442-FORTINET.out.kvm-boot.qcow2",
"version": "5.2.2",
"md5sum": "7d959ed264b064716e8f1378fceed48f",
"filesize": 104857600,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAD_KVM-V500-build0423-FORTINET.out.kvm-boot.qcow2",
"version": "5.2.0",
@@ -190,6 +197,13 @@
}
],
"versions": [
{
"name": "5.2.2",
"images": {
"hda_disk_image": "FAD_KVM-V500-build0442-FORTINET.out.kvm-boot.qcow2",
"hdb_disk_image": "FAD_KVM-FORTINET.out.kvm-data.qcow2"
}
},
{
"name": "5.2.0",
"images": {
+14
View File
@@ -26,6 +26,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FAZ_VM64_KVM-v6-build1050-FORTINET.out.kvm.qcow2",
"version": "6.2.0",
"md5sum": "dc123116e4c816d8b4dee244bd671844",
"filesize": 140177408,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAZ_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2",
"version": "6.0.3",
@@ -148,6 +155,13 @@
}
],
"versions": [
{
"name": "6.2.0",
"images": {
"hda_disk_image": "FAZ_VM64_KVM-v6-build1050-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "6.0.3",
"images": {
+25 -11
View File
@@ -26,6 +26,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FAC_VM_KVM-v6-build0010-FORTINET.out.kvm.qcow2",
"version": "6.0.0",
"md5sum": "6699c0b24e54dc6a5215ba3945abb364",
"filesize": 74317824,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v5-build0366-FORTINET.out.kvm.qcow2",
"version": "5.5.0",
@@ -90,75 +97,82 @@
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FAC_VM_KVM-v500-DATADRIVE.qcow2",
"version": "5.x.x",
"filename": "FAC_VM_KVM-ALL-DATADRIVE.qcow2",
"version": "All",
"md5sum": "09bad6cfe6301930adbc829eb8a67149",
"filesize": 258048,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
}
],
"versions": [
{
"name": "6.0.0",
"images": {
"hda_disk_image": "FAC_VM_KVM-v6-build0010-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
},
{
"name": "5.5.0",
"images": {
"hda_disk_image": "FAC_VM_KVM-v5-build0366-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2"
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
},
{
"name": "5.4.1",
"images": {
"hda_disk_image": "FAC_VM_KVM-v5-build0297-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2"
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
},
{
"name": "5.2.2",
"images": {
"hda_disk_image": "FAC_VM_KVM-v5-build0163-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2"
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
},
{
"name": "5.2.1",
"images": {
"hda_disk_image": "FAC_VM_KVM-v500-build0161-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2"
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
},
{
"name": "5.2.0",
"images": {
"hda_disk_image": "FAC_VM_KVM-v5-build0155-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2"
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
},
{
"name": "5.1.2",
"images": {
"hda_disk_image": "FAC_VM_KVM-v500-build0091-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2"
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
},
{
"name": "5.1.1",
"images": {
"hda_disk_image": "FAC_VM_KVM-v500-build0086-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2"
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
},
{
"name": "5.1.0",
"images": {
"hda_disk_image": "FAC_VM_KVM-v500-build0083-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2"
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
},
{
"name": "5.0.0",
"images": {
"hda_disk_image": "FAC_VM_KVM-v500-build0012-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FAC_VM_KVM-v500-DATADRIVE.qcow2"
"hdb_disk_image": "FAC_VM_KVM-ALL-DATADRIVE.qcow2"
}
}
]
+14
View File
@@ -26,6 +26,13 @@
"kvm": "require"
},
"images": [
{
"filename": "FCHKVM-v400-build0230-FORTINET.out.kvm.qcow2",
"version": "4.2.9",
"md5sum": "a3583f162004da2f1e0b751e7b23504a",
"filesize": 27672576,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FCHKVM-v400-build0226-FORTINET.out.kvm.qcow2",
"version": "4.2.8",
@@ -113,6 +120,13 @@
}
],
"versions": [
{
"name": "4.2.9",
"images": {
"hda_disk_image": "FCHKVM-v400-build0230-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty100G.qcow2"
}
},
{
"name": "4.2.8",
"images": {
+14
View File
@@ -26,6 +26,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FGT_VM64_KVM-v6-build0866-FORTINET.out.kvm.qcow2",
"version": "6.2.0",
"md5sum": "588df9ba0db485976f6681810001ae73",
"filesize": 57868288,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FGT_VM64_KVM-v6-build0200-FORTINET.out.kvm.qcow2",
"version": "6.0.3",
@@ -218,6 +225,13 @@
}
],
"versions": [
{
"name": "6.2.0",
"images": {
"hda_disk_image": "FGT_VM64_KVM-v6-build0866-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "6.0.3",
"images": {
+14
View File
@@ -26,6 +26,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FML_VMKV-64-v60-build0143-FORTINET.out.kvm.qcow2",
"version": "6.0.4",
"md5sum": "e6401ecfe9b145256cccb29757bbddfe",
"filesize": 98959360,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FML_VMKV-64-v60-build0126-FORTINET.out.kvm.qcow2",
"version": "6.0.3",
@@ -162,6 +169,13 @@
}
],
"versions": [
{
"name": "6.0.4",
"images": {
"hda_disk_image": "FML_VMKV-64-v60-build0143-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "6.0.3",
"images": {
+9 -2
View File
@@ -26,6 +26,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FMG_VM64_KVM-v6-build1050-FORTINET.out.kvm.qcow2",
"version": "6.2.0",
"md5sum": "c19d2527f91ad1bbafbde5bf08487867",
"filesize": 126894080,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FMG_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2",
"version": "6.0.3",
@@ -142,9 +149,9 @@
],
"versions": [
{
"name": "6.0.3",
"name": "6.2.0",
"images": {
"hda_disk_image": "FMG_VM64_KVM-v6-build0255-FORTINET.out.kvm.qcow2",
"hda_disk_image": "FMG_VM64_KVM-v6-build1050-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
+14
View File
@@ -26,6 +26,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FPX_KVM-v100-build0162-FORTINET.out.kvm.qcow2",
"version": "1.1.2",
"md5sum": "00db4c04fcc4ac0d7c389a86c71d20a5",
"filesize": 44601344,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FPX_KVM-v100-build0147-FORTINET.out.kvm.qcow2",
"version": "1.1.0",
@@ -43,6 +50,13 @@
}
],
"versions": [
{
"name": "1.1.2",
"images": {
"hda_disk_image": "FPX_KVM-v100-build0162-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "1.1.0",
"images": {
+16 -2
View File
@@ -27,7 +27,14 @@
},
"images": [
{
"filename": "fortirecorder-FRC_VMKV-64-v26-build0607-FORTINET.out.kvm.qcow2",
"filename": "FRC_VMKV-64-v27-build0700-FORTINET.out.kvm.qcow2",
"version": "2.7.1",
"md5sum": "3736c66af7d958fc672fe29439b405b8",
"filesize": 79429632,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FRC_VMKV-64-v26-build0607-FORTINET.out.kvm.qcow2",
"version": "2.6.3",
"md5sum": "ffa5d42119de576631673516f60e028b",
"filesize": 63569920,
@@ -43,10 +50,17 @@
}
],
"versions": [
{
"name": "2.7.1",
"images": {
"hda_disk_image": "FRC_VMKV-64-v27-build0700-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "2.6.3",
"images": {
"hda_disk_image": "fortirecorder-FRC_VMKV-64-v26-build0607-FORTINET.out.kvm.qcow2",
"hda_disk_image": "FRC_VMKV-64-v26-build0607-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
}
+15 -1
View File
@@ -27,6 +27,13 @@
"options": "-smp 2"
},
"images": [
{
"filename": "FSA_KVM-v300-build0060-FORTINET.out.kvm.qcow2",
"version": "3.0.4",
"md5sum": "7e744c4d62430917aea4533672710b5a",
"filesize": 157221376,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FSA_KVM-v300-build0049-FORTINET.out.kvm.qcow2",
"version": "3.0.3",
@@ -92,13 +99,20 @@
},
{
"filename": "FSA-datadrive.qcow2",
"version": "2.x",
"version": "All",
"md5sum": "f2dc0a8fc7591699c364aff400369157",
"filesize": 200192,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
}
],
"versions": [
{
"name": "3.0.4",
"images": {
"hda_disk_image": "FSA_KVM-v300-build0060-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "FSA-datadrive.qcow2"
}
},
{
"name": "3.0.3",
"images": {
@@ -28,6 +28,27 @@
"options": "-smp 4"
},
"images": [
{
"filename": "FortiSIEM-VA-5.2.1.1553-OS.qcow2",
"version": "5.2.1",
"md5sum": "9dc3f4a9614b65c83d3e9733248cbcea",
"filesize": 3902208000,
"download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html"
},
{
"filename": "FortiSIEM-VA-5.2.1.1553-CMDB.qcow2",
"version": "5.2.1",
"md5sum": "ea3f69191eb803cdf021227ec666bf7b",
"filesize": 46858240,
"download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html"
},
{
"filename": "FortiSIEM-VA-5.2.1.1553-SVN.qcow2",
"version": "5.2.1",
"md5sum": "eff32e40baf6ede7bc57ad8d241812ad",
"filesize": 46858240,
"download_url": "https://images-cdn.fortisiem.fortinet.com/VirtualAppliances/release510.html"
},
{
"filename": "FortiSIEM-VA-5.1.0.1336.qcow2",
"version": "5.1.0",
@@ -114,6 +135,14 @@
}
],
"versions": [
{
"name": "5.2.1",
"images": {
"hda_disk_image": "FortiSIEM-VA-5.2.1.1553-OS.qcow2",
"hdb_disk_image": "FortiSIEM-VA-5.2.1.1553-CMDB.qcow2",
"hdc_disk_image": "FortiSIEM-VA-5.2.1.1553-SVN.qcow2"
}
},
{
"name": "5.1.0",
"images": {
+14
View File
@@ -26,6 +26,13 @@
"kvm": "allow"
},
"images": [
{
"filename": "FWB_KVM-v600-build0383-FORTINET.out.kvm.qcow2",
"version": "6.1.0",
"md5sum": "d2dbbde9f03eb716a54119cc3e6055c4",
"filesize": 190120448,
"download_url": "https://support.fortinet.com/Download/FirmwareImages.aspx"
},
{
"filename": "FWB_KVM-v600-build0056-FORTINET.out.kvm.qcow2",
"version": "6.0.2",
@@ -107,6 +114,13 @@
],
"versions": [
{
"name": "6.1.0",
"images": {
"hda_disk_image": "FWB_KVM-v600-build0383-FORTINET.out.kvm.qcow2",
"hdb_disk_image": "empty30G.qcow2"
}
},
{
"name": "6.0.2",
"images": {
+16
View File
@@ -24,6 +24,14 @@
"kvm": "require"
},
"images": [
{
"filename": "FreeNAS-11.2-U3.iso",
"version": "11.2 U3",
"md5sum": "59ee32e2598a792eec0355b40a511251",
"filesize": 600387584,
"download_url": "http://www.freenas.org/download/",
"direct_download_url": "https://download.freenas.org/11.2/STABLE/U3/x64/FreeNAS-11.2-U3.iso"
},
{
"filename": "FreeNAS-11.2-RELEASE.iso",
"version": "11.2",
@@ -90,6 +98,14 @@
}
],
"versions": [
{
"name": "11.2 U3",
"images": {
"hda_disk_image": "empty30G.qcow2",
"hdb_disk_image": "empty30G.qcow2",
"cdrom_image": "FreeNAS-11.2-U3.iso"
}
},
{
"name": "11.2",
"images": {
+17 -1
View File
@@ -14,12 +14,22 @@
"qemu": {
"adapter_type": "virtio-net-pci",
"adapters": 8,
"ram": 256,
"ram": 512,
"hda_disk_interface": "virtio",
"arch": "x86_64",
"console_type": "telnet",
"kvm": "require"
},
"images": [
{
"filename": "frr7.0-vm0.3.qcow2",
"version": "FRR7.0 - VM0.3",
"md5sum": "5fa8ce0ee74215f4c4a8c61778ee0b10",
"filesize": 2044657664,
"download_url": "https://sourceforge.net/projects/frr/files/",
"direct_download_url": "https://sourceforge.net/projects/frr/files/FRR7.0-VM0.3.qcow2.bz2/download",
"compression": "bzip2"
},
{
"filename": "frr6.0-vm0.2.qcow2",
"version": "FRR6.0 - VM0.2",
@@ -40,6 +50,12 @@
}
],
"versions": [
{
"name": "FRR7.0 - VM0.3",
"images": {
"hda_disk_image": "frr7.0-vm0.3.qcow2"
}
},
{
"name": "FRR6.0 - VM0.2",
"images": {
+15
View File
@@ -24,6 +24,15 @@
"kvm": "allow"
},
"images": [
{
"filename": "ipfire-2.21.2gb-ext4.x86_64-full-core129.img",
"version": "2.21.129",
"md5sum": "84801c588174763c585967a2851a7769",
"filesize": 1541160960,
"download_url": "http://www.ipfire.org/download",
"direct_download_url": "https://downloads.ipfire.org/releases/ipfire-2.x/2.21-core129/ipfire-2.21.2gb-ext4.x86_64-full-core129.img.xz",
"compression": "xz"
},
{
"filename": "ipfire-2.21.2gb-ext4.x86_64-full-core124.img",
"version": "2.21.124",
@@ -89,6 +98,12 @@
}
],
"versions": [
{
"name": "2.21.129",
"images": {
"hda_disk_image": "ipfire-2.21.2gb-ext4.x86_64-full-core129.img"
}
},
{
"name": "2.21.124",
"images": {
+14
View File
@@ -20,6 +20,14 @@
"kvm": "require"
},
"images": [
{
"filename": "kali-linux-2019.1a-amd64.iso",
"version": "2019.1a",
"md5sum": "58c6111ed0be1919ea87267e7e65ab0f",
"filesize": 3483873280,
"download_url": "https://www.kali.org/downloads/",
"direct_download_url": "http://cdimage.kali.org/kali-2019.1a/kali-linux-2019.1a-amd64.iso"
},
{
"filename": "kali-linux-2018.4-amd64.iso",
"version": "2018.4",
@@ -94,6 +102,12 @@
}
],
"versions": [
{
"name": "2019.1a",
"images": {
"cdrom_image": "kali-linux-2019.1a-amd64.iso"
}
},
{
"name": "2018.4",
"images": {
+14
View File
@@ -23,6 +23,14 @@
"kvm": "require"
},
"images": [
{
"filename": "kerio-control-appliance-9.3.0-3273-vmware-disk1.vmdk",
"version": "9.3.0",
"md5sum": "6e6faf64b4ffce8b5639cdfce11ba31e",
"filesize": 192825856,
"download_url": "http://www.kerio.com/support/kerio-control",
"direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.3.0-3273/kerio-control-appliance-9.3.0-3273-vmware-disk1.vmdk"
},
{
"filename": "kerio-control-appliance-9.2.7-2921-vmware-disk1.vmdk",
"version": "9.2.7",
@@ -79,6 +87,12 @@
"direct_download_url": "http://cdn.kerio.com/dwn/control/control-9.1.4-1535/kerio-control-appliance-9.1.4-1535-vmware.vmdk" }
],
"versions": [
{
"name": "9.3.0",
"images": {
"hda_disk_image": "kerio-control-appliance-9.3.0-3273-vmware-disk1.vmdk"
}
},
{
"name": "9.2.7",
"images": {
-97
View File
@@ -1,97 +0,0 @@
{
"name": "LEDE",
"category": "router",
"description": "LEDE is a highly extensible GNU/Linux distribution for embedded devices (typically wireless routers). Unlike many other distributions for these routers, OpenWrt is built from the ground up to be a full-featured, easily modifiable operating system for your router. In practice, this means that you can have all the features you need with none of the bloat, powered by a Linux kernel that's more recent than most other distributions.",
"vendor_name": "LEDE Project",
"vendor_url": "https://lede-project.org/",
"documentation_url": "http://wiki.openwrt.org/doc/",
"product_name": "LEDE",
"product_url": "https://lede-project.org/",
"registry_version": 3,
"status": "stable",
"maintainer": "GNS3 Team",
"maintainer_email": "developers@gns3.net",
"usage": "Ethernet0 is the LAN link, Ethernet1 the WAN link.",
"qemu": {
"adapter_type": "virtio-net-pci",
"adapters": 2,
"ram": 64,
"arch": "i386",
"console_type": "telnet",
"kvm": "allow"
},
"images": [
{
"filename": "lede-17.01.4-x86-generic-combined-squashfs.img",
"version": "17.01.4",
"md5sum": "ae5d8d3fcab109565fe337d28e51c4b4",
"filesize": 19779546,
"download_url": "https://downloads.lede-project.org/releases/17.01.4/targets/x86/generic/",
"direct_download_url": "https://downloads.lede-project.org/releases/17.01.4/targets/x86/generic/lede-17.01.4-x86-generic-combined-squashfs.img"
},
{
"filename": "lede-17.01.3-x86-generic-combined-squashfs.img",
"version": "17.01.3",
"md5sum": "d315fc638160a9aec0966d58828bfccf",
"filesize": 19775618,
"download_url": "https://downloads.lede-project.org/releases/17.01.3/targets/x86/generic/",
"direct_download_url": "https://downloads.lede-project.org/releases/17.01.3/targets/x86/generic/lede-17.01.3-x86-generic-combined-squashfs.img"
},
{
"filename": "lede-17.01.2-x86-generic-combined-squashfs.img",
"version": "17.01.2",
"md5sum": "a466e493ef12935dad5e0c622b1a7859",
"filesize": 19774794,
"download_url": "https://downloads.lede-project.org/releases/17.01.2/targets/x86/generic/",
"direct_download_url": "https://downloads.lede-project.org/releases/17.01.2/targets/x86/generic/lede-17.01.2-x86-generic-combined-squashfs.img"
},
{
"filename": "lede-17.01.1-x86-generic-combined-squashfs.img",
"version": "17.01.1",
"md5sum": "b050e734c605a34a429389c752ae7c30",
"filesize": 19771166,
"download_url": "https://downloads.lede-project.org/releases/17.01.1/targets/x86/generic/",
"direct_download_url": "https://downloads.lede-project.org/releases/17.01.1/targets/x86/generic/lede-17.01.1-x86-generic-combined-squashfs.img"
},
{
"filename": "lede-17.01.0-r3205-59508e3-x86-generic-combined-squashfs.img",
"version": "17.01.0",
"md5sum": "3c5e068d50a377d4e26b548ab1ca7b1e",
"filesize": 19755118,
"download_url": "https://downloads.lede-project.org/releases/17.01.0/targets/x86/generic/",
"direct_download_url": "https://downloads.lede-project.org/releases/17.01.0/targets/x86/generic/lede-17.01.0-r3205-59508e3-x86-generic-combined-squashfs.img"
}
],
"versions": [
{
"name": "lede 17.01.4",
"images": {
"hda_disk_image": "lede-17.01.4-x86-generic-combined-squashfs.img"
}
},
{
"name": "lede 17.01.3",
"images": {
"hda_disk_image": "lede-17.01.3-x86-generic-combined-squashfs.img"
}
},
{
"name": "lede 17.01.2",
"images": {
"hda_disk_image": "lede-17.01.2-x86-generic-combined-squashfs.img"
}
},
{
"name": "lede 17.01.1",
"images": {
"hda_disk_image": "lede-17.01.1-x86-generic-combined-squashfs.img"
}
},
{
"name": "lede 17.01.0",
"images": {
"hda_disk_image": "lede-17.01.0-r3205-59508e3-x86-generic-combined-squashfs.img"
}
}
]
}
+15
View File
@@ -26,6 +26,15 @@
"options": "-nographic"
},
"images": [
{
"filename": "chr-6.44.2.img",
"version": "6.44.2",
"md5sum": "f1ddaa47829e12c1f9f023d8c06b88cc",
"filesize": 67108864,
"download_url": "http://www.mikrotik.com/download",
"direct_download_url": "https://download.mikrotik.com/routeros/6.44.2/chr-6.44.2.img.zip",
"compression": "zip"
},
{
"filename": "chr-6.43.8.img",
"version": "6.43.8",
@@ -280,6 +289,12 @@
}
],
"versions": [
{
"name": "6.44.2",
"images": {
"hda_disk_image": "chr-6.44.2.img"
}
},
{
"name": "6.43.8",
"images": {
+1 -1
View File
@@ -15,7 +15,7 @@
"qemu": {
"adapter_type": "virtio-net-pci",
"adapters": 4,
"ram": 64,
"ram": 128,
"arch": "x86_64",
"console_type": "telnet",
"kvm": "allow"
@@ -22,6 +22,15 @@
"kvm": "require"
},
"images": [
{
"filename": "PacketFenceZEN_USB-8.3.0.img",
"version": "8.3.0",
"md5sum": "b9de52dc2513220ad42d350486da4884",
"filesize": 3221225472,
"download_url": "https://packetfence.org/download.html#/zen",
"direct_download_url": "https://sourceforge.net/projects/packetfence/files/PacketFence%20ZEN/8.3.0/PacketFenceZEN_USB-8.3.0.tar.bz2/download",
"compression": "bzip2"
},
{
"filename": "PacketFenceZEN_USB-8.1.0.img",
"version": "8.1.0",
@@ -114,6 +123,12 @@
}
],
"versions": [
{
"name": "8.3.0",
"images": {
"hda_disk_image": "PacketFenceZEN_USB-8.3.0.img"
}
},
{
"name": "8.1.0",
"images": {
+4 -4
View File
@@ -27,10 +27,10 @@
},
"images": [
{
"filename": "MSEdge-Win10-VMWare-disk1.vmdk",
"filename": "MSEdge-Win10-VMware-disk1.vmdk",
"version": "10 w/ Edge",
"md5sum": "fef74c69e1949480d4e2095324a169af",
"filesize": 5636608512,
"md5sum": "670f3c2b03a5629dc85d0d1c261e5929",
"filesize": 7293386240,
"download_url": "https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/"
},
{
@@ -80,7 +80,7 @@
{
"name": "10 w/ Edge",
"images": {
"hda_disk_image": "MSEdge-Win10-VMWare-disk1.vmdk"
"hda_disk_image": "MSEdge-Win10-VMware-disk1.vmdk"
}
},
{
+25 -7
View File
@@ -26,6 +26,7 @@ import shlex
import aiohttp
import subprocess
import os
import re
from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer
from gns3server.utils.asyncio.raw_command_server import AsyncioRawCommandServer
@@ -64,11 +65,12 @@ class DockerVM(BaseNode):
:param console_http_port: Port to redirect HTTP queries
:param console_http_path: Url part with the path of the web interface
:param extra_hosts: Hosts which will be written into /etc/hosts into docker conainer
:param extra_volumes: Additional directories to make persistent
"""
def __init__(self, name, node_id, project, manager, image, console=None, aux=None, start_command=None,
adapters=None, environment=None, console_type="telnet", console_resolution="1024x768",
console_http_port=80, console_http_path="/", extra_hosts=None):
console_http_port=80, console_http_path="/", extra_hosts=None, extra_volumes=[]):
super().__init__(name, node_id, project, manager, console=console, aux=aux, allocate_aux=True, console_type=console_type)
@@ -89,6 +91,7 @@ class DockerVM(BaseNode):
self._console_http_port = console_http_port
self._console_websocket = None
self._extra_hosts = extra_hosts
self._extra_volumes = extra_volumes or []
self._permissions_fixed = False
self._display = None
self._closing = False
@@ -125,7 +128,8 @@ class DockerVM(BaseNode):
"status": self.status,
"environment": self.environment,
"node_directory": self.working_path,
"extra_hosts": self.extra_hosts
"extra_hosts": self.extra_hosts,
"extra_volumes": self.extra_volumes,
}
def _get_free_display_port(self):
@@ -197,6 +201,14 @@ class DockerVM(BaseNode):
def extra_hosts(self, extra_hosts):
self._extra_hosts = extra_hosts
@property
def extra_volumes(self):
return self._extra_volumes
@extra_volumes.setter
def extra_volumes(self, extra_volumes):
self._extra_volumes = extra_volumes
async def _get_container_state(self):
"""
Returns the container state (e.g. running, paused etc.)
@@ -242,11 +254,17 @@ class DockerVM(BaseNode):
binds.append("{}:/gns3volumes/etc/network:rw".format(network_config))
self._volumes = ["/etc/network"]
volumes = image_info.get("Config", {}).get("Volumes")
if volumes is None:
return binds
for volume in volumes.keys():
volumes = list((image_info.get("Config", {}).get("Volumes") or {}).keys())
for volume in self._extra_volumes:
if not volume.strip() or volume[0] != "/" or volume.find("..") >= 0:
raise DockerError("Persistent volume '{}' has invalid format. It must start with a '/' and not contain '..'.".format(volume))
volumes.extend(self._extra_volumes)
# define lambdas for validation checks
nf = lambda x: re.sub(r"//+", "/", (x if x.endswith("/") else x + "/"))
incompatible = lambda v1, v2: nf(v1).startswith(nf(v2)) or nf(v2).startswith(nf(v1))
for volume in volumes:
if [ v for v in self._volumes if incompatible(v, volume) ] :
raise DockerError("Duplicate persistent volume {} detected.\n\nVolumes specified in docker image as well as user specified persistent volumes must be unique.".format(volume))
source = os.path.join(self.working_dir, os.path.relpath(volume, "/"))
os.makedirs(source, exist_ok=True)
binds.append("{}:/gns3volumes{}".format(source, volume))
@@ -79,7 +79,7 @@ class EthernetSwitch(Device):
:param hypervisor: Dynamips hypervisor instance
"""
def __init__(self, name, node_id, project, manager, console=None, console_type="telnet", ports=None, hypervisor=None):
def __init__(self, name, node_id, project, manager, console=None, console_type="none", ports=None, hypervisor=None):
super().__init__(name, node_id, project, manager, hypervisor)
self._nios = {}
@@ -131,7 +131,12 @@ class EthernetSwitch(Device):
@console_type.setter
def console_type(self, console_type):
self._console_type = console_type
if self._console_type != console_type:
if console_type == "telnet":
self.project.emit("log.warning", {
"message": '"{name}": Telnet access for switches is not available in this version of GNS3'.format(name=self._name)})
self._console_type = console_type
@property
def ports_mapping(self):
@@ -184,6 +189,8 @@ class EthernetSwitch(Device):
# self._telnet_server = (await asyncio.start_server(self._telnet.run, self._manager.port_manager.console_host, self.console))
#except OSError as e:
# self.project.emit("log.warning", {"message": "Could not start Telnet server on socket {}:{}: {}".format(self._manager.port_manager.console_host, self.console, e)})
if self._console_type == "telnet":
self.project.emit("log.warning", {"message": '"{name}": Telnet access for switches is not available in this version of GNS3'.format(name=self._name)})
self._hypervisor.devices.append(self)
async def set_name(self, new_name):
+4 -4
View File
@@ -342,7 +342,7 @@ class IOUVM(BaseNode):
@iourc_content.setter
def iourc_content(self, value):
if value is not None:
if value:
# If we don't save the value in the ~/ the licence is lost at project
# reload
path = os.path.join(os.path.expanduser("~/"), ".iourc")
@@ -402,6 +402,7 @@ class IOUVM(BaseNode):
raise IOUError("Invalid licence check setting")
if server_wide_license_check is False:
log.warning("License check is explicitly disabled on this server")
return
config = configparser.ConfigParser()
@@ -508,7 +509,7 @@ class IOUVM(BaseNode):
iourc_path = self.iourc_path
if not iourc_path:
raise IOUError("Could not find an iourc file (IOU license)")
raise IOUError("Could not find an iourc file (IOU license), please configure an IOU license")
if not os.path.isfile(iourc_path):
raise IOUError("The iourc path '{}' is not a regular file".format(iourc_path))
@@ -528,8 +529,7 @@ class IOUVM(BaseNode):
# created a environment variable pointing to the iourc file.
env = os.environ.copy()
if "IOURC" not in os.environ:
if "IOURC" not in os.environ and iourc_path:
env["IOURC"] = iourc_path
# create a symbolic link to the image to avoid IOU error "failed code signing checks"
+56 -26
View File
@@ -746,7 +746,7 @@ class QemuVM(BaseNode):
log.info('QEMU VM "{name}" [{id}] has set the QEMU initrd path to {initrd}'.format(name=self._name,
id=self._id,
initrd=initrd))
if "asa" in initrd:
if "asa" in initrd and self._initrd != initrd:
self.project.emit("log.warning", {"message": "Warning ASA 8 is not supported by GNS3 and Cisco, please use ASAv instead. Depending of your hardware and OS this could not work or you could be limited to one instance. If ASA 8 is not booting their is no GNS3 solution, you must to upgrade to ASAv."})
self._initrd = initrd
@@ -966,10 +966,14 @@ class QemuVM(BaseNode):
set_link_commands.append("set_link gns3-{} off".format(adapter_number))
else:
set_link_commands.append("set_link gns3-{} off".format(adapter_number))
await self._control_vm_commands(set_link_commands)
if "-loadvm" not in command_string:
# only set the link statuses if not restoring a previous VM state
await self._control_vm_commands(set_link_commands)
try:
await self.start_wrap_console()
if self.is_running():
await self.start_wrap_console()
except OSError as e:
raise QemuError("Could not start Telnet QEMU console {}\n".format(e))
@@ -1081,7 +1085,15 @@ class QemuVM(BaseNode):
return result
try:
writer.write(command.encode('ascii') + b"\n")
cmd_byte = command.encode('ascii')
writer.write(cmd_byte + b"\n")
if not expected:
while True:
line = await asyncio.wait_for(reader.readline(), timeout=3) # echo of the command
if not line or cmd_byte in line:
break
except asyncio.TimeoutError:
log.warning("Missing echo of command '{}'".format(command))
except OSError as e:
log.warning("Could not write to QEMU monitor: {}".format(e))
writer.close()
@@ -1089,13 +1101,15 @@ class QemuVM(BaseNode):
if expected:
try:
while result is None:
line = await reader.readline()
line = await asyncio.wait_for(reader.readline(), timeout=3)
if not line:
break
for expect in expected:
if expect in line:
result = line.decode("utf-8").strip()
break
except asyncio.TimeoutError:
log.warning("Timeout while waiting for result of command '{}'".format(command))
except (ConnectionError, EOFError) as e:
log.warning("Could not read from QEMU monitor: {}".format(e))
writer.close()
@@ -1118,6 +1132,9 @@ class QemuVM(BaseNode):
log.info("Execute QEMU monitor command: {}".format(command))
try:
writer.write(command.encode('ascii') + b"\n")
await asyncio.wait_for(reader.readline(), timeout=3) # echo of the command
except asyncio.TimeoutError:
log.warning("Missing echo of command '{}'".format(command))
except OSError as e:
log.warning("Could not write to QEMU monitor: {}".format(e))
writer.close()
@@ -1130,7 +1147,9 @@ class QemuVM(BaseNode):
if not (await super().close()):
return False
self.on_close = "power_off"
#FIXME: Don't wait for ACPI shutdown when closing the project, should we?
if self.on_close == "shutdown_signal":
self.on_close = "power_off"
await self.stop()
for adapter in self._ethernet_adapters:
@@ -1835,18 +1854,22 @@ class QemuVM(BaseNode):
if not os.path.exists(disk):
continue
output = await subprocess_check_output(qemu_img_path, "info", "--output=json", disk)
json_data = json.loads(output)
if "snapshots" in json_data:
for snapshot in json_data["snapshots"]:
if snapshot["name"] == snapshot_name:
# delete the snapshot
command = [qemu_img_path, "snapshot", "-d", snapshot_name, disk]
retcode = await self._qemu_img_exec(command)
if retcode:
stdout = self.read_qemu_img_stdout()
log.warning("Could not delete saved VM state from disk {}: {}".format(disk, stdout))
else:
log.info("Deleted saved VM state from disk {}".format(disk))
if output:
try:
json_data = json.loads(output)
except ValueError as e:
raise QemuError("Invalid JSON data returned by qemu-img while looking for the Qemu VM saved state snapshot: {}".format(e))
if "snapshots" in json_data:
for snapshot in json_data["snapshots"]:
if snapshot["name"] == snapshot_name:
# delete the snapshot
command = [qemu_img_path, "snapshot", "-d", snapshot_name, disk]
retcode = await self._qemu_img_exec(command)
if retcode:
stdout = self.read_qemu_img_stdout()
log.warning("Could not delete saved VM state from disk {}: {}".format(disk, stdout))
else:
log.info("Deleted saved VM state from disk {}".format(disk))
except subprocess.SubprocessError as e:
raise QemuError("Error while looking for the Qemu VM saved state snapshot: {}".format(e))
@@ -1866,14 +1889,19 @@ class QemuVM(BaseNode):
if not os.path.exists(disk):
continue
output = await subprocess_check_output(qemu_img_path, "info", "--output=json", disk)
json_data = json.loads(output)
if "snapshots" in json_data:
for snapshot in json_data["snapshots"]:
if snapshot["name"] == snapshot_name:
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]
if output:
try:
json_data = json.loads(output)
except ValueError as e:
raise QemuError("Invalid JSON data returned by qemu-img while looking for the Qemu VM saved state snapshot: {}".format(e))
if "snapshots" in json_data:
for snapshot in json_data["snapshots"]:
if snapshot["name"] == snapshot_name:
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]
except subprocess.SubprocessError as e:
raise QemuError("Error while looking for the Qemu VM saved state snapshot: {}".format(e))
return []
@@ -1889,6 +1917,8 @@ class QemuVM(BaseNode):
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('"', '\\"') + '"')
if self._console:
additional_options = additional_options.replace("%console-port%", str(self._console))
command = [self.qemu_path]
command.extend(["-name", self._name])
command.extend(["-m", "{}M".format(self._ram)])
+7 -6
View File
@@ -54,7 +54,7 @@ class Config:
self._watch_callback = []
appname = "GNS3"
version = "{}.{}.{}".format(__version_info__[0], __version_info__[1], __version_info__[2])
version = "{}.{}".format(__version_info__[0], __version_info__[1])
if sys.platform.startswith("win"):
@@ -125,20 +125,21 @@ class Config:
if self._main_config_file is None:
# TODO: migrate versioned config file from a previous version of GNS3 (for instance 2.2.0 -> 2.2.1)
# TODO: migrate versioned config file from a previous version of GNS3 (for instance 2.2 -> 2.3) + support profiles
# migrate post version 2.2.0 config files if they exist
os.makedirs(versioned_user_dir, exist_ok=True)
try:
# migrate the server config file
old_server_config = os.path.join(legacy_user_dir, server_filename)
if os.path.exists(old_server_config):
new_server_config = os.path.join(versioned_user_dir, server_filename)
new_server_config = os.path.join(versioned_user_dir, server_filename)
if not os.path.exists(new_server_config) and os.path.exists(old_server_config):
shutil.copyfile(old_server_config, new_server_config)
# migrate the controller config file
old_controller_config = os.path.join(legacy_user_dir, controller_filename)
if os.path.exists(old_controller_config):
shutil.copyfile(old_controller_config, os.path.join(versioned_user_dir, controller_filename))
new_controller_config = os.path.join(versioned_user_dir, controller_filename)
if not os.path.exists(new_controller_config) and os.path.exists(old_controller_config):
shutil.copyfile(old_controller_config, os.path.join(versioned_user_dir, new_controller_config))
except OSError as e:
log.error("Cannot migrate old config files: {}".format(e))
+1
View File
@@ -128,6 +128,7 @@ class Controller:
except (ComputeError, aiohttp.web.HTTPError, OSError):
pass
await self.gns3vm.exit_vm()
#self.save()
self._computes = {}
self._projects = {}
+37 -17
View File
@@ -74,6 +74,7 @@ class Compute:
self._user = None
self._password = None
self._connected = False
self._notifications = None
self._closed = False # Close mean we are destroying the compute node
self._controller = controller
self._set_auth(user, password)
@@ -150,9 +151,15 @@ class Compute:
self._controller.save()
async def close(self):
self._connected = False
if self._http_session and not self._http_session.closed:
await self._http_session.close()
try:
if self._notifications:
await self._notifications
except asyncio.CancelledError:
pass
self._closed = True
@property
@@ -417,25 +424,38 @@ class Compute:
Connect to the notification stream
"""
async with self._session().ws_connect(self._getUrl("/notifications/ws"), auth=self._auth) as ws:
async for response in ws:
if response.type == aiohttp.WSMsgType.TEXT and response.data:
msg = json.loads(response.data)
action = msg.pop("action")
event = msg.pop("event")
project_id = msg.pop("project_id", None)
if action == "ping":
self._cpu_usage_percent = event["cpu_usage_percent"]
self._memory_usage_percent = event["memory_usage_percent"]
#FIXME: slow down number of compute events
self._controller.notification.controller_emit("compute.updated", self.__json__())
ws_url = self._getUrl("/notifications/ws")
try:
async with self._session().ws_connect(ws_url, auth=self._auth, heartbeat=10) as ws:
log.info("Connected to compute WebSocket '{}'".format(ws_url))
async for response in ws:
if response.type == aiohttp.WSMsgType.TEXT:
msg = json.loads(response.data)
action = msg.pop("action")
event = msg.pop("event")
project_id = msg.pop("project_id", None)
if action == "ping":
self._cpu_usage_percent = event["cpu_usage_percent"]
self._memory_usage_percent = event["memory_usage_percent"]
#FIXME: slow down number of compute events
self._controller.notification.controller_emit("compute.updated", self.__json__())
else:
await self._controller.notification.dispatch(action, event, project_id=project_id, compute_id=self.id)
else:
await self._controller.notification.dispatch(action, event, project_id=project_id, compute_id=self.id)
elif response.type == aiohttp.WSMsgType.CLOSED or response.type == aiohttp.WSMsgType.ERROR or response.data is None:
self._connected = False
break
if response.type == aiohttp.WSMsgType.CLOSE:
await ws.close()
elif response.type == aiohttp.WSMsgType.ERROR:
log.error("Error received on compute WebSocket '{}': {}".format(ws_url, ws.exception()))
elif response.type == aiohttp.WSMsgType.CLOSED:
pass
self._connected = False
break
except aiohttp.client_exceptions.ClientResponseError as e:
log.error("Client response error received on compute WebSocket '{}': {}".format(ws_url,e))
finally:
log.info("Connection closed to compute WebSocket '{}'".format(ws_url))
# Try to reconnect after 1 seconds if server unavailable only if not during tests (otherwise we create a ressources usage bomb)
# Try to reconnect after 1 second if server unavailable only if not during tests (otherwise we create a ressources usage bomb)
if not hasattr(sys, "_called_from_test") or not sys._called_from_test:
asyncio.get_event_loop().call_later(1, lambda: asyncio.ensure_future(self.connect()))
+74 -5
View File
@@ -22,10 +22,16 @@ import uuid
import shutil
import zipfile
import aiohttp
import aiofiles
import itertools
import tempfile
from .topology import load_topology
from ..utils.asyncio import wait_run_in_executor
from ..utils.asyncio import aiozipstream
import logging
log = logging.getLogger(__name__)
"""
Handle the import of project from a .gns3project
@@ -126,6 +132,14 @@ async def import_project(controller, project_id, stream, location=None, name=Non
node["compute_id"] = "vm"
else:
# Round-robin through available compute resources.
# computes = []
# for compute_id in controller.computes:
# compute = controller.get_compute(compute_id)
# # only use the local compute or any connected compute
# if compute_id == "local" or compute.connected:
# computes.append(compute_id)
# else:
# log.warning(compute.name, "is not connected!")
compute_nodes = itertools.cycle(controller.computes)
for node in topology["topology"]["nodes"]:
node["compute_id"] = next(compute_nodes)
@@ -148,8 +162,13 @@ async def import_project(controller, project_id, stream, location=None, name=Non
json.dump(topology, f, indent=4)
os.remove(os.path.join(path, "project.gns3"))
if os.path.exists(os.path.join(path, "images")):
_import_images(controller, path)
images_path = os.path.join(path, "images")
if os.path.exists(images_path):
await _import_images(controller, images_path)
snapshots_path = os.path.join(path, "snapshots")
if os.path.exists(snapshots_path):
await _import_snapshots(snapshots_path, project_name, project_id)
project = await controller.load_project(dot_gns3_path, load=False)
return project
@@ -204,13 +223,13 @@ async def _upload_file(compute, project_id, file_path, path):
await compute.http_query("POST", path, f, timeout=None)
def _import_images(controller, path):
async def _import_images(controller, images_path):
"""
Copy images to the images directory or delete them if they already exists.
"""
image_dir = controller.images_path()
root = os.path.join(path, "images")
root = images_path
for (dirpath, dirnames, filenames) in os.walk(root, followlinks=False):
for filename in filenames:
path = os.path.join(dirpath, filename)
@@ -218,4 +237,54 @@ def _import_images(controller, path):
continue
dst = os.path.join(image_dir, os.path.relpath(path, root))
os.makedirs(os.path.dirname(dst), exist_ok=True)
shutil.move(path, dst)
await wait_run_in_executor(shutil.move, path, dst)
async def _import_snapshots(snapshots_path, project_name, project_id):
"""
Import the snapshots and update their project name and ID to be the same as the main project.
"""
for snapshot in os.listdir(snapshots_path):
if not snapshot.endswith(".gns3project"):
continue
snapshot_path = os.path.join(snapshots_path, snapshot)
with tempfile.TemporaryDirectory(dir=snapshots_path) as tmpdir:
# extract everything to a temporary directory
try:
with open(snapshot_path, "rb") as f:
with zipfile.ZipFile(f) as zip_file:
await wait_run_in_executor(zip_file.extractall, tmpdir)
except OSError as e:
raise aiohttp.web.HTTPConflict(text="Cannot open snapshot '{}': {}".format(os.path.basename(snapshot), e))
except zipfile.BadZipFile:
raise aiohttp.web.HTTPConflict(text="Cannot extract files from snapshot '{}': not a GNS3 project (invalid zip)".format(os.path.basename(snapshot)))
# patch the topology with the correct project name and ID
try:
topology_file_path = os.path.join(tmpdir, "project.gns3")
with open(topology_file_path, encoding="utf-8") as f:
topology = json.load(f)
topology["name"] = project_name
topology["project_id"] = project_id
with open(topology_file_path, "w+", encoding="utf-8") as f:
json.dump(topology, f, indent=4, sort_keys=True)
except OSError as e:
raise aiohttp.web.HTTPConflict(text="Cannot update snapshot '{}': the project.gns3 file cannot be modified: {}".format(os.path.basename(snapshot), e))
except (ValueError, KeyError):
raise aiohttp.web.HTTPConflict(text="Cannot update snapshot '{}': the project.gns3 file is corrupted".format(os.path.basename(snapshot)))
# write everything back to the original snapshot file
try:
with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream:
for root, dirs, files in os.walk(tmpdir, topdown=True, followlinks=False):
for file in files:
path = os.path.join(root, file)
zstream.write(path, os.path.relpath(path, tmpdir))
async with aiofiles.open(snapshot_path, 'wb+') as f:
async for chunk in zstream:
await f.write(chunk)
except OSError as e:
raise aiohttp.web.HTTPConflict(text="Cannot update snapshot '{}': the snapshot cannot be recreated: {}".format(os.path.basename(snapshot), e))
+3 -3
View File
@@ -187,7 +187,7 @@ class Node:
if not os.path.isabs(path):
path = os.path.join(self.project.controller.configs_path(), path)
try:
with open(path, encoding="utf-8") as f:
with open(path, encoding="utf-8", errors="ignore") as f:
return f.read()
except OSError:
return None
@@ -495,8 +495,8 @@ class Node:
if self.node_type == "iou":
license_check = self._project.controller.iou_license.get("license_check", True)
iourc_content = self._project.controller.iou_license.get("iourc_content", None)
if license_check and not iourc_content:
raise aiohttp.web.HTTPConflict(text="IOU licence is not configured")
#if license_check and not iourc_content:
# raise aiohttp.web.HTTPConflict(text="IOU licence is not configured")
await self.post("/start", timeout=240, data={"license_check": license_check, "iourc_content": iourc_content})
else:
await self.post("/start", data=data, timeout=240)
+2
View File
@@ -567,6 +567,8 @@ class Project:
@open_required
async def delete_node(self, node_id):
node = self.get_node(node_id)
if node.locked:
raise aiohttp.web.HTTPConflict(text="Node {} cannot be deleted because it is locked".format(node.name))
await self.__delete_node_links(node)
self.remove_allocated_node_name(node.name)
del self._nodes[node.id]
+1 -1
View File
@@ -63,7 +63,7 @@ class TemplateManager:
builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "cloud"), {"template_type": "cloud", "name": "Cloud", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True))
builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "nat"), {"template_type": "nat", "name": "NAT", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True))
builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "vpcs"), {"template_type": "vpcs", "name": "VPCS", "default_name_format": "PC-{0}", "category": 2, "symbol": ":/symbols/vpcs_guest.svg", "properties": {"base_script_file": "vpcs_base_config.txt"}}, builtin=True))
builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_switch"), {"template_type": "ethernet_switch", "console_type": "telnet", "name": "Ethernet switch", "category": 1, "symbol": ":/symbols/ethernet_switch.svg"}, builtin=True))
builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_switch"), {"template_type": "ethernet_switch", "console_type": "none", "name": "Ethernet switch", "category": 1, "symbol": ":/symbols/ethernet_switch.svg"}, builtin=True))
builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_hub"), {"template_type": "ethernet_hub", "name": "Ethernet hub", "category": 1, "symbol": ":/symbols/hub.svg"}, builtin=True))
builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "frame_relay_switch"), {"template_type": "frame_relay_switch", "name": "Frame Relay switch", "category": 1, "symbol": ":/symbols/frame_relay_switch.svg"}, builtin=True))
builtins.append(Template(uuid.uuid3(uuid.NAMESPACE_DNS, "atm_switch"), {"template_type": "atm_switch", "name": "ATM switch", "category": 1, "symbol": ":/symbols/atm_switch.svg"}, builtin=True))
+5 -4
View File
@@ -128,17 +128,18 @@ def load_topology(path):
raise aiohttp.web.HTTPConflict(text="Could not load topology {}: {}".format(path, str(e)))
if topo.get("revision", 0) > GNS3_FILE_FORMAT_REVISION:
raise aiohttp.web.HTTPConflict(text="This project is designed for a more recent version of GNS3 please update GNS3 to version {} or later".format(topo["version"]))
raise aiohttp.web.HTTPConflict(text="This project was created with more recent version of GNS3 (file revision: {}). Please upgrade GNS3 to version {} or later".format(topo["revision"], topo["version"]))
changed = False
if "revision" not in topo or topo["revision"] < GNS3_FILE_FORMAT_REVISION:
# If it's an old GNS3 file we need to convert it
# first we backup the file
# Convert the topology if this is an old one but backup the file first
try:
shutil.copy(path, path + ".backup{}".format(topo.get("revision", 0)))
except (OSError) as e:
except OSError as e:
raise aiohttp.web.HTTPConflict(text="Can't write backup of the topology {}: {}".format(path, str(e)))
changed = True
# update the version because we converted the topology
topo["version"] = __version__
if "revision" not in topo or topo["revision"] < 5:
topo = _convert_1_3_later(topo, path)
+1 -1
View File
@@ -58,7 +58,7 @@ class CrashReport:
Report crash to a third party service
"""
DSN = "https://eb305634570047afb80a73d634baa5f2:453d676bad2b4d068326e6cb22af7ae5@sentry.io/38482"
DSN = "https://eb9c34a9e4504bf99a6392a3ed2e0568:65d873fc33544886b239628c5e8577e4@sentry.io/38482"
if hasattr(sys, "frozen"):
cacert = get_resource("cacert.pem")
if cacert is not None and os.path.isfile(cacert):
@@ -61,7 +61,8 @@ class DockerHandler:
console_http_port=request.json.get("console_http_port", 80),
console_http_path=request.json.get("console_http_path", "/"),
aux=request.json.get("aux"),
extra_hosts=request.json.get("extra_hosts"))
extra_hosts=request.json.get("extra_hosts"),
extra_volumes=request.json.get("extra_volumes"))
for name, value in request.json.items():
if name != "node_id":
if hasattr(container, name) and getattr(container, name) != value:
@@ -316,7 +317,7 @@ class DockerHandler:
props = [
"name", "console", "aux", "console_type", "console_resolution",
"console_http_port", "console_http_path", "start_command",
"environment", "adapters", "extra_hosts"
"environment", "adapters", "extra_hosts", "extra_volumes"
]
changed = False
@@ -21,6 +21,9 @@ from aiohttp.web import WebSocketResponse
from gns3server.web.route import Route
from gns3server.compute.notification_manager import NotificationManager
import logging
log = logging.getLogger(__name__)
async def process_websocket(ws):
"""
@@ -44,7 +47,7 @@ class NotificationHandler:
request.app['websockets'].add(ws)
asyncio.ensure_future(process_websocket(ws))
log.info("New client has connected to compute WebSocket")
try:
with notifications.queue() as queue:
while True:
@@ -53,6 +56,7 @@ class NotificationHandler:
break
await ws.send_str(notification)
finally:
log.info("Client has disconnected from compute WebSocket")
if not ws.closed:
await ws.close()
request.app['websockets'].discard(ws)
@@ -72,7 +72,9 @@ class GNS3VMHandler:
})
async def update(request, response):
gns3_vm = Controller().instance().gns3vm
controller = Controller().instance()
gns3_vm = controller.gns3vm
await gns3_vm.update_settings(request.json)
controller.save()
response.json(gns3_vm)
response.set_status(201)
@@ -189,7 +189,8 @@ class NodeHandler:
status_codes={
204: "Instance deleted",
400: "Invalid request",
404: "Instance doesn't exist"
404: "Instance doesn't exist",
409: "Cannot delete locked node"
},
description="Delete a node instance")
async def delete(request, response):
@@ -21,6 +21,9 @@ from aiohttp.web import WebSocketResponse
from gns3server.web.route import Route
from gns3server.controller import Controller
import logging
log = logging.getLogger(__name__)
async def process_websocket(ws):
"""
@@ -67,6 +70,7 @@ class NotificationHandler:
request.app['websockets'].add(ws)
asyncio.ensure_future(process_websocket(ws))
log.info("New client has connected to controller WebSocket")
try:
with controller.notification.controller_queue() as queue:
while True:
@@ -75,6 +79,7 @@ class NotificationHandler:
break
await ws.send_str(notification)
finally:
log.info("Client has disconnected from controller WebSocket")
if not ws.closed:
await ws.close()
request.app['websockets'].discard(ws)
@@ -305,6 +305,10 @@ class ProjectHandler:
controller = Controller.instance()
project = await controller.get_loaded_project(request.match_info["project_id"])
if request.query.get("include_snapshots", "no").lower() == "yes":
include_snapshots = True
else:
include_snapshots = False
if request.query.get("include_images", "no").lower() == "yes":
include_images = True
else:
@@ -323,7 +327,7 @@ class ProjectHandler:
begin = time.time()
with tempfile.TemporaryDirectory() as tmp_dir:
with aiozipstream.ZipFile(compression=compression) as zstream:
await export_project(zstream, project, tmp_dir, include_images=include_images)
await export_project(zstream, project, tmp_dir, include_snapshots=include_snapshots, include_images=include_images)
# We need to do that now because export could failed and raise an HTTP error
# that why response start need to be the later possible
+9 -3
View File
@@ -91,7 +91,6 @@ def parse_arguments(argv):
parser.add_argument("--host", help="run on the given host/IP address")
parser.add_argument("--port", help="run on the given port", type=int)
parser.add_argument("--ssl", action="store_true", help="run in SSL mode")
parser.add_argument("--no-ubridge", action="store_false", help="do not use ubridge to handle node connections")
parser.add_argument("--config", help="Configuration file")
parser.add_argument("--certfile", help="SSL cert file")
parser.add_argument("--certkey", help="SSL key file")
@@ -102,6 +101,9 @@ def parse_arguments(argv):
parser.add_argument("-d", "--debug", action="store_true", help="show debug logs")
parser.add_argument("--shell", action="store_true", help="start a shell inside the server (debugging purpose only you need to install ptpython before)")
parser.add_argument("--log", help="send output to logfile instead of console")
parser.add_argument("--logmaxsize", help="maximum logfile size in bytes (default is 10MB)")
parser.add_argument("--logbackupcount", help="number of historical log files to keep (default is 10)")
parser.add_argument("--logcompression", action="store_true", help="compress inactive (historical) logs")
parser.add_argument("--daemon", action="store_true", help="start as a daemon")
parser.add_argument("--pid", help="store process pid")
parser.add_argument("--profile", help="Settings profile (blank will use default settings files)")
@@ -124,7 +126,10 @@ def parse_arguments(argv):
"allow": config.getboolean("allow_remote_console", False),
"quiet": config.getboolean("quiet", False),
"debug": config.getboolean("debug", False),
"logfile": config.getboolean("logfile", "")
"logfile": config.getboolean("logfile", ""),
"logmaxsize": config.get("logmaxsize", 10000000), # default is 10MB
"logbackupcount": config.get("logbackupcount", 10),
"logcompression": config.getboolean("logcompression", False)
}
parser.set_defaults(**defaults)
@@ -209,7 +214,8 @@ def run():
if args.debug:
level = logging.DEBUG
user_log = init_logger(level, logfile=args.log, quiet=args.quiet)
user_log = init_logger(level, logfile=args.log, max_bytes=int(args.logmaxsize), backup_count=int(args.logbackupcount),
compression=args.logcompression, quiet=args.quiet)
user_log.info("GNS3 server version {}".format(__version__))
current_year = datetime.date.today().year
user_log.info("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year))
+16
View File
@@ -95,6 +95,14 @@ DOCKER_CREATE_SCHEMA = {
"type": ["string", "null"],
"minLength": 0,
},
"extra_volumes": {
"description": "Additional directories to make persistent",
"type": "array",
"minItems": 0,
"items": {
"type": "string"
}
},
"container_id": {
"description": "Docker container ID Read only",
"type": "string",
@@ -198,6 +206,14 @@ DOCKER_OBJECT_SCHEMA = {
"type": ["string", "null"],
"minLength": 0,
},
"extra_volumes": {
"description": "Additional directories to make persistent",
"type": "array",
"minItems": 0,
"items": {
"type": "string",
}
},
"node_directory": {
"description": "Path to the node working directory Read only",
"type": "string"
+6 -1
View File
@@ -80,7 +80,12 @@ DOCKER_TEMPLATE_PROPERTIES = {
"extra_hosts": {
"description": "Docker extra hosts (added to /etc/hosts)",
"type": "string",
"default": "",
"default": ""
},
"extra_volumes": {
"description": "Additional directories to make persistent",
"type": "array",
"default": []
},
"custom_adapters": CUSTOM_ADAPTERS_ARRAY_SCHEMA
}
@@ -109,7 +109,7 @@ ETHERNET_SWITCH_TEMPLATE_PROPERTIES = {
"console_type": {
"description": "Console type",
"enum": ["telnet", "none"],
"default": "telnet"
"default": "none"
},
}
@@ -98,6 +98,8 @@ THE SOFTWARE.
@angular/material/table
@angular/material/tabs
@angular/material/toolbar
@angular/material/tooltip
@@ -0,0 +1,428 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="filter-capture.svg"
inkscape:version="0.91 r13725"
sodipodi:version="0.32"
id="svg11300"
height="48px"
width="48px"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs3">
<linearGradient
id="linearGradient2846">
<stop
id="stop2848"
offset="0.0000000"
style="stop-color:#8a8a8a;stop-opacity:1.0000000;" />
<stop
id="stop2850"
offset="1.0000000"
style="stop-color:#484848;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient2366">
<stop
id="stop2368"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ffffff;stop-opacity:0.21904762;"
offset="0.50000000"
id="stop2374" />
<stop
id="stop2370"
offset="1.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4487">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop4489" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop4491" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4477">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4479" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4481" />
</linearGradient>
<linearGradient
id="linearGradient4467">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop4469" />
<stop
style="stop-color:#ffffff;stop-opacity:0.24761905;"
offset="1.0000000"
id="stop4471" />
</linearGradient>
<linearGradient
id="linearGradient4454">
<stop
style="stop-color:#729fcf;stop-opacity:0.20784314;"
offset="0.0000000"
id="stop4456" />
<stop
style="stop-color:#729fcf;stop-opacity:0.67619050;"
offset="1.0000000"
id="stop4458" />
</linearGradient>
<linearGradient
id="linearGradient4440">
<stop
style="stop-color:#7d7d7d;stop-opacity:1;"
offset="0"
id="stop4442" />
<stop
id="stop4448"
offset="0.50000000"
style="stop-color:#b1b1b1;stop-opacity:1.0000000;" />
<stop
style="stop-color:#686868;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop4444" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4440"
id="linearGradient4446"
x1="30.656250"
y1="34.000000"
x2="33.218750"
y2="31.062500"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.334593,0.000000,0.000000,1.291292,-6.973842,-7.460658)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4454"
id="radialGradient4460"
cx="18.240929"
cy="21.817987"
fx="18.240929"
fy="21.817987"
r="8.3085051"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4467"
id="radialGradient4473"
cx="15.414371"
cy="13.078408"
fx="15.414371"
fy="13.078408"
r="6.6562500"
gradientTransform="matrix(2.592963,-7.746900e-24,-5.714443e-24,2.252104,-25.05975,-18.94100)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4487"
id="radialGradient4493"
cx="24.130018"
cy="37.967922"
fx="24.130018"
fy="37.967922"
r="16.528622"
gradientTransform="matrix(0.47747795,0,0,0.17126529,6.9831225,31.643536)"
gradientUnits="userSpaceOnUse" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="25.743469"
x2="17.500893"
y1="13.602121"
x1="18.292673"
id="linearGradient2372"
xlink:href="#linearGradient2366"
inkscape:collect="always" />
<radialGradient
r="16.528622"
fy="37.967922"
fx="24.130018"
cy="37.967922"
cx="24.130018"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.237968,-2.471981e-16,28.93278)"
gradientUnits="userSpaceOnUse"
id="radialGradient2842"
xlink:href="#linearGradient4477"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="30.557772"
x2="31.335964"
y1="26.580296"
x1="27.366341"
id="linearGradient2852"
xlink:href="#linearGradient2846"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
stroke="#3465a4"
inkscape:window-y="48"
inkscape:window-x="130"
inkscape:window-height="1752"
inkscape:window-width="3070"
inkscape:showpageshadow="false"
inkscape:document-units="px"
inkscape:grid-bbox="true"
showgrid="false"
inkscape:current-layer="g1772"
inkscape:cy="37.212656"
inkscape:cx="23.821561"
inkscape:zoom="11.313708"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="0.25490196"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
fill="#729fcf"
inkscape:window-maximized="1" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>http://jimmac.musichall.cz</dc:source>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="Layer 1"
id="layer1">
<g
id="g1772">
<path
sodipodi:type="arc"
style="opacity:0.17112298;color:#000000;fill:url(#radialGradient2842);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
id="path4475"
sodipodi:cx="24.130018"
sodipodi:cy="37.967922"
sodipodi:rx="16.528622"
sodipodi:ry="3.9332814"
d="M 40.658640 37.967922 A 16.528622 3.9332814 0 1 1 7.6013966,37.967922 A 16.528622 3.9332814 0 1 1 40.658640 37.967922 z"
transform="matrix(1.446431,0.000000,0.000000,1.519990,-10.97453,-17.75168)" />
<path
sodipodi:nodetypes="csscccscccscczzzz"
id="path2844"
d="M 18.627569,3.1435548 C 10.488439,3.1435548 3.8827682,9.7492259 3.8827682,17.888356 C 3.8827682,26.027486 10.488439,32.633158 18.627569,32.633158 C 22.107124,32.633158 25.178570,31.248765 27.701292,29.230511 C 27.495915,30.237392 27.623257,31.265879 28.457436,31.990436 L 39.421520,41.517846 C 40.654936,42.589175 42.508982,42.448806 43.580310,41.215389 C 44.651638,39.981971 44.511269,38.127927 43.277853,37.056599 L 32.313769,27.529188 C 31.642242,26.945909 30.820891,26.773219 30.007531,26.886466 C 31.994231,24.374044 33.372370,21.337663 33.372370,17.888356 C 33.372370,9.7492259 26.766699,3.1435548 18.627569,3.1435548 z M 18.551954,4.3697381 C 26.191413,4.3697381 31.843729,9.1586886 31.843729,17.661513 C 31.843729,26.336626 26.027039,30.953288 18.551954,30.953288 C 11.249005,30.953288 5.2601806,25.475196 5.2601806,17.661513 C 5.2601806,9.6774061 11.084819,4.3697380 18.551954,4.3697381 z "
style="opacity:1.0000000;color:#000000;fill:#dcdcdc;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2852);stroke-width:2.0000010;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;" />
<path
style="opacity:1.0000000;color:#000000;fill:#dcdcdc;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000004;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
d="M 18.602905,3.0803551 C 10.437465,3.0803551 3.8104408,9.7073791 3.8104408,17.872819 C 3.8104408,26.038259 10.437465,32.665283 18.602905,32.665283 C 22.093708,32.665283 25.175082,31.276416 27.705960,29.251638 C 27.499919,30.261774 27.627672,31.293585 28.464547,32.020484 L 39.464073,41.578691 C 40.701476,42.653483 42.561515,42.512661 43.636306,41.275256 C 44.711097,40.037852 44.570274,38.177814 43.332871,37.103023 L 32.333346,27.544815 C 31.659648,26.959651 30.835642,26.786402 30.019653,26.900016 C 32.012775,24.379472 33.395369,21.333276 33.395369,17.872819 C 33.395369,9.7073791 26.768345,3.0803551 18.602905,3.0803551 z M 18.527046,6.2664243 C 24.808154,6.2664245 29.905864,11.364135 29.905864,17.645243 C 29.905864,23.926351 24.808154,29.024061 18.527046,29.024061 C 12.245938,29.024061 7.1482276,23.926351 7.1482276,17.645243 C 7.1482278,11.364135 12.245938,6.2664243 18.527046,6.2664243 z "
id="path4430" />
<path
style="opacity:1.0000000;color:#000000;fill:url(#linearGradient4446);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
d="M 39.507004,41.577690 C 39.028332,39.304503 40.904334,36.766268 43.091057,36.789315 C 43.091057,36.789315 32.330690,27.531204 32.330690,27.531204 C 29.385899,27.474498 28.061188,29.803820 28.553876,32.131126 L 39.507004,41.577690 z "
id="path4438"
sodipodi:nodetypes="ccccc" />
<path
sodipodi:type="arc"
style="opacity:1.0000000;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2372);stroke-width:0.80273360;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
id="path4450"
sodipodi:cx="17.500893"
sodipodi:cy="18.920233"
sodipodi:rx="11.048544"
sodipodi:ry="11.048544"
d="M 28.549437 18.920233 A 11.048544 11.048544 0 1 1 6.4523487,18.920233 A 11.048544 11.048544 0 1 1 28.549437 18.920233 z"
transform="matrix(1.245743,0.000000,0.000000,1.245743,-3.425346,-6.177033)" />
<ellipse
id="path4485"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4493);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
cx="18.504675"
cy="38.146122"
rx="7.8920522"
ry="2.8307779" />
<rect
style="opacity:0.43315509;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000311;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
id="rect4495"
width="19.048439"
height="4.4404783"
x="40.373337"
y="0.14086054"
rx="2.1366608"
ry="1.8879365"
transform="matrix(0.752986,0.658037,-0.648902,0.760872,0.000000,0.000000)" />
<path
sodipodi:type="arc"
style="color:#000000;fill:url(#radialGradient4460);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#3063a3;stroke-width:0.71499395;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10.000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;"
id="path4452"
sodipodi:cx="17.589281"
sodipodi:cy="18.478292"
sodipodi:rx="8.3085051"
sodipodi:ry="8.3085051"
d="M 25.897786 18.478292 A 8.3085051 8.3085051 0 1 1 9.2807760,18.478292 A 8.3085051 8.3085051 0 1 1 25.897786 18.478292 z"
transform="matrix(1.398614,0.000000,0.000000,1.398614,-6.224338,-8.298958)" />
<path
style="opacity:0.83422458;color:#000000;fill:url(#radialGradient4473);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
d="M 18.156915,7.3966938 C 12.949325,7.3966938 8.7323681,11.613651 8.7323681,16.821241 C 8.7323681,18.325216 9.1526753,19.709014 9.7795400,20.971144 C 11.031920,21.432757 12.362297,21.746827 13.774307,21.746827 C 19.945262,21.746827 24.873589,16.885190 25.254413,10.809698 C 23.523449,8.7641668 21.044374,7.3966938 18.156915,7.3966938 z "
id="path4462" />
<g
transform="matrix(0.02264973,0,0,0.02609408,48.046283,48.655279)"
id="g6-3"
style="opacity:0.4;fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1">
<g
id="g8-6"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1">
<path
inkscape:connector-curvature="0"
d="m -1627.0838,-595.53083 c 10.4,11.3 16.1,26 16.1,41.3 l 0,449.7 c 0,27.099997 32.7,40.799997 52,21.799997 l 125.5,-143.799997 c 16.8,-20.1 26,-30.1 26,-50.1 l 0,-277.4 c 0,-15.3 5.8,-30 16.1,-41.3 l 360,-390.6 c 27,-29.29997 6.2,-76.79997 -33.7,-76.79997 l -888.3,0 c -39.9,-0.1 -60.7,47.3 -33.7,76.69997 l 360,390.5 z"
id="path10-7"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:82.35282898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g12-5"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g14-3"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g16-5"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g18-6"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g20-2"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g22-9"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g24-1"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g26-2"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g28-7"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g30-0"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g32-9"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g34-3"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g36-6"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g38-0"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g40-6"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
</g>
<g
transform="matrix(0.0233822,0,0,0.02642586,47.842749,48.274221)"
id="g6"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<g
id="g8"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<path
inkscape:connector-curvature="0"
d="m -1627.0838,-595.53083 c 10.4,11.3 16.1,26 16.1,41.3 l 0,449.7 c 0,27.099997 32.7,40.799997 52,21.799997 l 125.5,-143.799997 c 16.8,-20.1 26,-30.1 26,-50.1 l 0,-277.4 c 0,-15.3 5.8,-30 16.1,-41.3 l 360,-390.6 c 27,-29.29997 6.2,-76.79997 -33.7,-76.79997 l -888.3,0 c -39.9,-0.1 -60.7,47.3 -33.7,76.69997 l 360,390.5 z"
id="path10"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g12"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g14"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g16"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g18"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g20"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g22"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g24"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g26"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g28"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g30"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g32"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g34"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g36"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g38"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
id="g40"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978302;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

@@ -0,0 +1,708 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="filter.svg"
inkscape:version="0.91 r13725"
sodipodi:version="0.32"
id="svg11300"
height="48px"
width="48px"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs3">
<linearGradient
id="linearGradient2846">
<stop
id="stop2848"
offset="0.0000000"
style="stop-color:#8a8a8a;stop-opacity:1.0000000;" />
<stop
id="stop2850"
offset="1.0000000"
style="stop-color:#484848;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient2366">
<stop
id="stop2368"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ffffff;stop-opacity:0.21904762;"
offset="0.50000000"
id="stop2374" />
<stop
id="stop2370"
offset="1.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient4467">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop4469" />
<stop
style="stop-color:#ffffff;stop-opacity:0.24761905;"
offset="1.0000000"
id="stop4471" />
</linearGradient>
<linearGradient
id="linearGradient4454">
<stop
style="stop-color:#729fcf;stop-opacity:0.20784314;"
offset="0.0000000"
id="stop4456" />
<stop
style="stop-color:#729fcf;stop-opacity:0.67619050;"
offset="1.0000000"
id="stop4458" />
</linearGradient>
<linearGradient
id="linearGradient4440">
<stop
style="stop-color:#7d7d7d;stop-opacity:1;"
offset="0"
id="stop4442" />
<stop
id="stop4448"
offset="0.50000000"
style="stop-color:#b1b1b1;stop-opacity:1.0000000;" />
<stop
style="stop-color:#686868;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop4444" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1.5770403,0,0,1.4373405,-85.325285,-112.88055)"
y2="78.206215"
x2="71.53405"
y1="124.11652"
x1="71.288956"
gradientUnits="userSpaceOnUse"
id="linearGradient2306"
xlink:href="#linearGradient5075"
inkscape:collect="always" />
<linearGradient
id="linearGradient3340">
<stop
id="stop3342"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3344"
offset="1"
style="stop-color:#ffffff;stop-opacity:0.62886596;" />
</linearGradient>
<linearGradient
id="linearGradient5075">
<stop
id="stop5077"
offset="0"
style="stop-color:#adb0a8;stop-opacity:1;" />
<stop
id="stop5079"
offset="1"
style="stop-color:#464744;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient2584">
<stop
id="stop2586"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop2588"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2684">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2686" />
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="1"
id="stop2688" />
</linearGradient>
<linearGradient
y2="52.510574"
x2="14"
y1="15.291994"
x1="15.089521"
gradientTransform="translate(-4e-4,-9.426e-2)"
gradientUnits="userSpaceOnUse"
id="linearGradient2864"
xlink:href="#linearGradient3081"
inkscape:collect="always" />
<linearGradient
y2="93.204849"
x2="169"
y1="110.33805"
x1="169"
gradientTransform="matrix(1,0,0,1.004384,-145.0004,-71.4625)"
gradientUnits="userSpaceOnUse"
id="linearGradient2862"
xlink:href="#linearGradient2697"
inkscape:collect="always" />
<radialGradient
r="11"
fy="100.20107"
fx="169.77171"
cy="100.20107"
cx="169.77171"
gradientTransform="matrix(3.562309e-6,-1.07205,1.992104,-1.250658e-6,-175.6121,212.6949)"
gradientUnits="userSpaceOnUse"
id="radialGradient2860"
xlink:href="#linearGradient2679"
inkscape:collect="always" />
<linearGradient
y2="105.49083"
x2="174.74524"
y1="84.263489"
x1="174.83363"
gradientTransform="matrix(1.103262,0,0,1.054917,-163.1228,-76.31138)"
gradientUnits="userSpaceOnUse"
id="linearGradient2858"
xlink:href="#linearGradient2817"
inkscape:collect="always" />
<radialGradient
r="11"
fy="100.20107"
fx="169.77171"
cy="100.20107"
cx="169.77171"
gradientTransform="matrix(3.562309e-6,-1.07205,1.992104,-1.250658e-6,-175.6121,186.6949)"
gradientUnits="userSpaceOnUse"
id="radialGradient2831"
xlink:href="#linearGradient2679"
inkscape:collect="always" />
<linearGradient
y2="52.510574"
x2="14"
y1="15.291994"
x1="15.089521"
gradientTransform="translate(-4e-4,-26.09426)"
gradientUnits="userSpaceOnUse"
id="linearGradient2825"
xlink:href="#linearGradient3081"
inkscape:collect="always" />
<linearGradient
y2="105.49083"
x2="174.74524"
y1="84.263489"
x1="174.83363"
gradientTransform="matrix(1.103262,0,0,1.054917,-163.1228,-76.31138)"
gradientUnits="userSpaceOnUse"
id="linearGradient2823"
xlink:href="#linearGradient2817"
inkscape:collect="always" />
<radialGradient
r="11"
fy="100.20107"
fx="169.77171"
cy="100.20107"
cx="169.77171"
gradientTransform="matrix(3.562309e-6,-1.07205,1.992104,-1.250658e-6,-175.6121,212.6949)"
gradientUnits="userSpaceOnUse"
id="radialGradient2809"
xlink:href="#linearGradient2679"
inkscape:collect="always" />
<linearGradient
y2="93.204849"
x2="169"
y1="110.33805"
x1="169"
gradientTransform="translate(-145.0004,-97.0943)"
gradientUnits="userSpaceOnUse"
id="linearGradient2806"
xlink:href="#linearGradient2697"
inkscape:collect="always" />
<linearGradient
y2="93.204849"
x2="169"
y1="110.33805"
x1="169"
gradientTransform="matrix(1,0,0,1.004384,-145.0004,-71.4625)"
gradientUnits="userSpaceOnUse"
id="linearGradient2803"
xlink:href="#linearGradient2697"
inkscape:collect="always" />
<linearGradient
y2="52.510574"
x2="14"
y1="15.291994"
x1="15.089521"
gradientTransform="translate(-4e-4,-9.426e-2)"
gradientUnits="userSpaceOnUse"
id="linearGradient2800"
xlink:href="#linearGradient3081"
inkscape:collect="always" />
<linearGradient
y2="52.510574"
x2="14"
y1="15.291994"
x1="15.089521"
gradientTransform="translate(133,70.99999)"
gradientUnits="userSpaceOnUse"
id="linearGradient2797"
xlink:href="#linearGradient3081"
inkscape:collect="always" />
<linearGradient
y2="93.204849"
x2="169"
y1="110.33805"
x1="169"
gradientTransform="translate(-12,0)"
gradientUnits="userSpaceOnUse"
id="linearGradient2795"
xlink:href="#linearGradient2697"
inkscape:collect="always" />
<linearGradient
y2="93.204849"
x2="169"
y1="110.33805"
x1="169"
gradientTransform="translate(-12,0)"
gradientUnits="userSpaceOnUse"
id="linearGradient2793"
xlink:href="#linearGradient2697"
inkscape:collect="always" />
<radialGradient
r="11"
fy="100.20107"
fx="169.77171"
cy="100.20107"
cx="169.77171"
gradientTransform="matrix(3.562309e-6,-1.07205,1.992104,-1.250658e-6,-42.61165,283.7891)"
gradientUnits="userSpaceOnUse"
id="radialGradient2791"
xlink:href="#linearGradient2679"
inkscape:collect="always" />
<linearGradient
y2="52.510574"
x2="14"
y1="15.291994"
x1="15.089521"
gradientTransform="translate(133,70.99999)"
gradientUnits="userSpaceOnUse"
id="linearGradient2753"
xlink:href="#linearGradient3081"
inkscape:collect="always" />
<linearGradient
y2="93.204849"
x2="169"
y1="110.33805"
x1="169"
gradientTransform="translate(-12,0)"
gradientUnits="userSpaceOnUse"
id="linearGradient2751"
xlink:href="#linearGradient2697"
inkscape:collect="always" />
<radialGradient
r="11"
fy="100.20107"
fx="169.77171"
cy="100.20107"
cx="169.77171"
gradientTransform="matrix(3.562309e-6,-1.07205,1.992104,-1.250658e-6,-42.61165,283.7891)"
gradientUnits="userSpaceOnUse"
id="radialGradient2749"
xlink:href="#linearGradient2679"
inkscape:collect="always" />
<radialGradient
r="15.644737"
fy="36.421127"
fx="24.837126"
cy="36.421127"
cx="24.837126"
gradientTransform="matrix(1,0,0,0.536723,-1.44832e-12,16.87306)"
gradientUnits="userSpaceOnUse"
id="radialGradient2747"
xlink:href="#linearGradient8662"
inkscape:collect="always" />
<radialGradient
r="15.644737"
fy="36.421127"
fx="24.837126"
cy="36.421127"
cx="24.837126"
gradientTransform="matrix(1,0,0,0.536723,4.579205e-13,16.87306)"
gradientUnits="userSpaceOnUse"
id="radialGradient2745"
xlink:href="#linearGradient8662"
inkscape:collect="always" />
<linearGradient
y2="52.510574"
x2="14"
y1="15.291994"
x1="15.089521"
gradientTransform="translate(133,70.99999)"
gradientUnits="userSpaceOnUse"
id="linearGradient2733"
xlink:href="#linearGradient3081"
inkscape:collect="always" />
<linearGradient
y2="93.204849"
x2="169"
y1="110.33805"
x1="169"
gradientTransform="translate(-12,0)"
gradientUnits="userSpaceOnUse"
id="linearGradient2731"
xlink:href="#linearGradient2697"
inkscape:collect="always" />
<radialGradient
r="11"
fy="100.20107"
fx="169.77171"
cy="100.20107"
cx="169.77171"
gradientTransform="matrix(3.562309e-6,-1.07205,1.992104,-1.250658e-6,-42.61165,283.7891)"
gradientUnits="userSpaceOnUse"
id="radialGradient2729"
xlink:href="#linearGradient2679"
inkscape:collect="always" />
<radialGradient
r="15.644737"
fy="36.421127"
fx="24.837126"
cy="36.421127"
cx="24.837126"
gradientTransform="matrix(1,0,0,0.536723,-1.432388e-12,16.87306)"
gradientUnits="userSpaceOnUse"
id="radialGradient2727"
xlink:href="#linearGradient8662"
inkscape:collect="always" />
<radialGradient
r="15.644737"
fy="36.421127"
fx="24.837126"
cy="36.421127"
cx="24.837126"
gradientTransform="matrix(1,0,0,0.536723,4.526469e-13,16.87306)"
gradientUnits="userSpaceOnUse"
id="radialGradient2725"
xlink:href="#linearGradient8662"
inkscape:collect="always" />
<radialGradient
r="15.644737"
fy="36.421127"
fx="24.837126"
cy="36.421127"
cx="24.837126"
gradientTransform="matrix(1,0,0,0.536723,-1.416456e-12,16.87306)"
gradientUnits="userSpaceOnUse"
id="radialGradient2139"
xlink:href="#linearGradient8662"
inkscape:collect="always" />
<radialGradient
r="15.644737"
fy="36.421127"
fx="24.837126"
cy="36.421127"
cx="24.837126"
gradientTransform="matrix(1,0,0,0.536723,4.473733e-13,16.87306)"
gradientUnits="userSpaceOnUse"
id="radialGradient2137"
xlink:href="#linearGradient8662"
inkscape:collect="always" />
<linearGradient
y2="52.510574"
x2="14"
y1="15.291994"
x1="15.089521"
gradientTransform="translate(133,70.99999)"
gradientUnits="userSpaceOnUse"
id="linearGradient2124"
xlink:href="#linearGradient3081"
inkscape:collect="always" />
<linearGradient
y2="93.204849"
x2="169"
y1="110.33805"
x1="169"
gradientTransform="translate(-12,0)"
gradientUnits="userSpaceOnUse"
id="linearGradient2122"
xlink:href="#linearGradient2697"
inkscape:collect="always" />
<radialGradient
r="11"
fy="100.20107"
fx="169.77171"
cy="100.20107"
cx="169.77171"
gradientTransform="matrix(3.562309e-6,-1.07205,1.992104,-1.250658e-6,-42.61165,283.7891)"
gradientUnits="userSpaceOnUse"
id="radialGradient2112"
xlink:href="#linearGradient2679"
inkscape:collect="always" />
<linearGradient
id="linearGradient8662"
inkscape:collect="always">
<stop
id="stop8664"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop8666"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3081"
inkscape:collect="always">
<stop
id="stop3083"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3085"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2679">
<stop
style="stop-color:#f7f7f7;stop-opacity:1"
offset="0"
id="stop2681" />
<stop
style="stop-color:#ccd0c7;stop-opacity:1"
offset="1"
id="stop2683" />
</linearGradient>
<linearGradient
id="linearGradient2697">
<stop
style="stop-color:#babdb6"
offset="0"
id="stop2699" />
<stop
style="stop-color:#555753"
offset="1"
id="stop2701" />
</linearGradient>
<linearGradient
id="linearGradient2584-8">
<stop
id="stop2586-4"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop2588-8"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2817">
<stop
id="stop2819"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
<stop
id="stop2821"
offset="1"
style="stop-color:#ffffff;stop-opacity:0.48453608;" />
</linearGradient>
</defs>
<sodipodi:namedview
stroke="#3465a4"
inkscape:window-y="48"
inkscape:window-x="130"
inkscape:window-height="1752"
inkscape:window-width="3070"
inkscape:showpageshadow="false"
inkscape:document-units="px"
inkscape:grid-bbox="true"
showgrid="false"
inkscape:current-layer="layer1"
inkscape:cy="24.580209"
inkscape:cx="-23.904288"
inkscape:zoom="11.313708"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="0.25490196"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
fill="#729fcf"
inkscape:window-maximized="1" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>http://jimmac.musichall.cz</dc:source>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="Layer 1"
id="layer1">
<g
transform="matrix(0.04112758,0,0,0.04208992,87.449849,49.200049)"
id="g6-3"
style="opacity:0.4;fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1">
<g
id="g8-6"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1">
<path
inkscape:connector-curvature="0"
d="m -1627.0838,-595.53083 c 10.4,11.3 16.1,26 16.1,41.3 l 0,449.7 c 0,27.099997 32.7,40.799997 52,21.799997 l 125.5,-143.799997 c 16.8,-20.1 26,-30.1 26,-50.1 l 0,-277.4 c 0,-15.3 5.8,-30 16.1,-41.3 l 360,-390.6 c 27,-29.29997 6.2,-76.79997 -33.7,-76.79997 l -888.3,0 c -39.9,-0.1 -60.7,47.3 -33.7,76.69997 l 360,390.5 z"
id="path10-7"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:82.35282898;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g12-5"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g14-3"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g16-5"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g18-6"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g20-2"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g22-9"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g24-1"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g26-2"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g28-7"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g30-0"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g32-9"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g34-3"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g36-6"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g38-0"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
<g
id="g40-6"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1" />
</g>
<g
transform="matrix(0.04245758,0,0,0.04262509,87.080268,48.585402)"
id="g6"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none">
<g
id="g8"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none">
<path
inkscape:connector-curvature="0"
d="m -1627.0838,-595.53083 c 10.4,11.3 16.1,26 16.1,41.3 l 0,449.7 c 0,27.099997 32.7,40.799997 52,21.799997 l 125.5,-143.799997 c 16.8,-20.1 26,-30.1 26,-50.1 l 0,-277.4 c 0,-15.3 5.8,-30 16.1,-41.3 l 360,-390.6 c 27,-29.29997 6.2,-76.79997 -33.7,-76.79997 l -888.3,0 c -39.9,-0.1 -60.7,47.3 -33.7,76.69997 l 360,390.5 z"
id="path10"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g12"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g14"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g16"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g18"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g20"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g22"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g24"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g26"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g28"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g30"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g32"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g34"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g36"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g38"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
<g
id="g40"
style="fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:70.51978539;stroke-miterlimit:4;stroke-dasharray:none" />
</g>
<g
inkscape:r_cy="true"
inkscape:r_cx="true"
style="display:inline"
inkscape:label="Layer 1"
id="layer1-4"
transform="matrix(0.52129778,0,0,0.55541254,0.16640648,22.45761)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

@@ -0,0 +1,312 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="system-search.svg"
sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/actions"
inkscape:version="0.43+devel"
sodipodi:version="0.32"
id="svg11300"
height="48px"
width="48px"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs3">
<linearGradient
id="linearGradient2846">
<stop
id="stop2848"
offset="0.0000000"
style="stop-color:#8a8a8a;stop-opacity:1.0000000;" />
<stop
id="stop2850"
offset="1.0000000"
style="stop-color:#484848;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient2366">
<stop
id="stop2368"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ffffff;stop-opacity:0.21904762;"
offset="0.50000000"
id="stop2374" />
<stop
id="stop2370"
offset="1.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4487">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop4489" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop4491" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4477">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4479" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4481" />
</linearGradient>
<linearGradient
id="linearGradient4467">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop4469" />
<stop
style="stop-color:#ffffff;stop-opacity:0.24761905;"
offset="1.0000000"
id="stop4471" />
</linearGradient>
<linearGradient
id="linearGradient4454">
<stop
style="stop-color:#729fcf;stop-opacity:0.20784314;"
offset="0.0000000"
id="stop4456" />
<stop
style="stop-color:#729fcf;stop-opacity:0.67619050;"
offset="1.0000000"
id="stop4458" />
</linearGradient>
<linearGradient
id="linearGradient4440">
<stop
style="stop-color:#7d7d7d;stop-opacity:1;"
offset="0"
id="stop4442" />
<stop
id="stop4448"
offset="0.50000000"
style="stop-color:#b1b1b1;stop-opacity:1.0000000;" />
<stop
style="stop-color:#686868;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop4444" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4440"
id="linearGradient4446"
x1="30.656250"
y1="34.000000"
x2="33.218750"
y2="31.062500"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.334593,0.000000,0.000000,1.291292,-6.973842,-7.460658)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4454"
id="radialGradient4460"
cx="18.240929"
cy="21.817987"
fx="18.240929"
fy="21.817987"
r="8.3085051"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4467"
id="radialGradient4473"
cx="15.414371"
cy="13.078408"
fx="15.414371"
fy="13.078408"
r="6.6562500"
gradientTransform="matrix(2.592963,-7.746900e-24,-5.714443e-24,2.252104,-25.05975,-18.94100)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4487"
id="radialGradient4493"
cx="24.130018"
cy="37.967922"
fx="24.130018"
fy="37.967922"
r="16.528622"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.237968,3.152859e-15,28.93278)"
gradientUnits="userSpaceOnUse" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="25.743469"
x2="17.500893"
y1="13.602121"
x1="18.292673"
id="linearGradient2372"
xlink:href="#linearGradient2366"
inkscape:collect="always" />
<radialGradient
r="16.528622"
fy="37.967922"
fx="24.130018"
cy="37.967922"
cx="24.130018"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.237968,-2.471981e-16,28.93278)"
gradientUnits="userSpaceOnUse"
id="radialGradient2842"
xlink:href="#linearGradient4477"
inkscape:collect="always" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="30.557772"
x2="31.335964"
y1="26.580296"
x1="27.366341"
id="linearGradient2852"
xlink:href="#linearGradient2846"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
stroke="#3465a4"
inkscape:window-y="187"
inkscape:window-x="239"
inkscape:window-height="754"
inkscape:window-width="691"
inkscape:showpageshadow="false"
inkscape:document-units="px"
inkscape:grid-bbox="true"
showgrid="false"
inkscape:current-layer="layer1"
inkscape:cy="23.070520"
inkscape:cx="23.821561"
inkscape:zoom="11.313708"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="0.25490196"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
fill="#729fcf" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>http://jimmac.musichall.cz</dc:source>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="Layer 1"
id="layer1">
<g
id="g1772">
<path
sodipodi:type="arc"
style="opacity:0.17112298;color:#000000;fill:url(#radialGradient2842);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
id="path4475"
sodipodi:cx="24.130018"
sodipodi:cy="37.967922"
sodipodi:rx="16.528622"
sodipodi:ry="3.9332814"
d="M 40.658640 37.967922 A 16.528622 3.9332814 0 1 1 7.6013966,37.967922 A 16.528622 3.9332814 0 1 1 40.658640 37.967922 z"
transform="matrix(1.446431,0.000000,0.000000,1.519990,-10.97453,-17.75168)" />
<path
sodipodi:nodetypes="csscccscccscczzzz"
id="path2844"
d="M 18.627569,3.1435548 C 10.488439,3.1435548 3.8827682,9.7492259 3.8827682,17.888356 C 3.8827682,26.027486 10.488439,32.633158 18.627569,32.633158 C 22.107124,32.633158 25.178570,31.248765 27.701292,29.230511 C 27.495915,30.237392 27.623257,31.265879 28.457436,31.990436 L 39.421520,41.517846 C 40.654936,42.589175 42.508982,42.448806 43.580310,41.215389 C 44.651638,39.981971 44.511269,38.127927 43.277853,37.056599 L 32.313769,27.529188 C 31.642242,26.945909 30.820891,26.773219 30.007531,26.886466 C 31.994231,24.374044 33.372370,21.337663 33.372370,17.888356 C 33.372370,9.7492259 26.766699,3.1435548 18.627569,3.1435548 z M 18.551954,4.3697381 C 26.191413,4.3697381 31.843729,9.1586886 31.843729,17.661513 C 31.843729,26.336626 26.027039,30.953288 18.551954,30.953288 C 11.249005,30.953288 5.2601806,25.475196 5.2601806,17.661513 C 5.2601806,9.6774061 11.084819,4.3697380 18.551954,4.3697381 z "
style="opacity:1.0000000;color:#000000;fill:#dcdcdc;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2852);stroke-width:2.0000010;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;" />
<path
style="opacity:1.0000000;color:#000000;fill:#dcdcdc;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000004;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
d="M 18.602905,3.0803551 C 10.437465,3.0803551 3.8104408,9.7073791 3.8104408,17.872819 C 3.8104408,26.038259 10.437465,32.665283 18.602905,32.665283 C 22.093708,32.665283 25.175082,31.276416 27.705960,29.251638 C 27.499919,30.261774 27.627672,31.293585 28.464547,32.020484 L 39.464073,41.578691 C 40.701476,42.653483 42.561515,42.512661 43.636306,41.275256 C 44.711097,40.037852 44.570274,38.177814 43.332871,37.103023 L 32.333346,27.544815 C 31.659648,26.959651 30.835642,26.786402 30.019653,26.900016 C 32.012775,24.379472 33.395369,21.333276 33.395369,17.872819 C 33.395369,9.7073791 26.768345,3.0803551 18.602905,3.0803551 z M 18.527046,6.2664243 C 24.808154,6.2664245 29.905864,11.364135 29.905864,17.645243 C 29.905864,23.926351 24.808154,29.024061 18.527046,29.024061 C 12.245938,29.024061 7.1482276,23.926351 7.1482276,17.645243 C 7.1482278,11.364135 12.245938,6.2664243 18.527046,6.2664243 z "
id="path4430" />
<path
style="opacity:1.0000000;color:#000000;fill:url(#linearGradient4446);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
d="M 39.507004,41.577690 C 39.028332,39.304503 40.904334,36.766268 43.091057,36.789315 C 43.091057,36.789315 32.330690,27.531204 32.330690,27.531204 C 29.385899,27.474498 28.061188,29.803820 28.553876,32.131126 L 39.507004,41.577690 z "
id="path4438"
sodipodi:nodetypes="ccccc" />
<path
sodipodi:type="arc"
style="opacity:1.0000000;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2372);stroke-width:0.80273360;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
id="path4450"
sodipodi:cx="17.500893"
sodipodi:cy="18.920233"
sodipodi:rx="11.048544"
sodipodi:ry="11.048544"
d="M 28.549437 18.920233 A 11.048544 11.048544 0 1 1 6.4523487,18.920233 A 11.048544 11.048544 0 1 1 28.549437 18.920233 z"
transform="matrix(1.245743,0.000000,0.000000,1.245743,-3.425346,-6.177033)" />
<path
transform="matrix(0.497764,0.000000,0.000000,0.609621,8.973526,15.61929)"
d="M 40.658640 37.967922 A 16.528622 3.9332814 0 1 1 7.6013966,37.967922 A 16.528622 3.9332814 0 1 1 40.658640 37.967922 z"
sodipodi:ry="3.9332814"
sodipodi:rx="16.528622"
sodipodi:cy="37.967922"
sodipodi:cx="24.130018"
id="path4485"
style="opacity:1.0000000;color:#000000;fill:url(#radialGradient4493);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
sodipodi:type="arc" />
<rect
style="opacity:0.43315509;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000311;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
id="rect4495"
width="19.048439"
height="4.4404783"
x="40.373337"
y="0.14086054"
rx="2.1366608"
ry="1.8879365"
transform="matrix(0.752986,0.658037,-0.648902,0.760872,0.000000,0.000000)" />
<path
sodipodi:type="arc"
style="color:#000000;fill:url(#radialGradient4460);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#3063a3;stroke-width:0.71499395;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10.000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;"
id="path4452"
sodipodi:cx="17.589281"
sodipodi:cy="18.478292"
sodipodi:rx="8.3085051"
sodipodi:ry="8.3085051"
d="M 25.897786 18.478292 A 8.3085051 8.3085051 0 1 1 9.2807760,18.478292 A 8.3085051 8.3085051 0 1 1 25.897786 18.478292 z"
transform="matrix(1.398614,0.000000,0.000000,1.398614,-6.224338,-8.298958)" />
<path
style="opacity:0.83422458;color:#000000;fill:url(#radialGradient4473);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible;"
d="M 18.156915,7.3966938 C 12.949325,7.3966938 8.7323681,11.613651 8.7323681,16.821241 C 8.7323681,18.325216 9.1526753,19.709014 9.7795400,20.971144 C 11.031920,21.432757 12.362297,21.746827 13.774307,21.746827 C 19.945262,21.746827 24.873589,16.885190 25.254413,10.809698 C 23.523449,8.7641668 21.044374,7.3966938 18.156915,7.3966938 z "
id="path4462" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

+2 -2
View File
@@ -32,9 +32,9 @@
}
})();
</script>
<link rel="stylesheet" href="styles.0a22cbd56b6e27a9938f.css"></head>
<link rel="stylesheet" href="styles.7a07d35efbc0270fb065.css"></head>
<!-- <body class="mat-app-background" oncontextmenu="return false;"> -->
<body class="mat-app-background" oncontextmenu="return false;">
<app-root></app-root>
<script type="text/javascript" src="runtime.a5dd35324ddfd942bef1.js"></script><script type="text/javascript" src="polyfills.f4c5bd079c16579a94cf.js"></script><script type="text/javascript" src="main.4afddaebdefb25000188.js"></script></body>
<script type="text/javascript" src="runtime.26209474bfa8dc87a77c.js"></script><script type="text/javascript" src="polyfills.9cf8d114d9c6322da643.js"></script><script type="text/javascript" src="main.d7e59714b81de1a1004d.js"></script></body>
</html>
@@ -1 +0,0 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{"+/L5":function(n,e,t){var l=t("t1UP").isCustomProperty,o=t("vd7W").TYPE,r=o.Identifier,i=o.Colon,a=o.ExclamationMark,u=o.Solidus,s=o.Asterisk,d=o.DollarSign,c=o.HyphenMinus,p=o.Semicolon,f=o.PlusSign,h=o.NumberSign;function m(n){return this.Raw(n,a,p,!1,!0)}function v(n){return this.Raw(n,a,p,!1,!1)}function g(){var n=this.scanner.currentToken,e=this.Value();return"Raw"!==e.type&&!1===this.scanner.eof&&this.scanner.tokenType!==p&&this.scanner.tokenType!==a&&!1===this.scanner.isBalanceEdge(n)&&this.scanner.error(),e}n.exports={name:"Declaration",structure:{important:[Boolean,String],property:String,value:["Value","Raw"]},parse:function(){var n,e=this.scanner.tokenStart,t=this.scanner.currentToken,o=(function(){var n=this.scanner.tokenStart,e=0;switch(this.scanner.tokenType){case s:case d:case f:case h:e=1;break;case u:e=this.scanner.lookupType(1)===u?2:1}return this.scanner.lookupType(e)===c&&e++,e&&this.scanner.skip(e),this.scanner.eat(r),this.scanner.substrToCursor(n)}).call(this),b=l(o),y=b?this.parseCustomProperty:this.parseValue,_=b?v:m,w=!1;return this.scanner.skipSC(),this.scanner.eat(i),b||this.scanner.skipSC(),n=y?this.parseWithFallback(g,_):_.call(this,this.scanner.currentToken),this.scanner.tokenType===a&&(w=function(n){n.eat(a),n.skipSC();var e=n.consume(r);return"important"===e||e}(this.scanner),this.scanner.skipSC()),!1===this.scanner.eof&&this.scanner.tokenType!==p&&!1===this.scanner.isBalanceEdge(t)&&this.scanner.error(),{type:"Declaration",loc:this.getLocation(e,this.scanner.tokenStart),important:w,property:o,value:n}},generate:function(n){this.chunk(n.property),this.chunk(":"),this.node(n.value),n.important&&this.chunk(!0===n.important?"!important":"!"+n.important)},walkContext:"declaration"}},"+Kd2":function(n,e,t){var l=t("vd7W").TYPE,o=l.Identifier,r=l.Comma,i=l.Semicolon,a=l.HyphenMinus,u=l.ExclamationMark;n.exports=function(){var n=this.createList();this.scanner.skipSC();var e=this.scanner.tokenStart;return this.scanner.eat(a),this.scanner.source.charCodeAt(this.scanner.tokenStart)!==a&&this.scanner.error("HyphenMinus is expected"),this.scanner.eat(o),n.push({type:"Identifier",loc:this.getLocation(e,this.scanner.tokenStart),name:this.scanner.substrToCursor(e)}),this.scanner.skipSC(),this.scanner.tokenType===r&&(n.push(this.Operator()),n.push(this.parseCustomProperty?this.Value(null):this.Raw(this.scanner.currentToken,u,i,!1,!1))),n}},"+gEr":function(n,e,t){"use strict";t.d(e,"a",function(){return i}),t.d(e,"b",function(){return a});var l=t("mrSG"),o=t("MGBS"),r=t("zotm"),i={leading:!0,trailing:!1};function a(n,e){return void 0===e&&(e=i),function(t){return t.lift(new u(n,e.leading,e.trailing))}}var u=function(){function n(n,e,t){this.durationSelector=n,this.leading=e,this.trailing=t}return n.prototype.call=function(n,e){return e.subscribe(new s(n,this.durationSelector,this.leading,this.trailing))},n}(),s=function(n){function e(e,t,l,o){var r=n.call(this,e)||this;return r.destination=e,r.durationSelector=t,r._leading=l,r._trailing=o,r._hasValue=!1,r}return l.__extends(e,n),e.prototype._next=function(n){this._hasValue=!0,this._sendValue=n,this._throttled||(this._leading?this.send():this.throttle(n))},e.prototype.send=function(){var n=this._sendValue;this._hasValue&&(this.destination.next(n),this.throttle(n)),this._hasValue=!1,this._sendValue=null},e.prototype.throttle=function(n){var e=this.tryDurationSelector(n);e&&this.add(this._throttled=Object(r.a)(this,e))},e.prototype.tryDurationSelector=function(n){try{return this.durationSelector(n)}catch(e){return this.destination.error(e),null}},e.prototype.throttlingDone=function(){var n=this._throttled,e=this._trailing;n&&n.unsubscribe(),this._throttled=null,e&&this.send()},e.prototype.notifyNext=function(n,e,t,l,o){this.throttlingDone()},e.prototype.notifyComplete=function(){this.throttlingDone()},e}(o.a)},"+ryv":function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var l=t("CcnG");e.HotkeyOptions=new l.InjectionToken("HotkeyOptions")},"+tJ4":function(n,e,t){"use strict";t.d(e,"a",function(){return l});var l=function(n){return function(e){for(var t=0,l=n.length;t<l&&!e.closed;t++)e.next(n[t]);e.closed||e.complete()}}},"+umK":function(n,e,t){"use strict";function l(){}t.d(e,"a",function(){return l})},"/+5V":function(n,e){function t(n){function e(n){return null!==n&&("Type"===n.type||"Property"===n.type||"Keyword"===n.type)}var t=null;return null!==this.matched&&function l(o){if(Array.isArray(o.match)){for(var r=0;r<o.match.length;r++)if(l(o.match[r]))return e(o.syntax)&&t.unshift(o.syntax),!0}else if(o.node===n)return t=e(o.syntax)?[o.syntax]:[],!0;return!1}(this.matched),t}function l(n,e,l){var o=t.call(n,e);return null!==o&&o.some(l)}n.exports={getTrace:t,isType:function(n,e){return l(this,n,function(n){return"Type"===n.type&&n.name===e})},isProperty:function(n,e){return l(this,n,function(n){return"Property"===n.type&&n.name===e})},isKeyword:function(n){returLine truncated
@@ -0,0 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{"+/L5":function(n,e,t){var l=t("t1UP").isCustomProperty,o=t("vd7W").TYPE,r=o.Identifier,i=o.Colon,a=o.ExclamationMark,u=o.Solidus,s=o.Asterisk,d=o.DollarSign,c=o.HyphenMinus,p=o.Semicolon,f=o.PlusSign,h=o.NumberSign;function m(n){return this.Raw(n,a,p,!1,!0)}function v(n){return this.Raw(n,a,p,!1,!1)}function g(){var n=this.scanner.currentToken,e=this.Value();return"Raw"!==e.type&&!1===this.scanner.eof&&this.scanner.tokenType!==p&&this.scanner.tokenType!==a&&!1===this.scanner.isBalanceEdge(n)&&this.scanner.error(),e}n.exports={name:"Declaration",structure:{important:[Boolean,String],property:String,value:["Value","Raw"]},parse:function(){var n,e=this.scanner.tokenStart,t=this.scanner.currentToken,o=(function(){var n=this.scanner.tokenStart,e=0;switch(this.scanner.tokenType){case s:case d:case f:case h:e=1;break;case u:e=this.scanner.lookupType(1)===u?2:1}return this.scanner.lookupType(e)===c&&e++,e&&this.scanner.skip(e),this.scanner.eat(r),this.scanner.substrToCursor(n)}).call(this),b=l(o),y=b?this.parseCustomProperty:this.parseValue,_=b?v:m,w=!1;return this.scanner.skipSC(),this.scanner.eat(i),b||this.scanner.skipSC(),n=y?this.parseWithFallback(g,_):_.call(this,this.scanner.currentToken),this.scanner.tokenType===a&&(w=function(n){n.eat(a),n.skipSC();var e=n.consume(r);return"important"===e||e}(this.scanner),this.scanner.skipSC()),!1===this.scanner.eof&&this.scanner.tokenType!==p&&!1===this.scanner.isBalanceEdge(t)&&this.scanner.error(),{type:"Declaration",loc:this.getLocation(e,this.scanner.tokenStart),important:w,property:o,value:n}},generate:function(n){this.chunk(n.property),this.chunk(":"),this.node(n.value),n.important&&this.chunk(!0===n.important?"!important":"!"+n.important)},walkContext:"declaration"}},"+Kd2":function(n,e,t){var l=t("vd7W").TYPE,o=l.Identifier,r=l.Comma,i=l.Semicolon,a=l.HyphenMinus,u=l.ExclamationMark;n.exports=function(){var n=this.createList();this.scanner.skipSC();var e=this.scanner.tokenStart;return this.scanner.eat(a),this.scanner.source.charCodeAt(this.scanner.tokenStart)!==a&&this.scanner.error("HyphenMinus is expected"),this.scanner.eat(o),n.push({type:"Identifier",loc:this.getLocation(e,this.scanner.tokenStart),name:this.scanner.substrToCursor(e)}),this.scanner.skipSC(),this.scanner.tokenType===r&&(n.push(this.Operator()),n.push(this.parseCustomProperty?this.Value(null):this.Raw(this.scanner.currentToken,u,i,!1,!1))),n}},"+gEr":function(n,e,t){"use strict";t.d(e,"a",function(){return i}),t.d(e,"b",function(){return a});var l=t("mrSG"),o=t("MGBS"),r=t("zotm"),i={leading:!0,trailing:!1};function a(n,e){return void 0===e&&(e=i),function(t){return t.lift(new u(n,e.leading,e.trailing))}}var u=function(){function n(n,e,t){this.durationSelector=n,this.leading=e,this.trailing=t}return n.prototype.call=function(n,e){return e.subscribe(new s(n,this.durationSelector,this.leading,this.trailing))},n}(),s=function(n){function e(e,t,l,o){var r=n.call(this,e)||this;return r.destination=e,r.durationSelector=t,r._leading=l,r._trailing=o,r._hasValue=!1,r}return l.__extends(e,n),e.prototype._next=function(n){this._hasValue=!0,this._sendValue=n,this._throttled||(this._leading?this.send():this.throttle(n))},e.prototype.send=function(){var n=this._sendValue;this._hasValue&&(this.destination.next(n),this.throttle(n)),this._hasValue=!1,this._sendValue=null},e.prototype.throttle=function(n){var e=this.tryDurationSelector(n);e&&this.add(this._throttled=Object(r.a)(this,e))},e.prototype.tryDurationSelector=function(n){try{return this.durationSelector(n)}catch(e){return this.destination.error(e),null}},e.prototype.throttlingDone=function(){var n=this._throttled,e=this._trailing;n&&n.unsubscribe(),this._throttled=null,e&&this.send()},e.prototype.notifyNext=function(n,e,t,l,o){this.throttlingDone()},e.prototype.notifyComplete=function(){this.throttlingDone()},e}(o.a)},"+ryv":function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var l=t("CcnG");e.HotkeyOptions=new l.InjectionToken("HotkeyOptions")},"+tJ4":function(n,e,t){"use strict";t.d(e,"a",function(){return l});var l=function(n){return function(e){for(var t=0,l=n.length;t<l&&!e.closed;t++)e.next(n[t]);e.complete()}}},"+umK":function(n,e,t){"use strict";function l(){}t.d(e,"a",function(){return l})},"/+5V":function(n,e){function t(n){function e(n){return null!==n&&("Type"===n.type||"Property"===n.type||"Keyword"===n.type)}var t=null;return null!==this.matched&&function l(o){if(Array.isArray(o.match)){for(var r=0;r<o.match.length;r++)if(l(o.match[r]))return e(o.syntax)&&t.unshift(o.syntax),!0}else if(o.node===n)return t=e(o.syntax)?[o.syntax]:[],!0;return!1}(this.matched),t}function l(n,e,l){var o=t.call(n,e);return null!==o&&o.some(l)}n.exports={getTrace:t,isType:function(n,e){return l(this,n,function(n){return"Type"===n.type&&n.name===e})},isProperty:function(n,e){return l(this,n,function(n){return"Property"===n.type&&n.name===e})},isKeyword:function(n){return l(this,nLine truncated
@@ -0,0 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{"0TWp":function(e,t,n){!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=!0===e.__zone_symbol__forceDuplicateZoneCheck;if(e.Zone){if(o||"function"!=typeof e.Zone.__symbol__)throw new Error("Zone already loaded.");return e.Zone}var a,i=function(){function t(e,t){this._parent=e,this._name=t?t.name||"unnamed":"<root>",this._properties=t&&t.properties||{},this._zoneDelegate=new c(this,this._parent&&this._parent._zoneDelegate,t)}return t.assertZonePatched=function(){if(e.Promise!==P.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 Z.zone},enumerable:!0,configurable:!0}),Object.defineProperty(t,"currentTask",{get:function(){return j},enumerable:!0,configurable:!0}),t.__load_patch=function(a,i){if(P.hasOwnProperty(a)){if(o)throw Error("Already loaded patch: "+a)}else if(!e["__Zone_disable_"+a]){var s="Zone:"+a;n(s),P[a]=i(e,t,D),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){Z={parent:Z,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,r)}finally{Z=Z.parent}},t.prototype.runGuarded=function(e,t,n,r){void 0===t&&(t=null),Z={parent:Z,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{Z=Z.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||y).name+"; Execution: "+this.name+")");if(e.state!==_||e.type!==O&&e.type!==S){var r=e.state!=k;r&&e._transitionTo(k,b),e.runCount++;var o=j;j=e,Z={parent:Z,zone:this};try{e.type==S&&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!==_&&e.state!==w&&(e.type==O||e.data&&e.data.isPeriodic?r&&e._transitionTo(b,k):(e.runCount=0,this._updateTaskCount(e,-1),r&&e._transitionTo(_,k,_))),Z=Z.parent,j=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(m,_);var n=[];e._zoneDelegates=n,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(r){throw e._transitionTo(w,m,_),this._zoneDelegate.handleError(this,r),r}return e._zoneDelegates===n&&this._updateTaskCount(e,1),e.state==m&&e._transitionTo(b,m),e},t.prototype.scheduleMicroTask=function(e,t,n,r){return this.scheduleTask(new l(E,e,t,n,r,void 0))},t.prototype.scheduleMacroTask=function(e,t,n,r,o){return this.scheduleTask(new l(S,e,t,n,r,o))},t.prototype.scheduleEventTask=function(e,t,n,r,o){return this.scheduleTask(new l(O,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||y).name+"; Execution: "+this.name+")");e._transitionTo(T,b,k);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(w,T),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(_,T),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.__symbol__=I,t}(),s={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)}},c=function(){function e(e,t,n){this._taskCounts={microTask:0,macroTask:0,eventTask:0},this.zone=e,this._parentDelegate=t,this._forkZS=n&&(n&&n.onFork?n:t._fLine truncated
@@ -1 +0,0 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{"0TWp":function(e,t,n){!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=!0===e.__zone_symbol__forceDuplicateZoneCheck;if(e.Zone){if(o||"function"!=typeof e.Zone.__symbol__)throw new Error("Zone already loaded.");return e.Zone}var a,i=function(){function t(e,t){this._parent=e,this._name=t?t.name||"unnamed":"<root>",this._properties=t&&t.properties||{},this._zoneDelegate=new c(this,this._parent&&this._parent._zoneDelegate,t)}return t.assertZonePatched=function(){if(e.Promise!==Z.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 O.zone},enumerable:!0,configurable:!0}),Object.defineProperty(t,"currentTask",{get:function(){return P},enumerable:!0,configurable:!0}),t.__load_patch=function(a,i){if(Z.hasOwnProperty(a)){if(o)throw Error("Already loaded patch: "+a)}else if(!e["__Zone_disable_"+a]){var s="Zone:"+a;n(s),Z[a]=i(e,t,z),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){O={parent:O,zone:this};try{return this._zoneDelegate.invoke(this,e,t,n,r)}finally{O=O.parent}},t.prototype.runGuarded=function(e,t,n,r){void 0===t&&(t=null),O={parent:O,zone:this};try{try{return this._zoneDelegate.invoke(this,e,t,n,r)}catch(o){if(this._zoneDelegate.handleError(this,o))throw o}}finally{O=O.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||y).name+"; Execution: "+this.name+")");if(e.state!==m||e.type!==D&&e.type!==S){var r=e.state!=b;r&&e._transitionTo(b,_),e.runCount++;var o=P;P=e,O={parent:O,zone:this};try{e.type==S&&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!==m&&e.state!==w&&(e.type==D||e.data&&e.data.isPeriodic?r&&e._transitionTo(_,b):(e.runCount=0,this._updateTaskCount(e,-1),r&&e._transitionTo(m,b,m))),O=O.parent,P=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,m);var n=[];e._zoneDelegates=n,e._zone=this;try{e=this._zoneDelegate.scheduleTask(this,e)}catch(r){throw e._transitionTo(w,k,m),this._zoneDelegate.handleError(this,r),r}return e._zoneDelegates===n&&this._updateTaskCount(e,1),e.state==k&&e._transitionTo(_,k),e},t.prototype.scheduleMicroTask=function(e,t,n,r){return this.scheduleTask(new l(E,e,t,n,r,void 0))},t.prototype.scheduleMacroTask=function(e,t,n,r,o){return this.scheduleTask(new l(S,e,t,n,r,o))},t.prototype.scheduleEventTask=function(e,t,n,r,o){return this.scheduleTask(new l(D,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||y).name+"; Execution: "+this.name+")");e._transitionTo(T,_,b);try{this._zoneDelegate.cancelTask(this,e)}catch(t){throw e._transitionTo(w,T),this._zoneDelegate.handleError(this,t),t}return this._updateTaskCount(e,-1),e._transitionTo(m,T),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.__symbol__=I,t}(),s={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)}},c=function(){function e(e,t,n){this._taskCounts={microTask:0,macroTask:0,eventTask:0},this.zone=e,this._parentDelegate=t,this._forkZS=n&&(n&&n.onFork?n:t._fLine truncated
@@ -1,6 +0,0 @@
/*!
* Bootstrap v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 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{outline:0!important}h1,h2,h3,h4,h5,h6{margin-top:0}dl,ol,p,ul{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{margin-bottom:1rem;font-style:normal;line-height:inherit}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote,figure{margin:0 0 1rem}b,strong{font-weight:bolder}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([tabindex]),a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}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}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}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:dotted 1px;outline:-webkit-focus-ring-color auto 5px}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}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}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}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;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{box-sizing:content-box;height:0;overflow:visible;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:Line truncated
@@ -0,0 +1,6 @@
/*!
* Bootstrap v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 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{outline:0!important}h1,h2,h3,h4,h5,h6{margin-top:0}dl,ol,p,ul{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{margin-bottom:1rem;font-style:normal;line-height:inherit}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote,figure{margin:0 0 1rem}b,strong{font-weight:bolder}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([tabindex]),a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}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}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}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:dotted 1px;outline:-webkit-focus-ring-color auto 5px}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}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}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}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;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{box-sizing:content-box;height:0;overflow:visible;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:Line truncated
+7 -4
View File
@@ -195,8 +195,8 @@ class UnstoppableEventLoop(EventLoop):
class ShellConnection(TelnetConnection):
def __init__(self, reader, writer, shell, loop):
super(ShellConnection, self).__init__(reader, writer)
def __init__(self, reader, writer, shell, window_size_changed_callback, loop):
super(ShellConnection, self).__init__(reader, writer, window_size_changed_callback)
self._shell = shell
self._loop = loop
self._cli = None
@@ -234,9 +234,12 @@ class ShellConnection(TelnetConnection):
async def disconnected(self):
pass
@asyncio.coroutine
def window_size_changed(self, columns, rows):
self._size = Size(rows=rows, columns=columns)
self._cb.terminal_size_changed()
if self._window_size_changed_callback:
yield from self._window_size_changed_callback(columns, rows)
async def feed(self, data):
data = data.decode()
@@ -285,8 +288,8 @@ def create_telnet_shell(shell, loop=None):
if loop is None:
loop = asyncio.get_event_loop()
def factory(reader, writer):
return ShellConnection(reader, writer, shell, loop)
def factory(reader, writer, window_size_changed_callback):
return ShellConnection(reader, writer, shell, window_size_changed_callback, loop)
return AsyncioTelnetServer(binary=True, echo=True, naws=True, connection_factory=factory)
+1 -1
View File
@@ -23,7 +23,7 @@
# or negative for a release candidate or beta (after the base version
# number has been incremented)
__version__ = "2.2.0a4"
__version__ = "2.2.0b2"
__version_info__ = (2, 2, 0, -99)
# If it's a git checkout try to add the commit
+35 -2
View File
@@ -21,6 +21,11 @@
import logging
import sys
import os
import shutil
import gzip
from logging.handlers import RotatingFileHandler
class ColouredFormatter(logging.Formatter):
@@ -108,9 +113,37 @@ class LogFilter:
return 1
def init_logger(level, logfile=None, quiet=False):
class CompressedRotatingFileHandler(RotatingFileHandler):
"""
Custom rotating file handler with compression support.
"""
def doRollover(self):
if self.stream:
self.stream.close()
if self.backupCount > 0:
for i in range(self.backupCount - 1, 0, -1):
sfn = "%s.%d.gz" % (self.baseFilename, i)
dfn = "%s.%d.gz" % (self.baseFilename, i + 1)
if os.path.exists(sfn):
if os.path.exists(dfn):
os.remove(dfn)
os.rename(sfn, dfn)
dfn = self.baseFilename + ".1.gz"
if os.path.exists(dfn):
os.remove(dfn)
with open(self.baseFilename, 'rb') as f_in, gzip.open(dfn, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
self.mode = 'w'
self.stream = self._open()
def init_logger(level, logfile=None, max_bytes=10000000, backup_count=10, compression=True, quiet=False):
if logfile and len(logfile) > 0:
stream_handler = logging.FileHandler(logfile)
if compression:
stream_handler = CompressedRotatingFileHandler(logfile, maxBytes=max_bytes, backupCount=backup_count)
else:
stream_handler = RotatingFileHandler(logfile, maxBytes=max_bytes, backupCount=backup_count)
stream_handler.formatter = ColouredFormatter("{asctime} {levelname} {filename}:{lineno} {message}", "%Y-%m-%d %H:%M:%S", "{")
elif sys.platform.startswith("win"):
stream_handler = WinStreamHandler(sys.stdout)
+135
View File
@@ -62,6 +62,7 @@ def test_json(vm, project):
'console_http_port': 80,
'console_http_path': '/',
'extra_hosts': None,
'extra_volumes': [],
'aux': vm.aux,
'start_command': vm.start_command,
'environment': vm.environment,
@@ -458,6 +459,140 @@ def test_create_with_user(loop, project, manager):
})
assert vm._cid == "e90e34656806"
def test_create_with_extra_volumes_invalid_format_1(loop, project, manager):
response = {
"Id": "e90e34656806",
"Warnings": []
}
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["vol1"])
with pytest.raises(DockerError):
loop.run_until_complete(asyncio.ensure_future(vm.create()))
def test_create_with_extra_volumes_invalid_format_2(loop, project, manager):
response = {
"Id": "e90e34656806",
"Warnings": []
}
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol1", ""])
with pytest.raises(DockerError):
loop.run_until_complete(asyncio.ensure_future(vm.create()))
def test_create_with_extra_volumes_invalid_format_3(loop, project, manager):
response = {
"Id": "e90e34656806",
"Warnings": []
}
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol1/.."])
with pytest.raises(DockerError):
loop.run_until_complete(asyncio.ensure_future(vm.create()))
def test_create_with_extra_volumes_duplicate_1_image(loop, project, manager):
response = {
"Id": "e90e34656806",
"Warnings": [],
"Config" : {
"Volumes" : {
"/vol/1": None
},
},
}
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol/1"])
with pytest.raises(DockerError):
loop.run_until_complete(asyncio.ensure_future(vm.create()))
def test_create_with_extra_volumes_duplicate_2_user(loop, project, manager):
response = {
"Id": "e90e34656806",
"Warnings": [],
}
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol/1", "/vol/1"])
with pytest.raises(DockerError):
loop.run_until_complete(asyncio.ensure_future(vm.create()))
def test_create_with_extra_volumes_duplicate_3_subdir(loop, project, manager):
response = {
"Id": "e90e34656806",
"Warnings": [],
}
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol/1/", "/vol"])
with pytest.raises(DockerError):
loop.run_until_complete(asyncio.ensure_future(vm.create()))
def test_create_with_extra_volumes_duplicate_4_backslash(loop, project, manager):
response = {
"Id": "e90e34656806",
"Warnings": [],
}
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol//", "/vol"])
with pytest.raises(DockerError):
loop.run_until_complete(asyncio.ensure_future(vm.create()))
def test_create_with_extra_volumes(loop, project, manager):
response = {
"Id": "e90e34656806",
"Warnings": [],
"Config" : {
"Volumes" : {
"/vol/1": None
},
},
}
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest", extra_volumes=["/vol/2"])
loop.run_until_complete(asyncio.ensure_future(vm.create()))
mock.assert_called_with("POST", "containers/create", data={
"Tty": True,
"OpenStdin": True,
"StdinOnce": False,
"HostConfig":
{
"CapAdd": ["ALL"],
"Binds": [
"{}:/gns3:ro".format(get_resource("compute/docker/resources")),
"{}:/gns3volumes/etc/network:rw".format(os.path.join(vm.working_dir, "etc", "network")),
"{}:/gns3volumes/vol/1".format(os.path.join(vm.working_dir, "vol", "1")),
"{}:/gns3volumes/vol/2".format(os.path.join(vm.working_dir, "vol", "2")),
],
"Privileged": True
},
"Volumes": {},
"NetworkDisabled": True,
"Name": "test",
"Hostname": "test",
"Image": "ubuntu:latest",
"Env": [
"container=docker",
"GNS3_MAX_ETHERNET=eth0",
"GNS3_VOLUMES=/etc/network:/vol/1:/vol/2"
],
"Entrypoint": ["/gns3/init.sh"],
"Cmd": ["/bin/sh"]
})
assert vm._cid == "e90e34656806"
def test_get_container_state(loop, vm):
response = {
"State": {
+1 -1
View File
@@ -97,7 +97,7 @@ def test_vm_create(loop, tmpdir, project, manager, fake_qemu_binary):
f.write('hello')
vm = QemuVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, qemu_path=fake_qemu_binary)
vm._hda_disk_image = fake_img
vm._hda_disk_image = fake_img
loop.run_until_complete(asyncio.ensure_future(vm.create()))
+2 -2
View File
@@ -405,8 +405,8 @@ def test_start_iou(compute, project, async_run, controller):
compute.post = AsyncioMagicMock()
# Without licence configured it should raise an error
with pytest.raises(aiohttp.web.HTTPConflict):
async_run(node.start())
#with pytest.raises(aiohttp.web.HTTPConflict):
# async_run(node.start())
controller._iou_license_settings = {"license_check": True, "iourc_content": "aa"}
async_run(node.start())
+19
View File
@@ -257,6 +257,25 @@ def test_delete_node(async_run, controller):
project.emit_notification.assert_any_call("node.deleted", node.__json__())
def test_delete_locked_node(async_run, controller):
"""
For a local server we send the project path
"""
compute = MagicMock()
project = Project(controller=controller, name="Test")
project.emit_notification = MagicMock()
response = MagicMock()
response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response)
node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"}))
assert node.id in project._nodes
node.locked = True
with pytest.raises(aiohttp.web_exceptions.HTTPConflict):
async_run(project.delete_node(node.id))
def test_delete_node_delete_link(async_run, controller):
"""
Delete a node delete all the node connected
@@ -811,7 +811,7 @@ def test_ethernet_switch_template_create(http_controller):
"builtin": False,
"category": "switch",
"compute_id": "local",
"console_type": "telnet",
"console_type": "none",
"default_name_format": "Switch{0}",
"name": "Ethernet switch template",
"ports_mapping": [{"ethertype": "",
+5 -2
View File
@@ -28,6 +28,7 @@ import shutil
from gns3server.controller.topology import load_topology, GNS3_FILE_FORMAT_REVISION
from gns3server.version import __version__
topologies_directory = os.path.join(os.path.dirname(os.path.realpath(__file__)), "topologies")
@@ -104,7 +105,7 @@ def compare_dict(path, source, reference):
"""
assert isinstance(source, dict), "Source is not a dict in {}".format(path)
for key in source:
assert key in reference, "Unexcepted {} in {} it should be {}".format(key, source, reference)
assert key in reference, "Unexpected {} in {} it should be {}".format(key, source, reference)
for key in sorted(reference.keys()):
val = reference[key]
assert key in source, "{} is missing in {}".format(key, source)
@@ -113,10 +114,12 @@ def compare_dict(path, source, reference):
pass
elif val == "ANYUUID" and len(source[key]) == 36:
pass
# We test that the revision number has been bumpd to last version. This avoid modifying all the tests
# We test that the revision number has been bumped to last version. This avoid modifying all the tests
# at each new revision bump.
elif key == "revision":
assert source[key] == GNS3_FILE_FORMAT_REVISION
elif key == "version":
assert source[key] == __version__
else:
assert val == source[key], "Wrong value for {}: \n{}\nit should be\n{}".format(key, source[key], val)
elif isinstance(val, dict):