mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-15 19:35:14 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6b345508b | ||
|
|
5d2e539193 | ||
|
|
eb0e26b55f | ||
|
|
17d657c919 | ||
|
|
0aa9ab53d1 | ||
|
|
4021a13651 | ||
|
|
341e2e2e3a | ||
|
|
f8ecd61a98 | ||
|
|
c620d0be84 | ||
|
|
abfbadecd6 | ||
|
|
4a6202fa84 | ||
|
|
f89d645b56 | ||
|
|
b7dd8b5176 | ||
|
|
00cf66fb0f | ||
|
|
8d4e73d23c | ||
|
|
4e712280b3 | ||
|
|
4d57a3befa | ||
|
|
38b72079b2 | ||
|
|
814526ba26 | ||
|
|
f5dc635baa | ||
|
|
902de3dd47 | ||
|
|
ad9b6f42bf | ||
|
|
3560cda06c | ||
|
|
a3d1e865a8 | ||
|
|
089d25c79d | ||
|
|
59ce105a50 | ||
|
|
aeb33024ca | ||
|
|
c593785c6d |
No files matched your search
@@ -30,3 +30,4 @@ env:
|
||||
- PYTHON_VERSION=3.4
|
||||
- PYTHON_VERSION=3.5
|
||||
- PYTHON_VERSION=3.6
|
||||
- PYTHON_VERSION=3.7
|
||||
@@ -1,5 +1,27 @@
|
||||
# Change Log
|
||||
|
||||
## 2.1.10 15/09/2018
|
||||
|
||||
* Include locale information and GNS3 VM version in crash reports.
|
||||
* Fix small errors like unhandled exceptions etc.
|
||||
* Import encodings.idna to avoid LookupError when standard library is in a zip file.
|
||||
* Catch exceptions in various locations to fix small issues reported by Sentry.
|
||||
* Check if serial pipe can be opened for VMware and VirtualBox VMs.
|
||||
* Improve the invalid port format detection. Fixes https://github.com/GNS3/gns3-gui/issues/2580
|
||||
* Update aiohttp verion requirement in order to support Python 3.7. Fixes https://github.com/GNS3/gns3-gui/issues/2566
|
||||
* Update setup.py and fix minor issues.
|
||||
* Catch asyncio.CancelledError when shutting down the server.
|
||||
* Report GNS3 VM errors to the GUI server summary. Ref #1359.
|
||||
* Replace vboxnet0 (if it does not exist) by the first available vboxnet interface on Windows. Fixes https://github.com/GNS3/gns3-vm/issues/102
|
||||
* Check if the VirtualBox host-only network exists when starting a GNS3 VM running on VirtualBox. Ref https://github.com/GNS3/gns3-vm/issues/102
|
||||
* Change file timestamps if necessary because ZIP does not support timestamps before 1980. Fixes #1360.
|
||||
* Add missing coroutine decorator Ref https://github.com/GNS3/gns3-gui/issues/2566
|
||||
* Refactor asyncio locking system for Python 3.7 support. Ref https://github.com/GNS3/gns3-gui/issues/2566 Ref https://github.com/GNS3/gns3-gui/issues/2568
|
||||
* Use asyncio.ensure_future() instead of asyncio.async() with conservative approach to support Python < 3.4.4. Fixes https://github.com/GNS3/gns3-gui/issues/2566
|
||||
* Forbid controller and compute servers to be different versions. Report last compute server error to clients and display in the server summary.
|
||||
* Fix exception with short names for Dynamips interfaces. Fixes #1386.
|
||||
* Add missing Qemu boot priority values. Fixes https://github.com/GNS3/gns3-server/issues/1385
|
||||
|
||||
## 2.1.9 13/08/2018
|
||||
|
||||
* Fix some more problems with interface short names. Fixes https://github.com/GNS3/gns3-gui/issues/2562
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "cEOS",
|
||||
"category": "multilayer_switch",
|
||||
"description": "Arista cEOS\u2122 introduces the containerized packaging of EOS software and its agents for deployment in cloud infrastructure with the same proven EOS software image that runs on all Arista products. These flexible deployment options empower cloud network operators that are customizing their operating environments to provide a uniform workflow for development, testing and deployment of differentiated services.",
|
||||
"vendor_name": "Arista",
|
||||
"vendor_url": "http://www.arista.com/",
|
||||
"product_name": "cEOS",
|
||||
"registry_version": 3,
|
||||
"status": "experimental",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"usage": "Download:\nCreate a (free) Arista account and login.\nThen navigate to Support / Software Download and download the cEOS-lab image.\n\nInstallation:\nCopy the image to your GNS3VM (or other Linux) server, then run the following commands:\n\ndocker import cEOS-lab.tar.xz ceosimage:4.20.5F\necho \"rm /etc/systemd/system/getty.target.wants/getty@tty1.service\" | \\\ndocker run --name=ceos-container -e CEOS=1 -e container=docker -e EOS_PLATFORM=ceossim -e SKIP_ZEROTOUCH_BARRIER_IN_SYSDBINIT=1 -e ETBA=1 -e INTFTYPE=eth -i ceosimage:4.20.5F sh\ndocker commit --change='CMD [\"/sbin/init\"]' --change='VOLUME /mnt/flash' ceos-container ceosimage:GNS3\ndocker rm ceos-container\n\nUsage:\nThe login is admin, with no password by default",
|
||||
"symbol": ":/symbols/multilayer_switch.svg",
|
||||
"docker": {
|
||||
"adapters": 8,
|
||||
"image": "ceosimage:GNS3",
|
||||
"console_type": "telnet"
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,15 @@
|
||||
"kvm": "allow"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "BSDRP-1.90-full-amd64-serial.img",
|
||||
"version": "1.90",
|
||||
"md5sum": "78b7182bed93888d17d18a67d5fec3a7",
|
||||
"filesize": 1000000000,
|
||||
"download_url": "https://bsdrp.net/downloads",
|
||||
"direct_download_url": "https://sourceforge.net/projects/bsdrp/files/BSD_Router_Project/1.90/amd64/BSDRP-1.90-full-amd64-serial.img.xz/download",
|
||||
"compression": "xz"
|
||||
},
|
||||
{
|
||||
"filename": "BSDRP-1.80-full-amd64-serial.img",
|
||||
"version": "1.80",
|
||||
@@ -39,6 +48,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "1.90",
|
||||
"images": {
|
||||
"hda_disk_image": "BSDRP-1.90-full-amd64-serial.img"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "1.80",
|
||||
"images": {
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"kvm": "require"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "asav992.qcow2",
|
||||
"version": "9.9.2",
|
||||
"md5sum": "0cba453dbf70313d8d63a00700618f52",
|
||||
"filesize": 204865536,
|
||||
"download_url": "https://software.cisco.com/download/home/286119613/type/280775065/release/9.9.2"
|
||||
},
|
||||
{
|
||||
"filename": "asav983.qcow2",
|
||||
"version": "9.8.3",
|
||||
@@ -104,6 +111,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "9.9.2",
|
||||
"images": {
|
||||
"hda_disk_image": "asav992.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "9.8.3",
|
||||
"images": {
|
||||
|
||||
@@ -11,19 +11,32 @@
|
||||
"status": "experimental",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"usage": "Default username/password: admin/admin, cisco/cisco and lab/lab. There is no default configuration present.",
|
||||
"usage": "Default username/password: admin/admin, cisco/cisco and lab/lab. There is no default configuration present. Interfaces may take several minutes to be usable after appliance boot.",
|
||||
"first_port_name": "MgmtEth0/0/CPU0/0",
|
||||
"port_name_format": "GigabitEthernet0/0/0/{0}",
|
||||
"qemu": {
|
||||
"adapter_type": "e1000",
|
||||
"adapters": 4,
|
||||
"adapter_type": "virtio-net-pci",
|
||||
"adapters": 7,
|
||||
"ram": 16384,
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
"kvm": "require",
|
||||
"options": "-smp 4"
|
||||
"options": "-smp 4 -cpu host"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "xrv9k-fullk9-x-6.4.2.qcow2",
|
||||
"version": "6.4.2",
|
||||
"md5sum": "6958763192c7bb59a1b8049d377de1b4",
|
||||
"filesize": 1311703040,
|
||||
"download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.4.2"
|
||||
},
|
||||
{ "filename": "xrv9k-fullk9-x-6.4.1.qcow2",
|
||||
"version": "6.4.1",
|
||||
"md5sum": "9c56b684e307706005a503e289cb9317",
|
||||
"filesize": 1304887296,
|
||||
"download_url": "https://software.cisco.com/download/home/286288939/type/280805694/release/6.4.1"
|
||||
},
|
||||
{
|
||||
"filename": "xrv9k-fullk9-x-6.2.25.qcow2",
|
||||
"version": "6.2.25",
|
||||
@@ -47,6 +60,18 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "6.4.2",
|
||||
"images": {
|
||||
"hda_disk_image": "xrv9k-fullk9-x-6.4.2.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "6.4.1",
|
||||
"images": {
|
||||
"hda_disk_image": "xrv9k-fullk9-x-6.4.1.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "6.2.25",
|
||||
"images": {
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
"kvm": "require"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "nxosv-final.9.2.1.qcow2",
|
||||
"version": "9.2.1",
|
||||
"md5sum": "1d7fa4654602d7ffbf62544edfe71986",
|
||||
"filesize": 1330315264,
|
||||
"download_url": "https://software.cisco.com/download/home/286312239/type/282088129/release/9.2%25281%2529"
|
||||
},
|
||||
{
|
||||
"filename": "nxosv-final.7.0.3.I7.4.qcow2",
|
||||
"version": "7.0.3.I7.4",
|
||||
@@ -85,6 +92,13 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "9.2.1",
|
||||
"images": {
|
||||
"bios_image": "OVMF-20160813.fd",
|
||||
"hda_disk_image": "nxosv-final.9.2.1.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.3.I7.4",
|
||||
"images": {
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
"kvm": "require"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "cumulus-linux-3.6.2-vx-amd64.qcow2",
|
||||
"version": "3.6.2",
|
||||
"md5sum": "02b0621d68fb2e709b4bcc48748c7b6f",
|
||||
"filesize": 1150746624,
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"filename": "cumulus-linux-3.6.1-vx-amd64.qcow2",
|
||||
"version": "3.6.1",
|
||||
@@ -165,6 +173,12 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "3.6.2",
|
||||
"images": {
|
||||
"hda_disk_image": "cumulus-linux-3.6.2-vx-amd64.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3.6.1",
|
||||
"images": {
|
||||
|
||||
@@ -26,6 +26,14 @@
|
||||
"options": "-smp 2 -cpu core2duo"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "exosvm-22.5.1.7.iso",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"filename": "exosvm-22.4.1.4.iso",
|
||||
"version": "22.4.1.4",
|
||||
@@ -100,6 +108,13 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "22.5.1.7",
|
||||
"images": {
|
||||
"hda_disk_image": "empty8G.qcow2",
|
||||
"cdrom_image": "exosvm-22.5.1.7.iso"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "22.4.1.4",
|
||||
"images": {
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "VOSS VM",
|
||||
"category": "multilayer_switch",
|
||||
"description": "The VOSS VM is a software emulation of a VSP8K switch.",
|
||||
"vendor_name": "Extreme Networks",
|
||||
"vendor_url": "http://www.extremenetworks.com",
|
||||
"documentation_url": "http://www.extremenetworks.com/support/documentation",
|
||||
"product_name": "VOSS_VM",
|
||||
"registry_version": 3,
|
||||
"status": "experimental",
|
||||
"maintainer": "Extreme Networks",
|
||||
"maintainer_email": "voss@extremenetworks.com",
|
||||
"usage": "Boot up and login is rwa/rwa",
|
||||
"symbol": "ethernet_switch.svg",
|
||||
"first_port_name": "Mgmt",
|
||||
"port_name_format": "1/{port1}",
|
||||
"qemu":
|
||||
{
|
||||
"adapter_type": "e1000",
|
||||
"adapters": 9,
|
||||
"ram": 1024,
|
||||
"hda_disk_interface": "ide",
|
||||
"arch": "i386",
|
||||
"console_type": "telnet",
|
||||
"kvm": "allow",
|
||||
"options": "-nographic"
|
||||
},
|
||||
|
||||
"images":
|
||||
[
|
||||
{
|
||||
"filename": "VOSSGNS3.7.1.0.0.qcow2",
|
||||
"version": "voss_7.1.0.0",
|
||||
"md5sum": "7bb2974efe1a1ab857debd9fa894dbe7",
|
||||
"filesize": 193724416,
|
||||
"direct_download_url": "https://stackingtool.extremenetworks.com/github/VOSSGNS3.7.1.0.0.qcow2"
|
||||
},
|
||||
{
|
||||
"filename": "VOSSGNS3.7.0.0.0.img",
|
||||
"version": "voss_7.0.0.0",
|
||||
"md5sum": "65fe97461156aa88c836a90be1287649",
|
||||
"filesize": 419430400,
|
||||
"direct_download_url": "https://stackingtool.extremenetworks.com/github/VOSSGNS3.7.0.0.0.img"
|
||||
}
|
||||
],
|
||||
|
||||
"versions":
|
||||
[
|
||||
{
|
||||
"name": "7.1.0.0",
|
||||
"images":
|
||||
{
|
||||
"hda_disk_image": "VOSSGNS3.7.1.0.0.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "7.0.0.0",
|
||||
"images": {
|
||||
"hda_disk_image": "VOSSGNS3.7.0.0.0.img"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
@@ -29,6 +29,13 @@
|
||||
"options": "-smp 2 -cpu host"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "BIG-IQ-5.4.0.2.24.7467.qcow2",
|
||||
"version": "5.4.0.2",
|
||||
"md5sum": "e3e6389438ba1e1676f507658f767e95",
|
||||
"filesize": 3480748032,
|
||||
"download_url": "https://downloads.f5.com/esd/serveDownload.jsp?path=/big-iq/big-iq_cm/5.4.0/english/virtual-edition_base-plus-hf2/&sw=BIG-IQ&pro=big-iq_CM&ver=5.4.0&container=Virtual-Edition_Base-Plus-HF2&file=BIG-IQ-5.4.0.2.24.7467.qcow2.zip"
|
||||
},
|
||||
{
|
||||
"filename": "BIG-IQ-5.4.0.0.0.7437.qcow2",
|
||||
"version": "5.4.0",
|
||||
@@ -81,6 +88,13 @@
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "5.4.0.2",
|
||||
"images": {
|
||||
"hda_disk_image": "BIG-IQ-5.4.0.2.24.7467.qcow2",
|
||||
"hdb_disk_image": "empty100G.qcow2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "5.4.0",
|
||||
"images": {
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
"kvm": "require"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "kali-linux-2018.3-amd64.iso",
|
||||
"version": "2018.3",
|
||||
"md5sum": "6dc3e57177249f73492b9edb95d082d1",
|
||||
"filesize": 3188391936,
|
||||
"download_url": "https://www.kali.org/downloads/",
|
||||
"direct_download_url": "http://cdimage.kali.org/kali-2018.3/kali-linux-2018.3-amd64.iso"
|
||||
},
|
||||
{
|
||||
"filename": "kali-linux-2018.1-amd64.iso",
|
||||
"version": "2018.1",
|
||||
@@ -79,7 +87,12 @@
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "2018.8",
|
||||
"name": "2018.3",
|
||||
"images": {
|
||||
"cdrom_image": "kali-linux-2018.3-amd64.iso"
|
||||
}
|
||||
}, {
|
||||
"name": "2018.1",
|
||||
"images": {
|
||||
"cdrom_image": "kali-linux-2018.1-amd64.iso"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
"ram": 2048,
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
"boot_priority": "dc",
|
||||
"kvm": "allow",
|
||||
"process_priority": "normal"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "TacacsGUI",
|
||||
"category": "guest",
|
||||
"description": "TacacsGUI Free Access Control Server for Your Network Devices. GUI for powerful daemon. The project of Alexey Mochalin, based on tacacs daemon by Marc Huber",
|
||||
"vendor_name": "TacacsGUI",
|
||||
"vendor_url": "https://tacacsgui.com/",
|
||||
"documentation_url": "https://tacacsgui.com/documentation/",
|
||||
"product_name": "TacacsGUI",
|
||||
"product_url": "https://drive.google.com/open?id=1U8tbj14NqEyCmarayhZm54qTyjgsJm4B",
|
||||
"registry_version": 3,
|
||||
"status": "stable",
|
||||
"maintainer": "GNS3 Team",
|
||||
"maintainer_email": "developers@gns3.net",
|
||||
"usage": "Credentials: SSH ---> username: root ---> password: 1234 MySQL DB: ---> username: root --> password: tacacs Web interface: ---> username: tacgui ---> password: abc123",
|
||||
"port_name_format": "Port{port1}",
|
||||
"qemu": {
|
||||
"adapter_type": "e1000",
|
||||
"adapters": 1,
|
||||
"ram": 1024,
|
||||
"hda_disk_interface": "ide",
|
||||
"arch": "x86_64",
|
||||
"console_type": "telnet",
|
||||
"boot_priority": "c",
|
||||
"kvm": "allow"
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"filename": "tac_plus.qcow2",
|
||||
"version": "201710201114",
|
||||
"md5sum": "6b5e66590051124dae586b8640b2eb11",
|
||||
"filesize": 160301056,
|
||||
"download_url": "https://drive.google.com/open?id=1U8tbj14NqEyCmarayhZm54qTyjgsJm4B"
|
||||
}
|
||||
],
|
||||
"versions": [
|
||||
{
|
||||
"name": "201710201114",
|
||||
"images": {
|
||||
"hda_disk_image": "tac_plus.qcow2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -30,6 +30,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
from uuid import UUID, uuid4
|
||||
from gns3server.utils.interfaces import is_interface_up
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
from ..config import Config
|
||||
from ..utils.asyncio import wait_run_in_executor
|
||||
from ..utils import force_unix_path
|
||||
@@ -127,7 +128,7 @@ class BaseManager:
|
||||
|
||||
tasks = []
|
||||
for node_id in self._nodes.keys():
|
||||
tasks.append(asyncio.async(self.close_node(node_id)))
|
||||
tasks.append(asyncio_ensure_future(self.close_node(node_id)))
|
||||
|
||||
if tasks:
|
||||
done, _ = yield from asyncio.wait(tasks)
|
||||
|
||||
@@ -29,7 +29,7 @@ import re
|
||||
|
||||
from gns3server.utils.interfaces import interfaces
|
||||
from ..compute.port_manager import PortManager
|
||||
from ..utils.asyncio import wait_run_in_executor, locked_coroutine
|
||||
from ..utils.asyncio import wait_run_in_executor, locking
|
||||
from ..utils.asyncio.telnet_server import AsyncioTelnetServer
|
||||
from ..ubridge.hypervisor import Hypervisor
|
||||
from ..ubridge.ubridge_error import UbridgeError
|
||||
@@ -516,7 +516,8 @@ class BaseNode:
|
||||
except UbridgeError as e:
|
||||
raise UbridgeError("Error while sending command '{}': {}: {}".format(command, e, self._ubridge_hypervisor.read_stdout()))
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def _start_ubridge(self):
|
||||
"""
|
||||
Starts uBridge (handles connections to and from this node).
|
||||
|
||||
@@ -163,7 +163,7 @@ class Cloud(BaseNode):
|
||||
|
||||
try:
|
||||
output = yield from gns3server.utils.asyncio.subprocess_check_output("networksetup", "-listallhardwareports")
|
||||
except (FileNotFoundError, subprocess.SubprocessError) as e:
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
log.warn("Could not execute networksetup: {}".format(e))
|
||||
return False
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import asyncio
|
||||
import logging
|
||||
import aiohttp
|
||||
from gns3server.utils import parse_version
|
||||
from gns3server.utils.asyncio import locked_coroutine
|
||||
from gns3server.utils.asyncio import locking
|
||||
from gns3server.compute.base_manager import BaseManager
|
||||
from gns3server.compute.docker.docker_vm import DockerVM
|
||||
from gns3server.compute.docker.docker_error import DockerError, DockerHttp304Error, DockerHttp404Error
|
||||
@@ -182,7 +182,8 @@ class Docker(BaseManager):
|
||||
autoping=True)
|
||||
return connection
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def pull_image(self, image, progress_callback=None):
|
||||
"""
|
||||
Pull image from docker repository
|
||||
|
||||
@@ -29,6 +29,8 @@ import os
|
||||
from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer
|
||||
from gns3server.utils.asyncio.raw_command_server import AsyncioRawCommandServer
|
||||
from gns3server.utils.asyncio import wait_for_file_creation
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
from gns3server.utils.asyncio import monitor_process
|
||||
from gns3server.utils.get_resource import get_resource
|
||||
|
||||
from gns3server.ubridge.ubridge_error import UbridgeError, UbridgeNamespaceError
|
||||
@@ -226,11 +228,13 @@ class DockerVM(BaseNode):
|
||||
binds = ["{}:/gns3:ro".format(ressources)]
|
||||
|
||||
# We mount our own etc/network
|
||||
network_config = self._create_network_config()
|
||||
try:
|
||||
network_config = self._create_network_config()
|
||||
except OSError as e:
|
||||
raise DockerError("Could not create network config in the container: {}".format(e))
|
||||
binds.append("{}:/gns3volumes/etc/network:rw".format(network_config))
|
||||
|
||||
self._volumes = ["/etc/network"]
|
||||
|
||||
volumes = image_infos.get("Config", {}).get("Volumes")
|
||||
if volumes is None:
|
||||
return binds
|
||||
@@ -283,11 +287,12 @@ class DockerVM(BaseNode):
|
||||
try:
|
||||
image_infos = yield from self._get_image_information()
|
||||
except DockerHttp404Error:
|
||||
log.info("Image %s is missing pulling it from docker hub", self._image)
|
||||
log.info("Image '{}' is missing, pulling it from Docker hub...".format(self._image))
|
||||
yield from self.pull_image(self._image)
|
||||
image_infos = yield from self._get_image_information()
|
||||
if image_infos is None:
|
||||
raise DockerError("Can't get image informations, please try again.")
|
||||
|
||||
if image_infos is None:
|
||||
raise DockerError("Cannot get information for image '{}', please try again.".format(self._image))
|
||||
|
||||
params = {
|
||||
"Hostname": self._name,
|
||||
@@ -311,7 +316,10 @@ class DockerVM(BaseNode):
|
||||
if params["Entrypoint"] is None:
|
||||
params["Entrypoint"] = []
|
||||
if self._start_command:
|
||||
params["Cmd"] = shlex.split(self._start_command)
|
||||
try:
|
||||
params["Cmd"] = shlex.split(self._start_command)
|
||||
except ValueError as e:
|
||||
raise DockerError("Invalid start command '{}': {}".format(self._start_command, e))
|
||||
if len(params["Cmd"]) == 0:
|
||||
params["Cmd"] = image_infos.get("Config", {"Cmd": []})["Cmd"]
|
||||
if params["Cmd"] is None:
|
||||
@@ -353,8 +361,7 @@ class DockerVM(BaseNode):
|
||||
|
||||
result = yield from self.manager.query("POST", "containers/create", data=params)
|
||||
self._cid = result['Id']
|
||||
log.info("Docker container '{name}' [{id}] created".format(
|
||||
name=self._name, id=self._id))
|
||||
log.info("Docker container '{name}' [{id}] created".format(name=self._name, id=self._id))
|
||||
return True
|
||||
|
||||
def _format_env(self, variables, env):
|
||||
@@ -447,16 +454,19 @@ class DockerVM(BaseNode):
|
||||
@asyncio.coroutine
|
||||
def _start_aux(self):
|
||||
"""
|
||||
Start an auxilary console
|
||||
Start an auxiliary console
|
||||
"""
|
||||
|
||||
# We can not use the API because docker doesn't expose a websocket api for exec
|
||||
# https://github.com/GNS3/gns3-gui/issues/1039
|
||||
process = yield from asyncio.subprocess.create_subprocess_exec(
|
||||
"docker", "exec", "-i", self._cid, "/gns3/bin/busybox", "script", "-qfc", "while true; do TERM=vt100 /gns3/bin/busybox sh; done", "/dev/null",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.STDOUT,
|
||||
stdin=asyncio.subprocess.PIPE)
|
||||
try:
|
||||
process = yield from asyncio.subprocess.create_subprocess_exec(
|
||||
"docker", "exec", "-i", self._cid, "/gns3/bin/busybox", "script", "-qfc", "while true; do TERM=vt100 /gns3/bin/busybox sh; done", "/dev/null",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.STDOUT,
|
||||
stdin=asyncio.subprocess.PIPE)
|
||||
except OSError as e:
|
||||
raise DockerError("Could not start auxiliary console process: {}".format(e))
|
||||
server = AsyncioTelnetServer(reader=process.stdout, writer=process.stdin, binary=True, echo=True)
|
||||
try:
|
||||
self._telnet_servers.append((yield from asyncio.start_server(server.run, self._manager.port_manager.console_host, self.aux)))
|
||||
@@ -479,21 +489,25 @@ class DockerVM(BaseNode):
|
||||
for volume in self._volumes:
|
||||
log.debug("Docker container '{name}' [{image}] fix ownership on {path}".format(
|
||||
name=self._name, image=self._image, path=volume))
|
||||
process = yield from asyncio.subprocess.create_subprocess_exec(
|
||||
"docker",
|
||||
"exec",
|
||||
self._cid,
|
||||
"/gns3/bin/busybox",
|
||||
"sh",
|
||||
"-c",
|
||||
"("
|
||||
"/gns3/bin/busybox find \"{path}\" -depth -print0"
|
||||
" | /gns3/bin/busybox xargs -0 /gns3/bin/busybox stat -c '%a:%u:%g:%n' > \"{path}/.gns3_perms\""
|
||||
")"
|
||||
" && /gns3/bin/busybox chmod -R u+rX \"{path}\""
|
||||
" && /gns3/bin/busybox chown {uid}:{gid} -R \"{path}\""
|
||||
.format(uid=os.getuid(), gid=os.getgid(), path=volume),
|
||||
)
|
||||
|
||||
try:
|
||||
process = yield from asyncio.subprocess.create_subprocess_exec(
|
||||
"docker",
|
||||
"exec",
|
||||
self._cid,
|
||||
"/gns3/bin/busybox",
|
||||
"sh",
|
||||
"-c",
|
||||
"("
|
||||
"/gns3/bin/busybox find \"{path}\" -depth -print0"
|
||||
" | /gns3/bin/busybox xargs -0 /gns3/bin/busybox stat -c '%a:%u:%g:%n' > \"{path}/.gns3_perms\""
|
||||
")"
|
||||
" && /gns3/bin/busybox chmod -R u+rX \"{path}\""
|
||||
" && /gns3/bin/busybox chown {uid}:{gid} -R \"{path}\""
|
||||
.format(uid=os.getuid(), gid=os.getgid(), path=volume),
|
||||
)
|
||||
except OSError as e:
|
||||
raise DockerError("Could not fix permissions for {}: {}".format(volume, e))
|
||||
yield from process.wait()
|
||||
|
||||
@asyncio.coroutine
|
||||
@@ -504,7 +518,7 @@ class DockerVM(BaseNode):
|
||||
|
||||
self._display = self._get_free_display_port()
|
||||
if shutil.which("Xvfb") is None or shutil.which("x11vnc") is None:
|
||||
raise DockerError("Please install Xvfb and x11vnc before using the VNC support")
|
||||
raise DockerError("Please install Xvfb and x11vnc before using VNC support")
|
||||
self._xvfb_process = yield from asyncio.create_subprocess_exec("Xvfb", "-nolisten", "tcp", ":{}".format(self._display), "-screen", "0", self._console_resolution + "x16")
|
||||
# We pass a port for TCPV6 due to a crash in X11VNC if not here: https://github.com/GNS3/gns3-server/issues/569
|
||||
self._x11vnc_process = yield from asyncio.create_subprocess_exec("x11vnc", "-forever", "-nopw", "-shared", "-geometry", self._console_resolution, "-display", "WAIT:{}".format(self._display), "-rfbport", str(self.console), "-rfbportv6", str(self.console), "-noncache", "-listen", self._manager.port_manager.console_host)
|
||||
@@ -512,6 +526,29 @@ class DockerVM(BaseNode):
|
||||
x11_socket = os.path.join("/tmp/.X11-unix/", "X{}".format(self._display))
|
||||
yield from wait_for_file_creation(x11_socket)
|
||||
|
||||
#monitor_process(self._xvfb_process, self._xvfb_callback)
|
||||
#monitor_process(self._x11vnc_process, self._x11vnc_callback)
|
||||
|
||||
def _xvfb_callback(self, returncode):
|
||||
"""
|
||||
Called when the process has stopped.
|
||||
|
||||
:param returncode: Process returncode
|
||||
"""
|
||||
|
||||
if returncode != 0:
|
||||
self.project.emit("log.error", {"message": "The Xvfb process has stopped, return code: {}.".format(returncode)})
|
||||
|
||||
def _x11vnc_callback(self, returncode):
|
||||
"""
|
||||
Called when the process has stopped.
|
||||
|
||||
:param returncode: Process returncode
|
||||
"""
|
||||
|
||||
if returncode != 0:
|
||||
self.project.emit("log.error", {"message": "The x11vnc process has stopped, return code: {}.".format(returncode)})
|
||||
|
||||
@asyncio.coroutine
|
||||
def _start_http(self):
|
||||
"""
|
||||
@@ -567,7 +604,7 @@ class DockerVM(BaseNode):
|
||||
|
||||
output_stream.feed_data(self.name.encode() + b" console is now available... Press RETURN to get started.\r\n")
|
||||
|
||||
asyncio.async(self._read_console_output(self._console_websocket, output_stream))
|
||||
asyncio_ensure_future(self._read_console_output(self._console_websocket, output_stream))
|
||||
|
||||
@asyncio.coroutine
|
||||
def _read_console_output(self, ws, out):
|
||||
|
||||
@@ -36,6 +36,7 @@ log = logging.getLogger(__name__)
|
||||
from gns3server.utils.interfaces import interfaces, is_interface_up
|
||||
from gns3server.utils.asyncio import wait_run_in_executor
|
||||
from gns3server.utils import parse_version
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
from uuid import uuid4
|
||||
from ..base_manager import BaseManager
|
||||
from ..port_manager import PortManager
|
||||
@@ -172,7 +173,7 @@ class Dynamips(BaseManager):
|
||||
|
||||
tasks = []
|
||||
for device in self._devices.values():
|
||||
tasks.append(asyncio.async(device.hypervisor.stop()))
|
||||
tasks.append(asyncio_ensure_future(device.hypervisor.stop()))
|
||||
|
||||
if tasks:
|
||||
done, _ = yield from asyncio.wait(tasks)
|
||||
@@ -196,7 +197,7 @@ class Dynamips(BaseManager):
|
||||
tasks = []
|
||||
for device in self._devices.values():
|
||||
if device.project.id == project.id:
|
||||
tasks.append(asyncio.async(device.delete()))
|
||||
tasks.append(asyncio_ensure_future(device.delete()))
|
||||
|
||||
if tasks:
|
||||
done, _ = yield from asyncio.wait(tasks)
|
||||
|
||||
@@ -87,6 +87,7 @@ class EthernetSwitch(Device):
|
||||
self._mappings = {}
|
||||
self._telnet_console = None
|
||||
self._telnet_shell = None
|
||||
self._telnet_server = None
|
||||
self._console = self._manager.port_manager.get_free_tcp_port(self._project)
|
||||
if ports is None:
|
||||
# create 8 ports by default
|
||||
@@ -217,8 +218,9 @@ class EthernetSwitch(Device):
|
||||
Deletes this Ethernet switch.
|
||||
"""
|
||||
yield from self._telnet.close()
|
||||
self._telnet_server.close()
|
||||
|
||||
if self._telnet_server:
|
||||
self._telnet_server.close()
|
||||
|
||||
for nio in self._nios.values():
|
||||
if nio:
|
||||
yield from nio.close()
|
||||
|
||||
@@ -40,7 +40,7 @@ from ..nios.nio_udp import NIOUDP
|
||||
|
||||
|
||||
from gns3server.utils.file_watcher import FileWatcher
|
||||
from gns3server.utils.asyncio import wait_run_in_executor, monitor_process
|
||||
from gns3server.utils.asyncio import wait_run_in_executor, monitor_process, asyncio_ensure_future
|
||||
from gns3server.utils.images import md5sum
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ class Router(BaseNode):
|
||||
"""
|
||||
Called when the NVRAM file has changed
|
||||
"""
|
||||
asyncio.async(self.save_configs())
|
||||
asyncio_ensure_future(self.save_configs())
|
||||
|
||||
@property
|
||||
def dynamips_id(self):
|
||||
|
||||
@@ -43,7 +43,7 @@ from .utils.iou_export import nvram_export
|
||||
from gns3server.ubridge.ubridge_error import UbridgeError
|
||||
from gns3server.utils.file_watcher import FileWatcher
|
||||
from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer
|
||||
from gns3server.utils.asyncio import locked_coroutine
|
||||
from gns3server.utils.asyncio import locking
|
||||
import gns3server.utils.asyncio
|
||||
import gns3server.utils.images
|
||||
|
||||
@@ -368,7 +368,7 @@ class IOUVM(BaseNode):
|
||||
|
||||
try:
|
||||
output = yield from gns3server.utils.asyncio.subprocess_check_output("ldd", self._path)
|
||||
except (FileNotFoundError, subprocess.SubprocessError) as e:
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
log.warn("Could not determine the shared library dependencies for {}: {}".format(self._path, e))
|
||||
return
|
||||
|
||||
@@ -421,7 +421,7 @@ class IOUVM(BaseNode):
|
||||
hostid = (yield from gns3server.utils.asyncio.subprocess_check_output("hostid")).strip()
|
||||
except FileNotFoundError as e:
|
||||
raise IOUError("Could not find hostid: {}".format(e))
|
||||
except subprocess.SubprocessError as e:
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
raise IOUError("Could not execute hostid: {}".format(e))
|
||||
|
||||
try:
|
||||
@@ -550,7 +550,8 @@ class IOUVM(BaseNode):
|
||||
# configure networking support
|
||||
yield from self._networking()
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def _networking(self):
|
||||
"""
|
||||
Configures the IOL bridge in uBridge.
|
||||
|
||||
@@ -29,7 +29,7 @@ from uuid import UUID, uuid4
|
||||
from .port_manager import PortManager
|
||||
from .notification_manager import NotificationManager
|
||||
from ..config import Config
|
||||
from ..utils.asyncio import wait_run_in_executor
|
||||
from ..utils.asyncio import wait_run_in_executor, asyncio_ensure_future
|
||||
from ..utils.path import check_path_allowed, get_default_project_directory
|
||||
|
||||
import logging
|
||||
@@ -346,7 +346,7 @@ class Project:
|
||||
|
||||
tasks = []
|
||||
for node in self._nodes:
|
||||
tasks.append(asyncio.async(node.manager.close_node(node.id)))
|
||||
tasks.append(asyncio_ensure_future(node.manager.close_node(node.id)))
|
||||
|
||||
if tasks:
|
||||
done, _ = yield from asyncio.wait(tasks)
|
||||
|
||||
@@ -193,7 +193,7 @@ class Qemu(BaseManager):
|
||||
return version
|
||||
else:
|
||||
raise QemuError("Could not determine the Qemu version for {}".format(qemu_path))
|
||||
except subprocess.SubprocessError as e:
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
raise QemuError("Error while looking for the Qemu version: {}".format(e))
|
||||
|
||||
@staticmethod
|
||||
@@ -213,7 +213,7 @@ class Qemu(BaseManager):
|
||||
return version
|
||||
else:
|
||||
raise QemuError("Could not determine the Qemu-img version for {}".format(qemu_img_path))
|
||||
except subprocess.SubprocessError as e:
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
raise QemuError("Error while looking for the Qemu-img version: {}".format(e))
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -1028,7 +1028,7 @@ class QemuVM(BaseNode):
|
||||
if expect in line:
|
||||
result = line.decode("utf-8").strip()
|
||||
break
|
||||
except EOFError as e:
|
||||
except (ConnectionError, EOFError) as e:
|
||||
log.warn("Could not read from QEMU monitor: {}".format(e))
|
||||
writer.close()
|
||||
return result
|
||||
|
||||
@@ -33,7 +33,7 @@ import xml.etree.ElementTree as ET
|
||||
from gns3server.utils import parse_version
|
||||
from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer
|
||||
from gns3server.utils.asyncio.serial import asyncio_open_serial
|
||||
from gns3server.utils.asyncio import locked_coroutine
|
||||
from gns3server.utils.asyncio import locking
|
||||
from gns3server.compute.virtualbox.virtualbox_error import VirtualBoxError
|
||||
from gns3server.compute.nios.nio_udp import NIOUDP
|
||||
from gns3server.compute.adapters.ethernet_adapter import EthernetAdapter
|
||||
@@ -217,6 +217,8 @@ class VirtualBoxVM(BaseNode):
|
||||
except ET.ParseError:
|
||||
raise VirtualBoxError("Cannot modify VirtualBox linked nodes file. "
|
||||
"File {} is corrupted.".format(self._linked_vbox_file()))
|
||||
except OSError as e:
|
||||
raise VirtualBoxError("Cannot modify VirtualBox linked nodes file '{}': {}".format(self._linked_vbox_file(), e))
|
||||
|
||||
machine = tree.getroot().find("{http://www.virtualbox.org/}Machine")
|
||||
if machine is not None and machine.get("uuid") != "{" + self.id + "}":
|
||||
@@ -245,6 +247,7 @@ class VirtualBoxVM(BaseNode):
|
||||
return True
|
||||
return False
|
||||
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def start(self):
|
||||
"""
|
||||
@@ -296,7 +299,8 @@ class VirtualBoxVM(BaseNode):
|
||||
if (yield from self.check_hw_virtualization()):
|
||||
self._hw_virtualization = True
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def stop(self):
|
||||
"""
|
||||
Stops this VirtualBox VM.
|
||||
@@ -937,7 +941,12 @@ class VirtualBoxVM(BaseNode):
|
||||
"""
|
||||
Starts remote console support for this VM.
|
||||
"""
|
||||
self._remote_pipe = yield from asyncio_open_serial(self._get_pipe_name())
|
||||
|
||||
pipe_name = self._get_pipe_name()
|
||||
try:
|
||||
self._remote_pipe = yield from asyncio_open_serial(pipe_name)
|
||||
except OSError as e:
|
||||
raise VirtualBoxError("Could not open serial pipe '{}': {}".format(pipe_name, e))
|
||||
server = AsyncioTelnetServer(reader=self._remote_pipe,
|
||||
writer=self._remote_pipe,
|
||||
binary=True,
|
||||
|
||||
@@ -32,6 +32,7 @@ import shlex
|
||||
from collections import OrderedDict
|
||||
from gns3server.utils.interfaces import interfaces
|
||||
from gns3server.utils.asyncio import subprocess_check_output
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
from gns3server.utils import parse_version
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -738,4 +739,4 @@ if __name__ == '__main__':
|
||||
loop = asyncio.get_event_loop()
|
||||
vmware = VMware.instance()
|
||||
print("=> Check version")
|
||||
loop.run_until_complete(asyncio.async(vmware.check_vmware_version()))
|
||||
loop.run_until_complete(asyncio_ensure_future(vmware.check_vmware_version()))
|
||||
@@ -26,7 +26,7 @@ import tempfile
|
||||
|
||||
from gns3server.utils.asyncio.telnet_server import AsyncioTelnetServer
|
||||
from gns3server.utils.asyncio.serial import asyncio_open_serial
|
||||
from gns3server.utils.asyncio import locked_coroutine
|
||||
from gns3server.utils.asyncio import locking
|
||||
from collections import OrderedDict
|
||||
from .vmware_error import VMwareError
|
||||
from ..nios.nio_udp import NIOUDP
|
||||
@@ -94,7 +94,8 @@ class VMwareVM(BaseNode):
|
||||
|
||||
return self._vmnets
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def _control_vm(self, subcommand, *additional_args):
|
||||
|
||||
args = [self._vmx_path]
|
||||
@@ -844,7 +845,12 @@ class VMwareVM(BaseNode):
|
||||
"""
|
||||
Starts remote console support for this VM.
|
||||
"""
|
||||
self._remote_pipe = yield from asyncio_open_serial(self._get_pipe_name())
|
||||
|
||||
pipe_name = self._get_pipe_name()
|
||||
try:
|
||||
self._remote_pipe = yield from asyncio_open_serial(self._get_pipe_name())
|
||||
except OSError as e:
|
||||
raise VMwareError("Could not open serial pipe '{}': {}".format(pipe_name, e))
|
||||
server = AsyncioTelnetServer(reader=self._remote_pipe,
|
||||
writer=self._remote_pipe,
|
||||
binary=True,
|
||||
|
||||
@@ -66,10 +66,8 @@ class Controller:
|
||||
|
||||
def load_appliances(self):
|
||||
self._appliance_templates = {}
|
||||
for directory, builtin in (
|
||||
(get_resource('appliances'), True,), (self.appliances_path(), False,)
|
||||
):
|
||||
if os.path.isdir(directory):
|
||||
for directory, builtin in ((get_resource('appliances'), True,), (self.appliances_path(), False,)):
|
||||
if directory and os.path.isdir(directory):
|
||||
for file in os.listdir(directory):
|
||||
if not file.endswith('.gns3a') and not file.endswith('.gns3appliance'):
|
||||
continue
|
||||
@@ -200,7 +198,7 @@ class Controller:
|
||||
for c in computes:
|
||||
try:
|
||||
yield from self.add_compute(**c)
|
||||
except (aiohttp.web.HTTPConflict, KeyError):
|
||||
except (aiohttp.web.HTTPError, KeyError):
|
||||
pass # Skip not available servers at loading
|
||||
yield from self.load_projects()
|
||||
try:
|
||||
@@ -509,7 +507,7 @@ class Controller:
|
||||
return self._computes[compute_id]
|
||||
except KeyError:
|
||||
if compute_id == "vm":
|
||||
raise aiohttp.web.HTTPNotFound(text="You try to use a node on the GNS3 VM server but the GNS3 VM is not configured")
|
||||
raise aiohttp.web.HTTPNotFound(text="A node is set to use the GNS3 VM server but the GNS3 VM is not configured")
|
||||
raise aiohttp.web.HTTPNotFound(text="Compute ID {} doesn't exist".format(compute_id))
|
||||
|
||||
def has_compute(self, compute_id):
|
||||
|
||||
@@ -27,9 +27,9 @@ from operator import itemgetter
|
||||
|
||||
from ..utils import parse_version
|
||||
from ..utils.images import list_images
|
||||
from ..utils.asyncio import locked_coroutine
|
||||
from ..utils.asyncio import locking, asyncio_ensure_future
|
||||
from ..controller.controller_error import ControllerError
|
||||
from ..version import __version__
|
||||
from ..version import __version__, __version_info__
|
||||
|
||||
|
||||
import logging
|
||||
@@ -95,6 +95,7 @@ class Compute:
|
||||
self._set_auth(user, password)
|
||||
self._cpu_usage_percent = None
|
||||
self._memory_usage_percent = None
|
||||
self._last_error = None
|
||||
self._capabilities = {
|
||||
"version": None,
|
||||
"node_types": []
|
||||
@@ -137,6 +138,14 @@ class Compute:
|
||||
self._password = None
|
||||
self._auth = aiohttp.BasicAuth(self._user, "")
|
||||
|
||||
def set_last_error(self, msg):
|
||||
"""
|
||||
Set the last error message for this compute.
|
||||
|
||||
:param msg: message
|
||||
"""
|
||||
self._last_error = msg
|
||||
|
||||
@asyncio.coroutine
|
||||
def interfaces(self):
|
||||
"""
|
||||
@@ -301,7 +310,8 @@ class Compute:
|
||||
"connected": self._connected,
|
||||
"cpu_usage_percent": self._cpu_usage_percent,
|
||||
"memory_usage_percent": self._memory_usage_percent,
|
||||
"capabilities": self._capabilities
|
||||
"capabilities": self._capabilities,
|
||||
"last_error": self._last_error
|
||||
}
|
||||
|
||||
@asyncio.coroutine
|
||||
@@ -398,13 +408,14 @@ class Compute:
|
||||
except aiohttp.web.HTTPConflict:
|
||||
pass
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def connect(self):
|
||||
"""
|
||||
Check if remote server is accessible
|
||||
"""
|
||||
|
||||
if not self._connected and not self._closed:
|
||||
if not self._connected and not self._closed and self.host:
|
||||
try:
|
||||
log.info("Connecting to compute '{}'".format(self._id))
|
||||
response = yield from self._run_http_query("GET", "/capabilities")
|
||||
@@ -416,7 +427,7 @@ class Compute:
|
||||
if self._connection_failure == 5:
|
||||
log.warning("Cannot connect to compute '{}': {}".format(self._id, e))
|
||||
yield from self._controller.close_compute_projects(self)
|
||||
asyncio.get_event_loop().call_later(2, lambda: asyncio.async(self._try_reconnect()))
|
||||
asyncio.get_event_loop().call_later(2, lambda: asyncio_ensure_future(self._try_reconnect()))
|
||||
return
|
||||
except aiohttp.web.HTTPNotFound:
|
||||
raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server or it's a 1.X server".format(self._id))
|
||||
@@ -428,16 +439,36 @@ class Compute:
|
||||
raise aiohttp.web.HTTPConflict(text="Invalid server url for server {}".format(self._id))
|
||||
|
||||
if "version" not in response.json:
|
||||
msg = "The server {} is not a GNS3 server".format(self._id)
|
||||
log.error(msg)
|
||||
self._http_session.close()
|
||||
raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server".format(self._id))
|
||||
raise aiohttp.web.HTTPConflict(text=msg)
|
||||
self._capabilities = response.json
|
||||
if parse_version(__version__)[:2] != parse_version(response.json["version"])[:2]:
|
||||
self._http_session.close()
|
||||
raise aiohttp.web.HTTPConflict(text="The server {} versions are not compatible {} != {}".format(self._id, __version__, response.json["version"]))
|
||||
|
||||
if response.json["version"].split("-")[0] != __version__.split("-")[0]:
|
||||
msg = "GNS3 controller version {} is not the same as compute server {} version {}".format(__version__,
|
||||
self._name,
|
||||
response.json["version"])
|
||||
if __version_info__[3] == 0:
|
||||
# Stable release
|
||||
log.error(msg)
|
||||
self._http_session.close()
|
||||
self._last_error = msg
|
||||
raise aiohttp.web.HTTPConflict(text=msg)
|
||||
elif parse_version(__version__)[:2] != parse_version(response.json["version"])[:2]:
|
||||
# We don't allow different major version to interact even with dev build
|
||||
log.error(msg)
|
||||
self._http_session.close()
|
||||
self._last_error = msg
|
||||
raise aiohttp.web.HTTPConflict(text=msg)
|
||||
else:
|
||||
msg = "{}\nUsing different versions may result in unexpected problems. Please use at your own risk.".format(msg)
|
||||
self._controller.notification.emit("log.warning", {"message": msg})
|
||||
|
||||
self._notifications = asyncio.gather(self._connect_notification())
|
||||
self._connected = True
|
||||
self._connection_failure = 0
|
||||
self._last_error = None
|
||||
self._controller.notification.emit("compute.updated", self.__json__())
|
||||
|
||||
@asyncio.coroutine
|
||||
@@ -472,7 +503,7 @@ class Compute:
|
||||
|
||||
# Try to reconnect after 1 seconds 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.async(self.connect()))
|
||||
asyncio.get_event_loop().call_later(1, lambda: asyncio_ensure_future(self.connect()))
|
||||
self._ws = None
|
||||
self._cpu_usage_percent = None
|
||||
self._memory_usage_percent = None
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import asyncio
|
||||
import aiohttp
|
||||
@@ -23,6 +24,7 @@ import zipfile
|
||||
import tempfile
|
||||
import zipstream
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -77,6 +79,7 @@ def export_project(project, temporary_dir, include_images=False, keep_compute_id
|
||||
# ignore the .gns3 file
|
||||
if file.endswith(".gns3"):
|
||||
continue
|
||||
_patch_mtime(path)
|
||||
zstream.write(path, os.path.relpath(path, project._path), compress_type=zipfile.ZIP_DEFLATED)
|
||||
|
||||
# Export files from remote computes
|
||||
@@ -99,12 +102,29 @@ def export_project(project, temporary_dir, include_images=False, keep_compute_id
|
||||
f.write(data)
|
||||
response.close()
|
||||
f.close()
|
||||
_patch_mtime(temp_path)
|
||||
zstream.write(temp_path, arcname=compute_file["path"], compress_type=zipfile.ZIP_DEFLATED)
|
||||
downloaded_files.add(compute_file['path'])
|
||||
|
||||
return zstream
|
||||
|
||||
|
||||
def _patch_mtime(path):
|
||||
"""
|
||||
Patch the file mtime because ZIP does not support timestamps before 1980
|
||||
|
||||
:param path: file path
|
||||
"""
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
# only UNIX type platforms
|
||||
return
|
||||
st = os.stat(path)
|
||||
file_date = datetime.fromtimestamp(st.st_mtime)
|
||||
if file_date.year < 1980:
|
||||
new_mtime = file_date.replace(year=1980).timestamp()
|
||||
os.utime(path, (st.st_atime, new_mtime))
|
||||
|
||||
def _is_exportable(path):
|
||||
"""
|
||||
:returns: True if file should not be included in the final archive
|
||||
@@ -228,6 +248,7 @@ def _export_local_image(image, zstream):
|
||||
|
||||
if os.path.exists(path):
|
||||
arcname = os.path.join("images", directory, os.path.basename(image))
|
||||
_patch_mtime(path)
|
||||
zstream.write(path, arcname)
|
||||
return
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import asyncio
|
||||
import aiohttp
|
||||
import ipaddress
|
||||
|
||||
from ...utils.asyncio import locked_coroutine
|
||||
from ...utils.asyncio import locking, asyncio_ensure_future
|
||||
from .vmware_gns3_vm import VMwareGNS3VM
|
||||
from .virtualbox_gns3_vm import VirtualBoxGNS3VM
|
||||
from .remote_gns3_vm import RemoteGNS3VM
|
||||
@@ -246,13 +246,15 @@ class GNS3VM:
|
||||
except GNS3VMError as e:
|
||||
# User will receive the error later when they will try to use the node
|
||||
try:
|
||||
yield from self._controller.add_compute(compute_id="vm",
|
||||
name="GNS3 VM ({})".format(self.current_engine().vmname),
|
||||
host=None,
|
||||
force=True)
|
||||
compute = yield from self._controller.add_compute(compute_id="vm",
|
||||
name="GNS3 VM ({})".format(self.current_engine().vmname),
|
||||
host=None,
|
||||
force=True)
|
||||
compute.set_last_error(str(e))
|
||||
|
||||
except aiohttp.web.HTTPConflict:
|
||||
pass
|
||||
log.error("Can't start the GNS3 VM: %s", str(e))
|
||||
log.error("Cannot start the GNS3 VM: {}".format(e))
|
||||
|
||||
@asyncio.coroutine
|
||||
def exit_vm(self):
|
||||
@@ -265,7 +267,8 @@ class GNS3VM:
|
||||
except GNS3VMError as e:
|
||||
log.warn(str(e))
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def start(self):
|
||||
"""
|
||||
Start the GNS3 VM
|
||||
@@ -289,8 +292,9 @@ class GNS3VM:
|
||||
yield from engine.start()
|
||||
except Exception as e:
|
||||
yield from self._controller.delete_compute("vm")
|
||||
log.error("Can't start the GNS3 VM: {}".format(str(e)))
|
||||
log.error("Cannot start the GNS3 VM: {}".format(str(e)))
|
||||
yield from compute.update(name="GNS3 VM ({})".format(engine.vmname))
|
||||
compute.set_last_error(str(e))
|
||||
raise e
|
||||
yield from compute.connect() # we can connect now that the VM has started
|
||||
yield from compute.update(name="GNS3 VM ({})".format(engine.vmname),
|
||||
@@ -302,7 +306,7 @@ class GNS3VM:
|
||||
|
||||
# check if the VM is in the same subnet as the local server, start 10 seconds later to give
|
||||
# some time for the compute in the VM to be ready for requests
|
||||
asyncio.get_event_loop().call_later(10, lambda: asyncio.async(self._check_network(compute)))
|
||||
asyncio.get_event_loop().call_later(10, lambda: asyncio_ensure_future(self._check_network(compute)))
|
||||
|
||||
@asyncio.coroutine
|
||||
def _check_network(self, compute):
|
||||
@@ -336,8 +340,11 @@ class GNS3VM:
|
||||
self._controller.notification.emit("log.warning", {"message": msg})
|
||||
except ComputeError as e:
|
||||
log.warning("Could not check the VM is in the same subnet as the local server: {}".format(e))
|
||||
except aiohttp.web.HTTPConflict as e:
|
||||
log.warning("Could not check the VM is in the same subnet as the local server: {}".format(e.text))
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def _suspend(self):
|
||||
"""
|
||||
Suspend the GNS3 VM
|
||||
@@ -349,7 +356,8 @@ class GNS3VM:
|
||||
log.info("Suspend the GNS3 VM")
|
||||
yield from engine.suspend()
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def _stop(self):
|
||||
"""
|
||||
Stop the GNS3 VM
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import aiohttp
|
||||
import logging
|
||||
import asyncio
|
||||
@@ -107,7 +108,6 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
Check if the DHCP server associated with a vboxnet is enabled.
|
||||
|
||||
:param vboxnet: vboxnet name
|
||||
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
@@ -125,6 +125,41 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
return True
|
||||
return False
|
||||
|
||||
@asyncio.coroutine
|
||||
def _check_vboxnet_exists(self, vboxnet):
|
||||
"""
|
||||
Check if the vboxnet interface exists
|
||||
|
||||
:param vboxnet: vboxnet name
|
||||
:returns: boolean
|
||||
"""
|
||||
|
||||
properties = yield from self._execute("list", ["hostonlyifs"])
|
||||
for prop in properties.splitlines():
|
||||
try:
|
||||
name, value = prop.split(':', 1)
|
||||
except ValueError:
|
||||
continue
|
||||
if name.strip() == "Name" and value.strip() == vboxnet:
|
||||
return True
|
||||
return False
|
||||
|
||||
@asyncio.coroutine
|
||||
def _find_first_available_vboxnet(self):
|
||||
"""
|
||||
Find the first available vboxnet.
|
||||
"""
|
||||
|
||||
properties = yield from self._execute("list", ["hostonlyifs"])
|
||||
for prop in properties.splitlines():
|
||||
try:
|
||||
name, value = prop.split(':', 1)
|
||||
except ValueError:
|
||||
continue
|
||||
if name.strip() == "Name":
|
||||
return value.strip()
|
||||
return None
|
||||
|
||||
@asyncio.coroutine
|
||||
def _check_vbox_port_forwarding(self):
|
||||
"""
|
||||
@@ -158,18 +193,32 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
# get a NAT interface number
|
||||
nat_interface_number = yield from self._look_for_interface("nat")
|
||||
if nat_interface_number < 0:
|
||||
raise GNS3VMError("The GNS3 VM: {} must have a NAT interface configured in order to start".format(self.vmname))
|
||||
raise GNS3VMError('VM "{}" must have a NAT interface configured in order to start'.format(self.vmname))
|
||||
|
||||
hostonly_interface_number = yield from self._look_for_interface("hostonly")
|
||||
if hostonly_interface_number < 0:
|
||||
raise GNS3VMError("The GNS3 VM: {} must have a host only interface configured in order to start".format(self.vmname))
|
||||
raise GNS3VMError('VM "{}" must have a host-only interface configured in order to start'.format(self.vmname))
|
||||
|
||||
vboxnet = yield from self._look_for_vboxnet(hostonly_interface_number)
|
||||
if vboxnet is None:
|
||||
raise GNS3VMError("VirtualBox host-only network could not be found for interface {} on GNS3 VM".format(hostonly_interface_number))
|
||||
raise GNS3VMError('A VirtualBox host-only network could not be found on network adapter {} for "{}"'.format(hostonly_interface_number, self._vmname))
|
||||
|
||||
if not (yield from self._check_vboxnet_exists(vboxnet)):
|
||||
if sys.platform.startswith("win") and vboxnet == "vboxnet0":
|
||||
# The GNS3 VM is configured with vboxnet0 by default which is not available
|
||||
# on Windows. Try to patch this with the first available vboxnet we find.
|
||||
first_available_vboxnet = yield from self._find_first_available_vboxnet()
|
||||
if first_available_vboxnet is None:
|
||||
raise GNS3VMError('Please add a VirtualBox host-only network with DHCP enabled and attached it to network adapter {} for "{}"'.format(hostonly_interface_number, self._vmname))
|
||||
yield from self.set_hostonly_network(hostonly_interface_number, first_available_vboxnet)
|
||||
vboxnet = first_available_vboxnet
|
||||
else:
|
||||
raise GNS3VMError('VirtualBox host-only network "{}" does not exist, please make the sure the network adapter {} configuration is valid for "{}"'.format(vboxnet,
|
||||
hostonly_interface_number,
|
||||
self._vmname))
|
||||
|
||||
if not (yield from self._check_dhcp_server(vboxnet)):
|
||||
raise GNS3VMError("DHCP must be enabled on VirtualBox host-only network: {} for GNS3 VM".format(vboxnet))
|
||||
raise GNS3VMError('DHCP must be enabled on VirtualBox host-only network "{}"'.format(vboxnet))
|
||||
|
||||
vm_state = yield from self._get_state()
|
||||
log.info('"{}" state is {}'.format(self._vmname, vm_state))
|
||||
@@ -311,3 +360,17 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
||||
|
||||
yield from self._execute("modifyvm", [self._vmname, "--memory", str(ram)], timeout=3)
|
||||
log.info("GNS3 VM RAM amount set to {}".format(ram))
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_hostonly_network(self, adapter_number, hostonly_network_name):
|
||||
"""
|
||||
Set a VirtualBox host-only network on a network adapter for the GNS3 VM.
|
||||
|
||||
:param adapter_number: network adapter number
|
||||
:param hostonly_network_name: name of the VirtualBox host-only network
|
||||
"""
|
||||
|
||||
yield from self._execute("modifyvm", [self._vmname, "--hostonlyadapter{}".format(adapter_number), hostonly_network_name], timeout=3)
|
||||
log.info('VirtualBox host-only network "{}" set on network adapter {} for "{}"'.format(hostonly_network_name,
|
||||
adapter_number,
|
||||
self._vmname))
|
||||
@@ -22,6 +22,8 @@ import html
|
||||
import asyncio
|
||||
import aiohttp
|
||||
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -296,7 +298,7 @@ class Link:
|
||||
|
||||
self._capturing = True
|
||||
self._capture_file_name = capture_file_name
|
||||
self._streaming_pcap = asyncio.async(self._start_streaming_pcap())
|
||||
self._streaming_pcap = asyncio_ensure_future(self._start_streaming_pcap())
|
||||
self._project.controller.notification.emit("link.updated", self.__json__())
|
||||
|
||||
@asyncio.coroutine
|
||||
|
||||
@@ -175,9 +175,9 @@ class Node:
|
||||
if not os.path.isabs(path):
|
||||
path = os.path.join(self.project.controller.configs_path(), path)
|
||||
try:
|
||||
with open(path) as f:
|
||||
with open(path, encoding="utf-8") as f:
|
||||
return f.read()
|
||||
except (PermissionError, OSError):
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
@property
|
||||
|
||||
@@ -33,8 +33,8 @@ class ATMPort(SerialPort):
|
||||
"""
|
||||
return "ATM"
|
||||
|
||||
@property
|
||||
def short_name_type(self):
|
||||
@staticmethod
|
||||
def short_name_type():
|
||||
"""
|
||||
Returns the short name type for this port.
|
||||
|
||||
@@ -42,10 +42,6 @@ class ATMPort(SerialPort):
|
||||
"""
|
||||
return "a"
|
||||
|
||||
@property
|
||||
def short_name(self):
|
||||
return "{}".format(self._port_number)
|
||||
|
||||
@property
|
||||
def data_link_types(self):
|
||||
"""
|
||||
|
||||
@@ -39,8 +39,8 @@ class EthernetPort(Port):
|
||||
|
||||
return "Ethernet"
|
||||
|
||||
@property
|
||||
def short_name_type(self):
|
||||
@staticmethod
|
||||
def short_name_type():
|
||||
"""
|
||||
Returns the short name type for this port.
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ class FastEthernetPort(Port):
|
||||
|
||||
return "FastEthernet"
|
||||
|
||||
@property
|
||||
def short_name_type(self):
|
||||
@staticmethod
|
||||
def short_name_type():
|
||||
"""
|
||||
Returns the short name type for this port.
|
||||
|
||||
|
||||
@@ -34,10 +34,6 @@ class FrameRelayPort(SerialPort):
|
||||
|
||||
return "FrameRelay"
|
||||
|
||||
@property
|
||||
def short_name(self):
|
||||
return "{}".format(self._port_number)
|
||||
|
||||
@property
|
||||
def data_link_types(self):
|
||||
"""
|
||||
|
||||
@@ -34,8 +34,8 @@ class GigabitEthernetPort(Port):
|
||||
|
||||
return "GigabitEthernet"
|
||||
|
||||
@property
|
||||
def short_name_type(self):
|
||||
@staticmethod
|
||||
def short_name_type():
|
||||
"""
|
||||
Returns the short name type for this port.
|
||||
|
||||
|
||||
@@ -67,9 +67,9 @@ class Port:
|
||||
if self._short_name:
|
||||
return self._short_name
|
||||
elif '/' in self._name:
|
||||
return self._name.replace(self.long_name_type(), self.short_name_type)
|
||||
return self._name.replace(self.long_name_type(), self.short_name_type())
|
||||
elif self._name.startswith("{}{}".format(self.long_name_type(), self._interface_number)):
|
||||
return self.short_name_type + "{}".format(self._interface_number)
|
||||
return self.short_name_type() + "{}".format(self._interface_number)
|
||||
return self._name
|
||||
|
||||
@short_name.setter
|
||||
|
||||
@@ -72,7 +72,7 @@ class StandardPortFactory:
|
||||
segment_number,
|
||||
adapter=adapter_number,
|
||||
**cls._generate_replacement(interface_number, segment_number))
|
||||
except (ValueError, KeyError) as e:
|
||||
except (IndexError, ValueError, KeyError) as e:
|
||||
raise aiohttp.web.HTTPConflict(text="Invalid port name format {}: {}".format(port_name_format, str(e)))
|
||||
port = PortFactory(port_name, segment_number, adapter_number, port_number, "ethernet")
|
||||
interface_number += 1
|
||||
@@ -191,7 +191,7 @@ class DynamipsPortFactory:
|
||||
for port_number in range(0, cls.ADAPTER_MATRIX[properties[name]]["nb_ports"]):
|
||||
name = "{}{}/{}".format(port_class.long_name_type(), adapter_number, port_number)
|
||||
port = port_class(name, adapter_number, adapter_number, port_number)
|
||||
port.short_name = "{}{}/{}".format(port.short_name_type, adapter_number, port_number)
|
||||
port.short_name = "{}{}/{}".format(port_class.short_name_type(), adapter_number, port_number)
|
||||
ports.append(port)
|
||||
adapter_number += 1
|
||||
elif name.startswith("wic") and properties[name]:
|
||||
@@ -200,7 +200,7 @@ class DynamipsPortFactory:
|
||||
for port_number in range(0, cls.WIC_MATRIX[properties[name]]["nb_ports"]):
|
||||
name = "{}{}/{}".format(port_class.long_name_type(), 0, display_wic_port_number)
|
||||
port = port_class(name, 0, 0, wic_port_number)
|
||||
port.short_name = "{}{}/{}".format(port.short_name_type, 0, display_wic_port_number)
|
||||
port.short_name = "{}{}/{}".format(port_class.short_name_type(), 0, display_wic_port_number)
|
||||
ports.append(port)
|
||||
display_wic_port_number += 1
|
||||
wic_port_number += 1
|
||||
|
||||
@@ -33,8 +33,8 @@ class POSPort(SerialPort):
|
||||
"""
|
||||
return "POS"
|
||||
|
||||
@property
|
||||
def short_name_type(self):
|
||||
@staticmethod
|
||||
def short_name_type():
|
||||
"""
|
||||
Returns the short name type for this port.
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ class SerialPort(Port):
|
||||
|
||||
return "Serial"
|
||||
|
||||
@property
|
||||
def short_name_type(self):
|
||||
@staticmethod
|
||||
def short_name_type():
|
||||
"""
|
||||
Returns the short name type for this port.
|
||||
|
||||
|
||||
@@ -36,8 +36,9 @@ from .udp_link import UDPLink
|
||||
from ..config import Config
|
||||
from ..utils.path import check_path_allowed, get_default_project_directory
|
||||
from ..utils.asyncio.pool import Pool
|
||||
from ..utils.asyncio import locked_coroutine
|
||||
from ..utils.asyncio import locking
|
||||
from ..utils.asyncio import wait_run_in_executor
|
||||
from ..utils.asyncio import asyncio_ensure_future
|
||||
from .export_project import export_project
|
||||
from .import_project import import_project
|
||||
|
||||
@@ -524,7 +525,8 @@ class Project:
|
||||
self.dump()
|
||||
return node
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def __delete_node_links(self, node):
|
||||
"""
|
||||
Delete all link connected to this node.
|
||||
@@ -782,7 +784,8 @@ class Project:
|
||||
def _topology_file(self):
|
||||
return os.path.join(self.path, self._filename)
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def open(self):
|
||||
"""
|
||||
Load topology elements
|
||||
@@ -840,7 +843,7 @@ class Project:
|
||||
link = yield from self.add_link(link_id=link_data["link_id"])
|
||||
if "filters" in link_data:
|
||||
yield from link.update_filters(link_data["filters"])
|
||||
for node_link in link_data["nodes"]:
|
||||
for node_link in link_data.get("nodes", []):
|
||||
node = self.get_node(node_link["node_id"])
|
||||
port = node.get_port(node_link["adapter_number"], node_link["port_number"])
|
||||
if port is None:
|
||||
@@ -868,7 +871,7 @@ class Project:
|
||||
try:
|
||||
if os.path.exists(path + ".backup"):
|
||||
shutil.copy(path + ".backup", path)
|
||||
except (PermissionError, OSError):
|
||||
except OSError:
|
||||
pass
|
||||
self._status = "closed"
|
||||
self._loading = False
|
||||
@@ -887,7 +890,7 @@ class Project:
|
||||
# Start all in the background without waiting for completion
|
||||
# we ignore errors because we want to let the user open
|
||||
# their project and fix it
|
||||
asyncio.async(self.start_all())
|
||||
asyncio_ensure_future(self.start_all())
|
||||
|
||||
@asyncio.coroutine
|
||||
def wait_loaded(self):
|
||||
|
||||
@@ -101,7 +101,7 @@ class Snapshot:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
zipstream = yield from export_project(self._project, tmpdir, keep_compute_id=True, allow_all_nodes=True)
|
||||
yield from wait_run_in_executor(self._create_snapshot_file, zipstream)
|
||||
except OSError as e:
|
||||
except (ValueError, OSError, RuntimeError) as e:
|
||||
raise aiohttp.web.HTTPConflict(text="Could not create snapshot file '{}': {}".format(self.path, e))
|
||||
|
||||
@asyncio.coroutine
|
||||
|
||||
@@ -22,6 +22,9 @@ from ..utils.get_resource import get_resource
|
||||
from ..utils.picture import get_size
|
||||
from ..config import Config
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Symbols:
|
||||
"""
|
||||
@@ -72,19 +75,25 @@ class Symbols:
|
||||
def symbols_path(self):
|
||||
directory = os.path.expanduser(Config.instance().get_section_config("Server").get("symbols_path", "~/GNS3/symbols"))
|
||||
if directory:
|
||||
os.makedirs(directory, exist_ok=True)
|
||||
try:
|
||||
os.makedirs(directory, exist_ok=True)
|
||||
except OSError as e:
|
||||
log.error("Could not create symbol directory '{}': {}".format(directory, e))
|
||||
return None
|
||||
return directory
|
||||
|
||||
def get_path(self, symbol_id):
|
||||
try:
|
||||
return self._symbols_path[symbol_id]
|
||||
# Symbol not found refresh cache
|
||||
# Symbol not found, let's refresh the cache
|
||||
except KeyError:
|
||||
self.list()
|
||||
try:
|
||||
self.list()
|
||||
return self._symbols_path[symbol_id]
|
||||
except KeyError:
|
||||
return self._symbols_path[":/symbols/computer.svg"]
|
||||
except (OSError, KeyError):
|
||||
log.warning("Could not retrieve symbol '{}'".format(symbol_id))
|
||||
symbols_path = self._symbols_path
|
||||
return symbols_path[":/symbols/computer.svg"]
|
||||
|
||||
def get_size(self, symbol_id):
|
||||
try:
|
||||
|
||||
@@ -409,7 +409,7 @@ def _convert_1_3_later(topo, topo_path):
|
||||
symbol = old_node.get("symbol", ":/symbols/computer.svg")
|
||||
old_node["ports"] = _create_cloud(node, old_node, symbol)
|
||||
else:
|
||||
raise NotImplementedError("Conversion of {} is not supported".format(old_node["type"]))
|
||||
raise aiohttp.web.HTTPConflict(text="Conversion of {} is not supported".format(old_node["type"]))
|
||||
|
||||
for prop in old_node.get("properties", {}):
|
||||
if prop not in ["console", "name", "console_type", "console_host", "use_ubridge"]:
|
||||
@@ -608,13 +608,13 @@ def _create_cloud(node, old_node, icon):
|
||||
elif old_port["name"].startswith("nio_nat"):
|
||||
continue
|
||||
else:
|
||||
raise NotImplementedError("The conversion of cloud with {} is not supported".format(old_port["name"]))
|
||||
raise aiohttp.web.HTTPConflict(text="The conversion of cloud with {} is not supported".format(old_port["name"]))
|
||||
|
||||
if port_type == "udp":
|
||||
try:
|
||||
_, lport, rhost, rport = old_port["name"].split(":")
|
||||
except ValueError:
|
||||
raise NotImplementedError("UDP tunnel using IPV6 is not supported in cloud")
|
||||
raise aiohttp.web.HTTPConflict(text="UDP tunnel using IPV6 is not supported in cloud")
|
||||
port = {
|
||||
"name": "UDP tunnel {}".format(len(ports) + 1),
|
||||
"port_number": len(ports) + 1,
|
||||
@@ -645,7 +645,7 @@ def _convert_snapshots(topo_dir):
|
||||
old_snapshots_dir = os.path.join(topo_dir, "project-files", "snapshots")
|
||||
if os.path.exists(old_snapshots_dir):
|
||||
new_snapshots_dir = os.path.join(topo_dir, "snapshots")
|
||||
os.makedirs(new_snapshots_dir)
|
||||
os.makedirs(new_snapshots_dir, exist_ok=True)
|
||||
|
||||
for snapshot in os.listdir(old_snapshots_dir):
|
||||
snapshot_dir = os.path.join(old_snapshots_dir, snapshot)
|
||||
|
||||
@@ -20,7 +20,7 @@ import sys
|
||||
import struct
|
||||
import aiohttp
|
||||
import platform
|
||||
|
||||
import locale
|
||||
|
||||
try:
|
||||
import raven
|
||||
@@ -57,7 +57,7 @@ class CrashReport:
|
||||
Report crash to a third party service
|
||||
"""
|
||||
|
||||
DSN = "sync+https://56af21e241ed4c1894ebe17bf06b1cd1:6075f91067954267b51e90b9638a6fad@sentry.io/38482"
|
||||
DSN = "https://71472e2845b2422cab117bdfa8af55ec:da50c8f08b9f44d8b905356741c278df@sentry.io/38482"
|
||||
if hasattr(sys, "frozen"):
|
||||
cacert = get_resource("cacert.pem")
|
||||
if cacert is not None and os.path.isfile(cacert):
|
||||
@@ -92,7 +92,8 @@ class CrashReport:
|
||||
"url": request.path,
|
||||
"data": request.json,
|
||||
})
|
||||
self._client.tags_context({
|
||||
|
||||
context = {
|
||||
"os:name": platform.system(),
|
||||
"os:release": platform.release(),
|
||||
"os:win_32": " ".join(platform.win32_ver()),
|
||||
@@ -105,7 +106,28 @@ class CrashReport:
|
||||
"python:bit": struct.calcsize("P") * 8,
|
||||
"python:encoding": sys.getdefaultencoding(),
|
||||
"python:frozen": "{}".format(hasattr(sys, "frozen"))
|
||||
})
|
||||
}
|
||||
|
||||
if sys.platform.startswith("linux") and not hasattr(sys, "frozen"):
|
||||
# add locale information
|
||||
try:
|
||||
language, encoding = locale.getlocale()
|
||||
context["locale:language"] = language
|
||||
context["locale:encoding"] = encoding
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# add GNS3 VM version if it exists
|
||||
home = os.path.expanduser("~")
|
||||
gns3vm_version = os.path.join(home, ".config", "GNS3", "gns3vm_version")
|
||||
if os.path.isfile(gns3vm_version):
|
||||
try:
|
||||
with open(gns3vm_version) as fd:
|
||||
context["gns3vm:version"] = fd.readline().strip()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
self._client.tags_context(context)
|
||||
try:
|
||||
report = self._client.captureException()
|
||||
except Exception as e:
|
||||
|
||||
@@ -20,6 +20,7 @@ import aiohttp
|
||||
from aiohttp.web import WebSocketResponse
|
||||
from gns3server.web.route import Route
|
||||
from gns3server.compute.notification_manager import NotificationManager
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
@@ -43,7 +44,7 @@ class NotificationHandler:
|
||||
ws = WebSocketResponse()
|
||||
yield from ws.prepare(request)
|
||||
|
||||
asyncio.async(process_websocket(ws))
|
||||
asyncio_ensure_future(process_websocket(ws))
|
||||
|
||||
with notifications.queue() as queue:
|
||||
while True:
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import aiohttp
|
||||
import asyncio
|
||||
import tempfile
|
||||
@@ -25,6 +26,7 @@ from gns3server.controller import Controller
|
||||
from gns3server.controller.import_project import import_project
|
||||
from gns3server.controller.export_project import export_project
|
||||
from gns3server.config import Config
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
|
||||
|
||||
from gns3server.schemas.project import (
|
||||
@@ -246,7 +248,7 @@ class ProjectHandler:
|
||||
ws = aiohttp.web.WebSocketResponse()
|
||||
yield from ws.prepare(request)
|
||||
|
||||
asyncio.async(process_websocket(ws))
|
||||
asyncio_ensure_future(process_websocket(ws))
|
||||
|
||||
with controller.notification.queue(project) as queue:
|
||||
while True:
|
||||
@@ -302,8 +304,8 @@ class ProjectHandler:
|
||||
yield from response.write_eof()
|
||||
# Will be raise if you have no space left or permission issue on your temporary directory
|
||||
# RuntimeError: something was wrong during the zip process
|
||||
except (OSError, RuntimeError) as e:
|
||||
raise aiohttp.web.HTTPNotFound(text="Can't export project: {}".format(str(e)))
|
||||
except (ValueError, OSError, RuntimeError) as e:
|
||||
raise aiohttp.web.HTTPNotFound(text="Cannot export project: {}".format(str(e)))
|
||||
|
||||
@Route.post(
|
||||
r"/projects/{project_id}/import",
|
||||
@@ -332,14 +334,25 @@ class ProjectHandler:
|
||||
# We write the content to a temporary location and after we extract it all.
|
||||
# It could be more optimal to stream this but it is not implemented in Python.
|
||||
# Spooled means the file is temporary kept in memory until max_size is reached
|
||||
# Cannot use tempfile.SpooledTemporaryFile(max_size=10000) in Python 3.7 due
|
||||
# to a bug https://bugs.python.org/issue26175
|
||||
try:
|
||||
with tempfile.SpooledTemporaryFile(max_size=10000) as temp:
|
||||
while True:
|
||||
chunk = yield from request.content.read(1024)
|
||||
if not chunk:
|
||||
break
|
||||
temp.write(chunk)
|
||||
project = yield from import_project(controller, request.match_info["project_id"], temp, location=path, name=name)
|
||||
if sys.version_info >= (3, 7) and sys.version_info < (3, 8):
|
||||
with tempfile.TemporaryFile() as temp:
|
||||
while True:
|
||||
chunk = yield from request.content.read(1024)
|
||||
if not chunk:
|
||||
break
|
||||
temp.write(chunk)
|
||||
project = yield from import_project(controller, request.match_info["project_id"], temp, location=path, name=name)
|
||||
else:
|
||||
with tempfile.SpooledTemporaryFile(max_size=10000) as temp:
|
||||
while True:
|
||||
chunk = yield from request.content.read(1024)
|
||||
if not chunk:
|
||||
break
|
||||
temp.write(chunk)
|
||||
project = yield from import_project(controller, request.match_info["project_id"], temp, location=path, name=name)
|
||||
except OSError as e:
|
||||
raise aiohttp.web.HTTPInternalServerError(text="Could not import the project: {}".format(e))
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ from gns3server.config import Config
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.schemas.version import VERSION_SCHEMA
|
||||
from gns3server.version import __version__
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
|
||||
from aiohttp.web import HTTPConflict, HTTPForbidden
|
||||
|
||||
@@ -57,7 +58,7 @@ class ServerHandler:
|
||||
|
||||
tasks = []
|
||||
for project in projects:
|
||||
tasks.append(asyncio.async(project.close()))
|
||||
tasks.append(asyncio_ensure_future(project.close()))
|
||||
|
||||
if tasks:
|
||||
done, _ = yield from asyncio.wait(tasks)
|
||||
@@ -71,7 +72,10 @@ class ServerHandler:
|
||||
# then shutdown the server itself
|
||||
from gns3server.web.web_server import WebServer
|
||||
server = WebServer.instance()
|
||||
asyncio.async(server.shutdown_server())
|
||||
try:
|
||||
asyncio_ensure_future(server.shutdown_server())
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
response.set_status(201)
|
||||
|
||||
@Route.get(
|
||||
|
||||
@@ -52,7 +52,8 @@ class SymbolHandler:
|
||||
controller = Controller.instance()
|
||||
try:
|
||||
yield from response.file(controller.symbols.get_path(request.match_info["symbol_id"]))
|
||||
except (KeyError, FileNotFoundError, PermissionError):
|
||||
except (KeyError, OSError) as e:
|
||||
log.warning("Could not get symbol file: {}".format(e))
|
||||
response.set_status(404)
|
||||
|
||||
@Route.post(
|
||||
@@ -66,7 +67,7 @@ class SymbolHandler:
|
||||
controller = Controller.instance()
|
||||
path = os.path.join(controller.symbols.symbols_path(), os.path.basename(request.match_info["symbol_id"]))
|
||||
try:
|
||||
with open(path, 'wb') as f:
|
||||
with open(path, "wb") as f:
|
||||
while True:
|
||||
try:
|
||||
chunk = yield from request.content.read(1024)
|
||||
@@ -75,7 +76,7 @@ class SymbolHandler:
|
||||
if not chunk:
|
||||
break
|
||||
f.write(chunk)
|
||||
except OSError as e:
|
||||
except (UnicodeEncodeError, OSError) as e:
|
||||
raise aiohttp.web.HTTPConflict(text="Could not write symbol file '{}': {}".format(path, e))
|
||||
# Reset the symbol list
|
||||
controller.symbols.list()
|
||||
|
||||
@@ -104,6 +104,10 @@ COMPUTE_OBJECT_SCHEMA = {
|
||||
"maximum": 100,
|
||||
"minimum": 0
|
||||
},
|
||||
"last_error": {
|
||||
"description": "Last error on the compute",
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"capabilities": CAPABILITIES_SCHEMA
|
||||
},
|
||||
"additionalProperties": False,
|
||||
|
||||
@@ -131,7 +131,7 @@ QEMU_CREATE_SCHEMA = {
|
||||
},
|
||||
"boot_priority": {
|
||||
"description": "QEMU boot priority",
|
||||
"enum": ["c", "d", "n", "cn", "cd"]
|
||||
"enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"]
|
||||
},
|
||||
"ram": {
|
||||
"description": "Amount of RAM in MB",
|
||||
@@ -316,7 +316,7 @@ QEMU_UPDATE_SCHEMA = {
|
||||
},
|
||||
"boot_priority": {
|
||||
"description": "QEMU boot priority",
|
||||
"enum": ["c", "d", "n", "cn", "cd"]
|
||||
"enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"]
|
||||
},
|
||||
"ram": {
|
||||
"description": "Amount of RAM in MB",
|
||||
@@ -500,7 +500,7 @@ QEMU_OBJECT_SCHEMA = {
|
||||
},
|
||||
"boot_priority": {
|
||||
"description": "QEMU boot priority",
|
||||
"enum": ["c", "d", "n", "cn", "cd"]
|
||||
"enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"]
|
||||
},
|
||||
"node_directory": {
|
||||
"description": "Path to the VM working directory",
|
||||
|
||||
@@ -178,7 +178,7 @@ class Hypervisor(UBridgeHypervisor):
|
||||
env=env)
|
||||
|
||||
log.info("ubridge started PID={}".format(self._process.pid))
|
||||
except (OSError, PermissionError, subprocess.SubprocessError) as e:
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
ubridge_stdout = self.read_stdout()
|
||||
log.error("Could not start ubridge: {}\n{}".format(e, ubridge_stdout))
|
||||
raise UbridgeError("Could not start ubridge: {}\n{}".format(e, ubridge_stdout))
|
||||
|
||||
@@ -20,7 +20,7 @@ import time
|
||||
import logging
|
||||
import asyncio
|
||||
|
||||
from ..utils.asyncio import locked_coroutine
|
||||
from ..utils.asyncio import locking
|
||||
from .ubridge_error import UbridgeError
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -176,7 +176,8 @@ class UBridgeHypervisor:
|
||||
|
||||
self._host = host
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def send(self, command):
|
||||
"""
|
||||
Sends commands to this hypervisor.
|
||||
|
||||
@@ -108,7 +108,7 @@ def _check_process(process, termination_callback):
|
||||
def monitor_process(process, termination_callback):
|
||||
"""Call termination_callback when a process dies"""
|
||||
|
||||
asyncio.async(_check_process(process, termination_callback))
|
||||
asyncio_ensure_future(_check_process(process, termination_callback))
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
@@ -138,23 +138,32 @@ def wait_for_named_pipe_creation(pipe_path, timeout=60):
|
||||
return
|
||||
raise asyncio.TimeoutError()
|
||||
|
||||
#FIXME: Use the following wrapper when we drop Python 3.4 and use the async def syntax
|
||||
# def locking(f):
|
||||
#
|
||||
# @wraps(f)
|
||||
# async def wrapper(oself, *args, **kwargs):
|
||||
# lock_name = "__" + f.__name__ + "_lock"
|
||||
# if not hasattr(oself, lock_name):
|
||||
# setattr(oself, lock_name, asyncio.Lock())
|
||||
# async with getattr(oself, lock_name):
|
||||
# return await f(oself, *args, **kwargs)
|
||||
# return wrapper
|
||||
|
||||
def locked_coroutine(f):
|
||||
"""
|
||||
Method decorator that replace asyncio.coroutine that warranty
|
||||
that this specific method of this class instance will not we
|
||||
executed twice at the same time
|
||||
"""
|
||||
@asyncio.coroutine
|
||||
def new_function(*args, **kwargs):
|
||||
def locking(f):
|
||||
|
||||
# In the instance of the class we will store
|
||||
# a lock has an attribute.
|
||||
lock_var_name = "__" + f.__name__ + "_lock"
|
||||
if not hasattr(args[0], lock_var_name):
|
||||
setattr(args[0], lock_var_name, asyncio.Lock())
|
||||
@functools.wraps(f)
|
||||
def wrapper(oself, *args, **kwargs):
|
||||
lock_name = "__" + f.__name__ + "_lock"
|
||||
if not hasattr(oself, lock_name):
|
||||
setattr(oself, lock_name, asyncio.Lock())
|
||||
with (yield from getattr(oself, lock_name)):
|
||||
return (yield from f(oself, *args, **kwargs))
|
||||
return wrapper
|
||||
|
||||
with (yield from getattr(args[0], lock_var_name)):
|
||||
return (yield from f(*args, **kwargs))
|
||||
|
||||
return new_function
|
||||
#FIXME: conservative approach to supported versions, please remove it when we drop the support to Python < 3.4.4
|
||||
try:
|
||||
from asyncio import ensure_future
|
||||
asyncio_ensure_future = asyncio.ensure_future
|
||||
except ImportError:
|
||||
asyncio_ensure_future = getattr(asyncio, 'async')
|
||||
@@ -20,6 +20,8 @@ import copy
|
||||
import asyncio
|
||||
import asyncio.subprocess
|
||||
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -69,8 +71,8 @@ class AsyncioRawCommandServer:
|
||||
else:
|
||||
replaces.append((replace[0], replace[1], ))
|
||||
|
||||
network_read = asyncio.async(network_reader.read(READ_SIZE))
|
||||
reader_read = asyncio.async(process_reader.read(READ_SIZE))
|
||||
network_read = asyncio_ensure_future(network_reader.read(READ_SIZE))
|
||||
reader_read = asyncio_ensure_future(process_reader.read(READ_SIZE))
|
||||
timeout = 30
|
||||
|
||||
while True:
|
||||
@@ -89,7 +91,7 @@ class AsyncioRawCommandServer:
|
||||
if network_reader.at_eof():
|
||||
raise ConnectionResetError()
|
||||
|
||||
network_read = asyncio.async(network_reader.read(READ_SIZE))
|
||||
network_read = asyncio_ensure_future(network_reader.read(READ_SIZE))
|
||||
|
||||
process_writer.write(data)
|
||||
yield from process_writer.drain()
|
||||
@@ -97,7 +99,7 @@ class AsyncioRawCommandServer:
|
||||
if process_reader.at_eof():
|
||||
raise ConnectionResetError()
|
||||
|
||||
reader_read = asyncio.async(process_reader.read(READ_SIZE))
|
||||
reader_read = asyncio_ensure_future(process_reader.read(READ_SIZE))
|
||||
|
||||
for replace in replaces:
|
||||
data = data.replace(replace[0], replace[1])
|
||||
|
||||
@@ -20,6 +20,8 @@ import asyncio
|
||||
import asyncio.subprocess
|
||||
import struct
|
||||
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -195,11 +197,9 @@ class AsyncioTelnetServer:
|
||||
yield from self._write_intro(network_writer, echo=self._echo, binary=self._binary, naws=self._naws)
|
||||
yield from connection.connected()
|
||||
yield from self._process(network_reader, network_writer, connection)
|
||||
except ConnectionResetError:
|
||||
except ConnectionError:
|
||||
with (yield from self._lock):
|
||||
|
||||
network_writer.close()
|
||||
|
||||
if self._reader_process == network_reader:
|
||||
self._reader_process = None
|
||||
# Cancel current read from this reader
|
||||
@@ -212,9 +212,12 @@ class AsyncioTelnetServer:
|
||||
@asyncio.coroutine
|
||||
def close(self):
|
||||
for writer, connection in self._connections.items():
|
||||
writer.write_eof()
|
||||
yield from writer.drain()
|
||||
|
||||
try:
|
||||
writer.write_eof()
|
||||
yield from writer.drain()
|
||||
except ConnectionError:
|
||||
continue
|
||||
|
||||
@asyncio.coroutine
|
||||
def client_connected_hook(self):
|
||||
pass
|
||||
@@ -229,13 +232,13 @@ class AsyncioTelnetServer:
|
||||
self._reader_process = network_reader
|
||||
if self._reader:
|
||||
if self._reader_process == network_reader:
|
||||
self._current_read = asyncio.async(self._reader.read(READ_SIZE))
|
||||
self._current_read = asyncio_ensure_future(self._reader.read(READ_SIZE))
|
||||
return self._current_read
|
||||
return None
|
||||
|
||||
@asyncio.coroutine
|
||||
def _process(self, network_reader, network_writer, connection):
|
||||
network_read = asyncio.async(network_reader.read(READ_SIZE))
|
||||
network_read = asyncio_ensure_future(network_reader.read(READ_SIZE))
|
||||
reader_read = yield from self._get_reader(network_reader)
|
||||
|
||||
while True:
|
||||
@@ -261,7 +264,7 @@ class AsyncioTelnetServer:
|
||||
if network_reader.at_eof():
|
||||
raise ConnectionResetError()
|
||||
|
||||
network_read = asyncio.async(network_reader.read(READ_SIZE))
|
||||
network_read = asyncio_ensure_future(network_reader.read(READ_SIZE))
|
||||
|
||||
if IAC in data:
|
||||
data = yield from self._IAC_parser(data, network_reader, network_writer, connection)
|
||||
@@ -317,6 +320,7 @@ class AsyncioTelnetServer:
|
||||
else:
|
||||
log.debug("Not supported negotiation sequence, received {} bytes", len(data))
|
||||
|
||||
@asyncio.coroutine
|
||||
def _IAC_parser(self, buf, network_reader, network_writer, connection):
|
||||
"""
|
||||
Processes and removes any Telnet commands from the buffer.
|
||||
@@ -418,10 +422,10 @@ if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
process = loop.run_until_complete(asyncio.async(asyncio.subprocess.create_subprocess_exec("/bin/sh", "-i",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.STDOUT,
|
||||
stdin=asyncio.subprocess.PIPE)))
|
||||
process = loop.run_until_complete(asyncio_ensure_future(asyncio.subprocess.create_subprocess_exec("/bin/sh", "-i",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.STDOUT,
|
||||
stdin=asyncio.subprocess.PIPE)))
|
||||
server = AsyncioTelnetServer(reader=process.stdout, writer=process.stdin, binary=False, echo=False)
|
||||
|
||||
coro = asyncio.start_server(server.run, '127.0.0.1', 4444, loop=loop)
|
||||
|
||||
@@ -43,8 +43,16 @@ class PingStats:
|
||||
cur_time > cls._last_measurement + 1.9:
|
||||
cls._last_measurement = cur_time
|
||||
# Non blocking call to get cpu usage. First call will return 0
|
||||
cls._last_cpu_percent = psutil.cpu_percent(interval=None)
|
||||
cls._last_mem_percent = psutil.virtual_memory().percent
|
||||
try:
|
||||
cls._last_cpu_percent = psutil.cpu_percent(interval=None)
|
||||
cls._last_mem_percent = psutil.virtual_memory().percent
|
||||
except RuntimeError:
|
||||
# ignore the following error:
|
||||
# RuntimeError: host_statistics(HOST_CPU_LOAD_INFO) syscall failed: (ipc/send) invalid reply port
|
||||
pass
|
||||
except PermissionError:
|
||||
# [Errno 13] Permission denied: '/proc/stat'
|
||||
pass
|
||||
stats["cpu_usage_percent"] = cls._last_cpu_percent
|
||||
stats["memory_usage_percent"] = cls._last_mem_percent
|
||||
return stats
|
||||
@@ -23,8 +23,8 @@
|
||||
# or negative for a release candidate or beta (after the base version
|
||||
# number has been incremented)
|
||||
|
||||
__version__ = "2.1.9"
|
||||
__version_info__ = (2, 1, 9, 0)
|
||||
__version__ = "2.1.10"
|
||||
__version_info__ = (2, 1, 10, 0)
|
||||
|
||||
# If it's a git checkout try to add the commit
|
||||
if "dev" in __version__:
|
||||
|
||||
@@ -225,6 +225,11 @@ class Route(object):
|
||||
response = Response(request=request, route=route)
|
||||
response.set_status(408)
|
||||
response.json({"message": "Client error", "status": 408})
|
||||
except MemoryError:
|
||||
log.error("Memory error detected, server has run out of memory!", exc_info=1)
|
||||
response = Response(request=request, route=route)
|
||||
response.set_status(500)
|
||||
response.json({"message": "Memory error", "status": 500})
|
||||
except Exception as e:
|
||||
log.error("Uncaught exception detected: {type}".format(type=type(e)), exc_info=1)
|
||||
response = Response(request=request, route=route)
|
||||
|
||||
@@ -29,12 +29,17 @@ import functools
|
||||
import time
|
||||
import atexit
|
||||
|
||||
# Import encoding now, to avoid implicit import later.
|
||||
# Implicit import within threads may cause LookupError when standard library is in a ZIP
|
||||
import encodings.idna
|
||||
|
||||
from .route import Route
|
||||
from ..config import Config
|
||||
from ..compute import MODULES
|
||||
from ..compute.port_manager import PortManager
|
||||
from ..compute.qemu import Qemu
|
||||
from ..controller import Controller
|
||||
from ..utils.asyncio import asyncio_ensure_future
|
||||
|
||||
# do not delete this import
|
||||
import gns3server.handlers
|
||||
@@ -136,7 +141,10 @@ class WebServer:
|
||||
|
||||
def signal_handler(signame, *args):
|
||||
log.warning("Server has got signal {}, exiting...".format(signame))
|
||||
asyncio.async(self.shutdown_server())
|
||||
try:
|
||||
asyncio_ensure_future(self.shutdown_server())
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
signals = ["SIGTERM", "SIGINT"]
|
||||
if sys.platform.startswith("win"):
|
||||
@@ -203,7 +211,7 @@ class WebServer:
|
||||
# Because with a large image collection
|
||||
# without md5sum already computed we start the
|
||||
# computing with server start
|
||||
asyncio.async(Qemu.instance().list_images())
|
||||
asyncio_ensure_future(Qemu.instance().list_images())
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
@@ -283,7 +291,7 @@ class WebServer:
|
||||
self._exit_handling()
|
||||
|
||||
if server_config.getboolean("shell"):
|
||||
asyncio.async(self.start_shell())
|
||||
asyncio_ensure_future(self.start_shell())
|
||||
|
||||
try:
|
||||
self._loop.run_forever()
|
||||
@@ -294,4 +302,7 @@ class WebServer:
|
||||
log.warning("TypeError exception in the loop {}".format(e))
|
||||
finally:
|
||||
if self._loop.is_running():
|
||||
self._loop.run_until_complete(self.shutdown_server())
|
||||
try:
|
||||
self._loop.run_until_complete(self.shutdown_server())
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
jsonschema>=2.4.0
|
||||
aiohttp>=2.2.0,<2.4.0 # pyup: ignore
|
||||
aiohttp>=2.3.3,<2.4.0 # pyup: ignore
|
||||
aiohttp-cors>=0.5.3,<0.6.0 # pyup: ignore
|
||||
yarl>=0.11
|
||||
Jinja2>=2.7.3
|
||||
|
||||
@@ -62,17 +62,21 @@ setup(
|
||||
zip_safe=False,
|
||||
platforms="any",
|
||||
classifiers=[
|
||||
"Development Status :: 4 - Beta",
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Environment :: Console",
|
||||
"Intended Audience :: Information Technology",
|
||||
"Topic :: System :: Networking",
|
||||
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||
"Natural Language :: English",
|
||||
"Operating System :: OS Independent",
|
||||
"Operating System :: POSIX",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
],
|
||||
)
|
||||
@@ -45,7 +45,7 @@ def test_query_success(loop, vm):
|
||||
|
||||
response.read.side_effect = read
|
||||
vm._session.request = AsyncioMagicMock(return_value=response)
|
||||
data = loop.run_until_complete(asyncio.async(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
data = loop.run_until_complete(asyncio.ensure_future(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
vm._session.request.assert_called_with('POST',
|
||||
'http://docker/v1.25/test',
|
||||
data='{"a": true}',
|
||||
@@ -68,7 +68,7 @@ def test_query_error(loop, vm):
|
||||
response.read.side_effect = read
|
||||
vm._session.request = AsyncioMagicMock(return_value=response)
|
||||
with pytest.raises(DockerError):
|
||||
data = loop.run_until_complete(asyncio.async(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
data = loop.run_until_complete(asyncio.ensure_future(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
vm._session.request.assert_called_with('POST',
|
||||
'http://docker/v1.25/test',
|
||||
data='{"a": true}',
|
||||
@@ -89,7 +89,7 @@ def test_query_error_json(loop, vm):
|
||||
response.read.side_effect = read
|
||||
vm._session.request = AsyncioMagicMock(return_value=response)
|
||||
with pytest.raises(DockerError):
|
||||
data = loop.run_until_complete(asyncio.async(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
data = loop.run_until_complete(asyncio.ensure_future(vm.query("POST", "test", data={"a": True}, params={"b": 1})))
|
||||
vm._session.request.assert_called_with('POST',
|
||||
'http://docker/v1.25/test',
|
||||
data='{"a": true}',
|
||||
@@ -126,7 +126,7 @@ def test_list_images(loop):
|
||||
]
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
images = loop.run_until_complete(asyncio.async(Docker.instance().list_images()))
|
||||
images = loop.run_until_complete(asyncio.ensure_future(Docker.instance().list_images()))
|
||||
mock.assert_called_with("GET", "images/json", params={"all": 0})
|
||||
assert len(images) == 5
|
||||
assert {"image": "ubuntu:12.04"} in images
|
||||
@@ -160,7 +160,7 @@ def test_pull_image(loop):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", side_effect=DockerHttp404Error("404")):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.http_query", return_value=mock_query) as mock:
|
||||
images = loop.run_until_complete(asyncio.async(Docker.instance().pull_image("ubuntu")))
|
||||
images = loop.run_until_complete(asyncio.ensure_future(Docker.instance().pull_image("ubuntu")))
|
||||
mock.assert_called_with("POST", "images/create", params={"fromImage": "ubuntu"}, timeout=None)
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ def test_docker_check_connection_docker_minimum_version(vm, loop):
|
||||
asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response):
|
||||
vm._connected = False
|
||||
with pytest.raises(DockerError):
|
||||
loop.run_until_complete(asyncio.async(vm._check_connection()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_connection()))
|
||||
|
||||
|
||||
def test_docker_check_connection_docker_preferred_version_against_newer(vm, loop):
|
||||
@@ -185,7 +185,7 @@ def test_docker_check_connection_docker_preferred_version_against_newer(vm, loop
|
||||
with patch("gns3server.compute.docker.Docker.connector"), \
|
||||
asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response):
|
||||
vm._connected = False
|
||||
loop.run_until_complete(asyncio.async(vm._check_connection()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_connection()))
|
||||
assert vm._api_version == DOCKER_PREFERRED_API_VERSION
|
||||
|
||||
|
||||
@@ -197,5 +197,5 @@ def test_docker_check_connection_docker_preferred_version_against_older(vm, loop
|
||||
with patch("gns3server.compute.docker.Docker.connector"), \
|
||||
asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response):
|
||||
vm._connected = False
|
||||
loop.run_until_complete(asyncio.async(vm._check_connection()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_connection()))
|
||||
assert vm._api_version == DOCKER_MINIMUM_API_VERSION
|
||||
@@ -87,7 +87,7 @@ def test_create(loop, project, manager):
|
||||
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")
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
mock.assert_called_with("POST", "containers/create", data={
|
||||
"Tty": True,
|
||||
"OpenStdin": True,
|
||||
@@ -126,7 +126,7 @@ def test_create_with_tag(loop, project, manager):
|
||||
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:16.04")
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
mock.assert_called_with("POST", "containers/create", data={
|
||||
"Tty": True,
|
||||
"OpenStdin": True,
|
||||
@@ -168,7 +168,7 @@ def test_create_vnc(loop, project, manager):
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu", console_type="vnc", console=5900)
|
||||
vm._start_vnc = MagicMock()
|
||||
vm._display = 42
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
mock.assert_called_with("POST", "containers/create", data={
|
||||
"Tty": True,
|
||||
"OpenStdin": True,
|
||||
@@ -214,7 +214,7 @@ def test_create_with_extra_hosts(loop, project, manager):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu", extra_hosts=extra_hosts)
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
called_kwargs = mock.call_args[1]
|
||||
assert "GNS3_EXTRA_HOSTS=199.199.199.1\ttest\n199.199.199.1\ttest2" in called_kwargs["data"]["Env"]
|
||||
assert vm._extra_hosts == extra_hosts
|
||||
@@ -232,7 +232,7 @@ def test_create_with_extra_hosts_wrong_format(loop, project, manager):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response):
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu", extra_hosts=extra_hosts)
|
||||
with pytest.raises(DockerError):
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
|
||||
|
||||
def test_create_with_empty_extra_hosts(loop, project, manager):
|
||||
@@ -246,7 +246,7 @@ def test_create_with_empty_extra_hosts(loop, project, manager):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu", extra_hosts=extra_hosts)
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
called_kwargs = mock.call_args[1]
|
||||
assert len([ e for e in called_kwargs["data"]["Env"] if "GNS3_EXTRA_HOSTS" in e]) == 0
|
||||
|
||||
@@ -266,7 +266,7 @@ def test_create_with_project_variables(loop, project, manager):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu")
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
called_kwargs = mock.call_args[1]
|
||||
assert "VAR1=" in called_kwargs["data"]["Env"]
|
||||
assert "VAR2=VAL1" in called_kwargs["data"]["Env"]
|
||||
@@ -284,7 +284,7 @@ def test_create_start_cmd(loop, project, manager):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu:latest")
|
||||
vm._start_command = "/bin/ls"
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
mock.assert_called_with("POST", "containers/create", data={
|
||||
"Tty": True,
|
||||
"OpenStdin": True,
|
||||
@@ -328,7 +328,7 @@ def test_create_environment(loop, project, manager):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu")
|
||||
vm.environment = "YES=1\nNO=0\nGNS3_MAX_ETHERNET=eth2"
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
assert mock.call_args[1]['data']['Env'] == [
|
||||
"container=docker",
|
||||
"GNS3_MAX_ETHERNET=eth0",
|
||||
@@ -352,7 +352,7 @@ def test_create_environment_with_last_new_line_character(loop, project, manager)
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu")
|
||||
vm.environment = "YES=1\nNO=0\nGNS3_MAX_ETHERNET=eth2\n"
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
assert mock.call_args[1]['data']['Env'] == [
|
||||
"container=docker",
|
||||
"GNS3_MAX_ETHERNET=eth0",
|
||||
@@ -385,7 +385,7 @@ def test_create_image_not_available(loop, project, manager):
|
||||
vm._get_image_information.side_effect = information
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM.pull_image", return_value=True) as mock_pull:
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
mock.assert_called_with("POST", "containers/create", data={
|
||||
"Tty": True,
|
||||
"OpenStdin": True,
|
||||
@@ -431,17 +431,17 @@ def test_get_container_state(loop, vm):
|
||||
}
|
||||
}
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
assert loop.run_until_complete(asyncio.async(vm._get_container_state())) == "running"
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._get_container_state())) == "running"
|
||||
|
||||
response["State"]["Running"] = False
|
||||
response["State"]["Paused"] = True
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
assert loop.run_until_complete(asyncio.async(vm._get_container_state())) == "paused"
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._get_container_state())) == "paused"
|
||||
|
||||
response["State"]["Running"] = False
|
||||
response["State"]["Paused"] = False
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
assert loop.run_until_complete(asyncio.async(vm._get_container_state())) == "exited"
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._get_container_state())) == "exited"
|
||||
|
||||
|
||||
def test_is_running(loop, vm):
|
||||
@@ -452,17 +452,17 @@ def test_is_running(loop, vm):
|
||||
}
|
||||
}
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
assert loop.run_until_complete(asyncio.async(vm.is_running())) is False
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm.is_running())) is False
|
||||
|
||||
response["State"]["Running"] = True
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
assert loop.run_until_complete(asyncio.async(vm.is_running())) is True
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm.is_running())) is True
|
||||
|
||||
|
||||
def test_pause(loop, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock:
|
||||
loop.run_until_complete(asyncio.async(vm.pause()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.pause()))
|
||||
|
||||
mock.assert_called_with("POST", "containers/e90e34656842/pause")
|
||||
assert vm.status == "suspended"
|
||||
@@ -471,7 +471,7 @@ def test_pause(loop, vm):
|
||||
def test_unpause(loop, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock:
|
||||
loop.run_until_complete(asyncio.async(vm.unpause()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.unpause()))
|
||||
|
||||
mock.assert_called_with("POST", "containers/e90e34656842/unpause")
|
||||
|
||||
@@ -491,10 +491,10 @@ def test_start(loop, vm, manager, free_console_port):
|
||||
vm._start_console = AsyncioMagicMock()
|
||||
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
|
||||
mock_query.assert_called_with("POST", "containers/e90e34656842/start")
|
||||
vm._add_ubridge_connection.assert_called_once_with(nio, 0)
|
||||
@@ -510,7 +510,7 @@ def test_start_namespace_failed(loop, vm, manager, free_console_port):
|
||||
vm.adapters = 1
|
||||
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="stopped"):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
||||
@@ -520,7 +520,7 @@ def test_start_namespace_failed(loop, vm, manager, free_console_port):
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_log", return_value='Hello not available') as mock_log:
|
||||
|
||||
with pytest.raises(DockerError):
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
|
||||
mock_query.assert_any_call("POST", "containers/e90e34656842/start")
|
||||
mock_add_ubridge_connection.assert_called_once_with(nio, 0)
|
||||
@@ -542,7 +542,7 @@ def test_start_without_nio(loop, vm, manager, free_console_port):
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_namespace", return_value=42) as mock_namespace:
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._add_ubridge_connection") as mock_add_ubridge_connection:
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._start_console") as mock_start_console:
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
|
||||
mock_query.assert_called_with("POST", "containers/e90e34656842/start")
|
||||
assert mock_add_ubridge_connection.called
|
||||
@@ -555,7 +555,7 @@ def test_start_unpause(loop, vm, manager, free_console_port):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="paused"):
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM.unpause", return_value="paused") as mock:
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
assert mock.called
|
||||
assert vm.status == "started"
|
||||
|
||||
@@ -563,7 +563,7 @@ def test_start_unpause(loop, vm, manager, free_console_port):
|
||||
def test_restart(loop, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock:
|
||||
loop.run_until_complete(asyncio.async(vm.restart()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.restart()))
|
||||
|
||||
mock.assert_called_with("POST", "containers/e90e34656842/restart")
|
||||
|
||||
@@ -576,7 +576,7 @@ def test_stop(loop, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="running"):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
||||
loop.run_until_complete(asyncio.async(vm.stop()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
mock_query.assert_called_with("POST", "containers/e90e34656842/stop", params={"t": 5})
|
||||
assert mock.stop.called
|
||||
assert vm._ubridge_hypervisor is None
|
||||
@@ -588,7 +588,7 @@ def test_stop_paused_container(loop, vm):
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="paused"):
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM.unpause") as mock_unpause:
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
||||
loop.run_until_complete(asyncio.async(vm.stop()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
mock_query.assert_called_with("POST", "containers/e90e34656842/stop", params={"t": 5})
|
||||
assert mock_unpause.called
|
||||
|
||||
@@ -606,7 +606,7 @@ def test_update(loop, vm):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="stopped"):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock_query:
|
||||
loop.run_until_complete(asyncio.async(vm.update()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.update()))
|
||||
|
||||
mock_query.assert_any_call("DELETE", "containers/e90e34656842", params={"force": 1, "v": 1})
|
||||
mock_query.assert_any_call("POST", "containers/create", data={
|
||||
@@ -656,7 +656,7 @@ def test_update_vnc(loop, vm):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="stopped"):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock_query:
|
||||
loop.run_until_complete(asyncio.async(vm.update()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.update()))
|
||||
|
||||
assert vm.console == original_console
|
||||
assert vm.aux == original_aux
|
||||
@@ -675,7 +675,7 @@ def test_update_running(loop, vm):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]) as mock_list_images:
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="running"):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock_query:
|
||||
loop.run_until_complete(asyncio.async(vm.update()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.update()))
|
||||
|
||||
mock_query.assert_any_call("DELETE", "containers/e90e34656842", params={"force": 1, "v": 1})
|
||||
mock_query.assert_any_call("POST", "containers/create", data={
|
||||
@@ -713,7 +713,7 @@ def test_delete(loop, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="stopped"):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
||||
loop.run_until_complete(asyncio.async(vm.delete()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.delete()))
|
||||
mock_query.assert_called_with("DELETE", "containers/e90e34656842", params={"force": 1, "v": 1})
|
||||
|
||||
|
||||
@@ -723,11 +723,11 @@ def test_close(loop, vm, port_manager):
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="stopped"):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
||||
loop.run_until_complete(asyncio.async(vm.close()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
mock_query.assert_called_with("DELETE", "containers/e90e34656842", params={"force": 1, "v": 1})
|
||||
|
||||
assert vm._closed is True
|
||||
@@ -742,7 +742,7 @@ def test_close_vnc(loop, vm, port_manager):
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="stopped"):
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query") as mock_query:
|
||||
loop.run_until_complete(asyncio.async(vm.close()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
mock_query.assert_called_with("DELETE", "containers/e90e34656842", params={"force": 1, "v": 1})
|
||||
|
||||
assert vm._closed is True
|
||||
@@ -756,7 +756,7 @@ def test_get_namespace(loop, vm):
|
||||
}
|
||||
}
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock_query:
|
||||
assert loop.run_until_complete(asyncio.async(vm._get_namespace())) == 42
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._get_namespace())) == 42
|
||||
mock_query.assert_called_with("GET", "containers/e90e34656842/json")
|
||||
|
||||
|
||||
@@ -771,7 +771,7 @@ def test_add_ubridge_connection(loop, vm):
|
||||
vm._ubridge_hypervisor = MagicMock()
|
||||
vm._namespace = 42
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._add_ubridge_connection(nio, 0)))
|
||||
|
||||
calls = [
|
||||
call.send('bridge create bridge0'),
|
||||
@@ -792,7 +792,7 @@ def test_add_ubridge_connection_none_nio(loop, vm):
|
||||
vm._ubridge_hypervisor = MagicMock()
|
||||
vm._namespace = 42
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._add_ubridge_connection(nio, 0)))
|
||||
|
||||
calls = [
|
||||
call.send('bridge create bridge0'),
|
||||
@@ -813,7 +813,7 @@ def test_add_ubridge_connection_invalid_adapter_number(loop, vm):
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
with pytest.raises(DockerError):
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 12)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._add_ubridge_connection(nio, 12)))
|
||||
|
||||
|
||||
def test_add_ubridge_connection_no_free_interface(loop, vm):
|
||||
@@ -829,7 +829,7 @@ def test_add_ubridge_connection_no_free_interface(loop, vm):
|
||||
interfaces = ["tap-gns3-e{}".format(index) for index in range(4096)]
|
||||
|
||||
with patch("psutil.net_if_addrs", return_value=interfaces):
|
||||
loop.run_until_complete(asyncio.async(vm._add_ubridge_connection(nio, 0)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._add_ubridge_connection(nio, 0)))
|
||||
|
||||
|
||||
def test_adapter_add_nio_binding(vm, loop):
|
||||
@@ -838,7 +838,7 @@ def test_adapter_add_nio_binding(vm, loop):
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
assert vm._ethernet_adapters[0].get_nio(0) == nio
|
||||
|
||||
|
||||
@@ -853,9 +853,9 @@ def test_adapter_udpate_nio_binding(vm, loop):
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="running"):
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_update_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_update_nio_binding(0, nio)))
|
||||
assert vm._ubridge_apply_filters.called
|
||||
|
||||
|
||||
@@ -867,9 +867,9 @@ def test_adapter_udpate_nio_binding_bridge_not_started(vm, loop):
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="running"):
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_update_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_update_nio_binding(0, nio)))
|
||||
assert vm._ubridge_apply_filters.called is False
|
||||
|
||||
|
||||
@@ -880,7 +880,7 @@ def test_adapter_add_nio_binding_invalid_adapter(vm, loop):
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
with pytest.raises(DockerError):
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(12, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(12, nio)))
|
||||
|
||||
|
||||
def test_adapter_remove_nio_binding(vm, loop):
|
||||
@@ -892,10 +892,10 @@ def test_adapter_remove_nio_binding(vm, loop):
|
||||
"rport": 4343,
|
||||
"rhost": "127.0.0.1"}
|
||||
nio = vm.manager.create_nio(nio)
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.DockerVM._ubridge_send") as delete_ubridge_mock:
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_remove_nio_binding(0)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_remove_nio_binding(0)))
|
||||
assert vm._ethernet_adapters[0].get_nio(0) is None
|
||||
delete_ubridge_mock.assert_any_call('bridge stop bridge0')
|
||||
delete_ubridge_mock.assert_any_call('bridge remove_nio_udp bridge0 4242 127.0.0.1 4343')
|
||||
@@ -903,15 +903,15 @@ def test_adapter_remove_nio_binding(vm, loop):
|
||||
|
||||
def test_adapter_remove_nio_binding_invalid_adapter(vm, loop):
|
||||
with pytest.raises(DockerError):
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_remove_nio_binding(12)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_remove_nio_binding(12)))
|
||||
|
||||
|
||||
def test_start_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.async(vm.start_capture(0, output_file)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start_capture(0, output_file)))
|
||||
assert vm._ethernet_adapters[0].get_nio(0).capturing
|
||||
|
||||
|
||||
@@ -919,10 +919,10 @@ def test_stop_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(vm.start_capture(0, output_file))
|
||||
assert vm._ethernet_adapters[0].get_nio(0).capturing
|
||||
loop.run_until_complete(asyncio.async(vm.stop_capture(0)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop_capture(0)))
|
||||
assert vm._ethernet_adapters[0].get_nio(0).capturing is False
|
||||
|
||||
|
||||
@@ -935,7 +935,7 @@ def test_get_log(loop, vm):
|
||||
mock_query.read = read
|
||||
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.http_query", return_value=mock_query) as mock:
|
||||
images = loop.run_until_complete(asyncio.async(vm._get_log()))
|
||||
images = loop.run_until_complete(asyncio.ensure_future(vm._get_log()))
|
||||
mock.assert_called_with("GET", "containers/e90e34656842/logs", params={"stderr": 1, "stdout": 1}, data={})
|
||||
|
||||
|
||||
@@ -944,7 +944,7 @@ def test_get_image_informations(project, manager, loop):
|
||||
}
|
||||
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
|
||||
vm = DockerVM("test", str(uuid.uuid4()), project, manager, "ubuntu")
|
||||
loop.run_until_complete(asyncio.async(vm._get_image_information()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._get_image_information()))
|
||||
mock.assert_called_with("GET", "images/ubuntu:latest/json")
|
||||
|
||||
|
||||
@@ -974,7 +974,7 @@ def test_start_vnc(vm, loop):
|
||||
with patch("shutil.which", return_value="/bin/x"):
|
||||
with asyncio_patch("gns3server.compute.docker.docker_vm.wait_for_file_creation") as mock_wait:
|
||||
with asyncio_patch("asyncio.create_subprocess_exec") as mock_exec:
|
||||
loop.run_until_complete(asyncio.async(vm._start_vnc()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._start_vnc()))
|
||||
assert vm._display is not None
|
||||
mock_exec.assert_any_call("Xvfb", "-nolisten", "tcp", ":{}".format(vm._display), "-screen", "0", "1280x1024x16")
|
||||
mock_exec.assert_any_call("x11vnc", "-forever", "-nopw", "-shared", "-geometry", "1280x1024", "-display", "WAIT:{}".format(vm._display), "-rfbport", str(vm.console), "-rfbportv6", str(vm.console), "-noncache", "-listen", "127.0.0.1")
|
||||
@@ -983,13 +983,13 @@ def test_start_vnc(vm, loop):
|
||||
|
||||
def test_start_vnc_xvfb_missing(vm, loop):
|
||||
with pytest.raises(DockerError):
|
||||
loop.run_until_complete(asyncio.async(vm._start_vnc()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._start_vnc()))
|
||||
|
||||
|
||||
def test_start_aux(vm, loop):
|
||||
|
||||
with asyncio_patch("asyncio.subprocess.create_subprocess_exec", return_value=MagicMock()) as mock_exec:
|
||||
loop.run_until_complete(asyncio.async(vm._start_aux()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._start_aux()))
|
||||
mock_exec.assert_called_with('docker', 'exec', '-i', 'e90e34656842', '/gns3/bin/busybox', 'script', '-qfc', 'while true; do TERM=vt100 /gns3/bin/busybox sh; done', '/dev/null', stderr=asyncio.subprocess.STDOUT, stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE)
|
||||
|
||||
|
||||
@@ -1051,5 +1051,5 @@ def test_read_console_output_with_binary_mode(vm, loop):
|
||||
output_stream = MagicMock()
|
||||
|
||||
with asyncio_patch('gns3server.compute.docker.docker_vm.DockerVM.stop'):
|
||||
loop.run_until_complete(asyncio.async(vm._read_console_output(input_stream, output_stream)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._read_console_output(input_stream, output_stream)))
|
||||
output_stream.feed_data.assert_called_once_with(b"test")
|
||||
@@ -70,6 +70,6 @@ def test_router_invalid_dynamips_path(project, manager, loop):
|
||||
|
||||
with pytest.raises(DynamipsError):
|
||||
router = Router("test", "00010203-0405-0607-0809-0a0b0c0d0e0e", project, manager)
|
||||
loop.run_until_complete(asyncio.async(router.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(router.create()))
|
||||
assert router.name == "test"
|
||||
assert router.id == "00010203-0405-0607-0809-0a0b0c0d0e0e"
|
||||
@@ -101,7 +101,7 @@ def test_start(loop, vm):
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=mock_process) as mock_exec:
|
||||
mock_process.returncode = None
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
assert vm.is_running()
|
||||
assert vm.command_line == ' '.join(mock_exec.call_args[0])
|
||||
|
||||
@@ -129,7 +129,7 @@ def test_start_with_iourc(loop, vm, tmpdir):
|
||||
with patch("gns3server.config.Config.get_section_config", return_value={"iourc_path": fake_file}):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=mock_process) as exec_mock:
|
||||
mock_process.returncode = None
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
assert vm.is_running()
|
||||
arsgs, kwargs = exec_mock.call_args
|
||||
assert kwargs["env"]["IOURC"] == fake_file
|
||||
@@ -167,10 +167,10 @@ def test_stop(loop, vm):
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
process.returncode = None
|
||||
assert vm.is_running()
|
||||
loop.run_until_complete(asyncio.async(vm.stop()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
assert vm.is_running() is False
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
@@ -192,9 +192,9 @@ def test_reload(loop, vm, fake_iou_bin):
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
assert vm.is_running()
|
||||
loop.run_until_complete(asyncio.async(vm.reload()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.reload()))
|
||||
assert vm.is_running() is True
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
@@ -204,7 +204,7 @@ def test_close(vm, port_manager, loop):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
vm.start()
|
||||
port = vm.console
|
||||
loop.run_until_complete(asyncio.async(vm.close()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
# Raise an exception if the port is not free
|
||||
port_manager.reserve_tcp_port(port, vm.project)
|
||||
assert vm.is_running() is False
|
||||
@@ -249,7 +249,7 @@ def test_create_netmap_config(vm):
|
||||
|
||||
def test_build_command(vm, loop):
|
||||
|
||||
assert loop.run_until_complete(asyncio.async(vm._build_command())) == [vm.path, str(vm.application_id)]
|
||||
assert loop.run_until_complete(asyncio.ensure_future(vm._build_command())) == [vm.path, str(vm.application_id)]
|
||||
|
||||
|
||||
def test_get_startup_config(vm):
|
||||
@@ -311,11 +311,11 @@ def test_library_check(loop, vm):
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="") as mock:
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm._library_check()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._library_check()))
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="libssl => not found") as mock:
|
||||
with pytest.raises(IOUError):
|
||||
loop.run_until_complete(asyncio.async(vm._library_check()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._library_check()))
|
||||
|
||||
|
||||
def test_enable_l1_keepalives(loop, vm):
|
||||
@@ -323,14 +323,14 @@ def test_enable_l1_keepalives(loop, vm):
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="***************************************************************\n\n-l Enable Layer 1 keepalive messages\n-u <n> UDP port base for distributed networks\n") as mock:
|
||||
|
||||
command = ["test"]
|
||||
loop.run_until_complete(asyncio.async(vm._enable_l1_keepalives(command)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._enable_l1_keepalives(command)))
|
||||
assert command == ["test", "-l"]
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.subprocess_check_output", return_value="***************************************************************\n\n-u <n> UDP port base for distributed networks\n") as mock:
|
||||
|
||||
command = ["test"]
|
||||
with pytest.raises(IOUError):
|
||||
loop.run_until_complete(asyncio.async(vm._enable_l1_keepalives(command)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._enable_l1_keepalives(command)))
|
||||
assert command == ["test"]
|
||||
|
||||
|
||||
@@ -338,8 +338,8 @@ def test_start_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, 0, nio)))
|
||||
loop.run_until_complete(asyncio.async(vm.start_capture(0, 0, output_file)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, 0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start_capture(0, 0, output_file)))
|
||||
assert vm._adapters[0].get_nio(0).capturing
|
||||
|
||||
|
||||
@@ -347,10 +347,10 @@ def test_stop_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, 0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, 0, nio)))
|
||||
loop.run_until_complete(vm.start_capture(0, 0, output_file))
|
||||
assert vm._adapters[0].get_nio(0).capturing
|
||||
loop.run_until_complete(asyncio.async(vm.stop_capture(0, 0)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop_capture(0, 0)))
|
||||
assert vm._adapters[0].get_nio(0).capturing is False
|
||||
|
||||
|
||||
@@ -363,42 +363,42 @@ def test_invalid_iou_file(loop, vm, iourc_file):
|
||||
|
||||
hostname = socket.gethostname()
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm._check_iou_licence()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
|
||||
# Missing ;
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[license]\n{} = aaaaaaaaaaaaaaaa".format(hostname))
|
||||
loop.run_until_complete(asyncio.async(vm._check_iou_licence()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
|
||||
# Key too short
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[license]\n{} = aaaaaaaaaaaaaa;".format(hostname))
|
||||
loop.run_until_complete(asyncio.async(vm._check_iou_licence()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
|
||||
# Invalid hostname
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[license]\nbla = aaaaaaaaaaaaaa;")
|
||||
loop.run_until_complete(asyncio.async(vm._check_iou_licence()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
|
||||
# Missing licence section
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[licensetest]\n{} = aaaaaaaaaaaaaaaa;")
|
||||
loop.run_until_complete(asyncio.async(vm._check_iou_licence()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
|
||||
# Broken config file
|
||||
with pytest.raises(IOUError):
|
||||
with open(iourc_file, "w+") as f:
|
||||
f.write("[")
|
||||
loop.run_until_complete(asyncio.async(vm._check_iou_licence()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
|
||||
# Missing file
|
||||
with pytest.raises(IOUError):
|
||||
os.remove(iourc_file)
|
||||
loop.run_until_complete(asyncio.async(vm._check_iou_licence()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_iou_licence()))
|
||||
|
||||
|
||||
def test_iourc_content(vm):
|
||||
|
||||
@@ -69,5 +69,5 @@ def test_rebase(tmpdir, loop):
|
||||
qcow2 = Qcow2(str(tmpdir / "linked.qcow2"))
|
||||
assert qcow2.version == 3
|
||||
assert qcow2.backing_file == "empty8G.qcow2"
|
||||
loop.run_until_complete(asyncio.async(qcow2.rebase(qemu_img(), str(tmpdir / "empty16G.qcow2"))))
|
||||
loop.run_until_complete(asyncio.ensure_future(qcow2.rebase(qemu_img(), str(tmpdir / "empty16G.qcow2"))))
|
||||
assert qcow2.backing_file == str(tmpdir / "empty16G.qcow2")
|
||||
@@ -41,7 +41,7 @@ def fake_qemu_img_binary(tmpdir):
|
||||
def test_get_qemu_version(loop):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.subprocess_check_output", return_value="QEMU emulator version 2.2.0, Copyright (c) 2003-2008 Fabrice Bellard") as mock:
|
||||
version = loop.run_until_complete(asyncio.async(Qemu.get_qemu_version("/tmp/qemu-test")))
|
||||
version = loop.run_until_complete(asyncio.ensure_future(Qemu.get_qemu_version("/tmp/qemu-test")))
|
||||
if sys.platform.startswith("win"):
|
||||
assert version == ""
|
||||
else:
|
||||
@@ -64,7 +64,7 @@ def test_binary_list(loop):
|
||||
else:
|
||||
version = "2.2.0"
|
||||
|
||||
qemus = loop.run_until_complete(asyncio.async(Qemu.binary_list()))
|
||||
qemus = loop.run_until_complete(asyncio.ensure_future(Qemu.binary_list()))
|
||||
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} in qemus
|
||||
@@ -72,14 +72,14 @@ def test_binary_list(loop):
|
||||
assert {"path": os.path.join(os.environ["PATH"], "hello"), "version": version} not in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86_64-spice"), "version": version} not in qemus
|
||||
|
||||
qemus = loop.run_until_complete(asyncio.async(Qemu.binary_list(["x86"])))
|
||||
qemus = loop.run_until_complete(asyncio.ensure_future(Qemu.binary_list(["x86"])))
|
||||
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} not in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x42"), "version": version} not in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "hello"), "version": version} not in qemus
|
||||
|
||||
qemus = loop.run_until_complete(asyncio.async(Qemu.binary_list(["x86", "x42"])))
|
||||
qemus = loop.run_until_complete(asyncio.ensure_future(Qemu.binary_list(["x86", "x42"])))
|
||||
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-system-x86"), "version": version} in qemus
|
||||
assert {"path": os.path.join(os.environ["PATH"], "qemu-kvm"), "version": version} not in qemus
|
||||
@@ -98,7 +98,7 @@ def test_img_binary_list(loop):
|
||||
os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.subprocess_check_output", return_value="qemu-img version 2.2.0, Copyright (c) 2004-2008 Fabrice Bellard") as mock:
|
||||
qemus = loop.run_until_complete(asyncio.async(Qemu.img_binary_list()))
|
||||
qemus = loop.run_until_complete(asyncio.ensure_future(Qemu.img_binary_list()))
|
||||
|
||||
version = "2.2.0"
|
||||
|
||||
@@ -125,7 +125,7 @@ def test_create_image_abs_path(loop, tmpdir, fake_qemu_img_binary):
|
||||
"size": 100
|
||||
}
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
loop.run_until_complete(asyncio.async(Qemu.instance().create_disk(fake_qemu_img_binary, str(tmpdir / "hda.qcow2"), options)))
|
||||
loop.run_until_complete(asyncio.ensure_future(Qemu.instance().create_disk(fake_qemu_img_binary, str(tmpdir / "hda.qcow2"), options)))
|
||||
args, kwargs = process.call_args
|
||||
assert args == (
|
||||
fake_qemu_img_binary,
|
||||
@@ -152,7 +152,7 @@ def test_create_image_relative_path(loop, tmpdir, fake_qemu_img_binary):
|
||||
}
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
with patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
loop.run_until_complete(asyncio.async(Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options)))
|
||||
loop.run_until_complete(asyncio.ensure_future(Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options)))
|
||||
args, kwargs = process.call_args
|
||||
assert args == (
|
||||
fake_qemu_img_binary,
|
||||
@@ -174,7 +174,7 @@ def test_create_image_exist(loop, tmpdir, fake_qemu_img_binary):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
with patch("gns3server.compute.qemu.Qemu.get_images_directory", return_value=str(tmpdir)):
|
||||
with pytest.raises(QemuError):
|
||||
loop.run_until_complete(asyncio.async(Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options)))
|
||||
loop.run_until_complete(asyncio.ensure_future(Qemu.instance().create_disk(fake_qemu_img_binary, "hda.qcow2", options)))
|
||||
assert not process.called
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ def test_create_image_with_not_supported_characters_by_filesystem(loop, tmpdir,
|
||||
patch("os.makedirs"):
|
||||
|
||||
with pytest.raises(QemuError):
|
||||
loop.run_until_complete(asyncio.async(Qemu.instance().create_disk(
|
||||
loop.run_until_complete(asyncio.ensure_future(Qemu.instance().create_disk(
|
||||
fake_qemu_img_binary, "hda.qcow2", options)))
|
||||
assert not process.called
|
||||
|
||||
@@ -201,12 +201,12 @@ def test_create_image_with_not_supported_characters_by_filesystem(loop, tmpdir,
|
||||
def test_get_kvm_archs_kvm_ok(loop):
|
||||
|
||||
with patch("os.path.exists", return_value=True):
|
||||
archs = loop.run_until_complete(asyncio.async(Qemu.get_kvm_archs()))
|
||||
archs = loop.run_until_complete(asyncio.ensure_future(Qemu.get_kvm_archs()))
|
||||
if platform.machine() == 'x86_64':
|
||||
assert archs == ['x86_64', 'i386']
|
||||
else:
|
||||
assert archs == [platform.machine()]
|
||||
|
||||
with patch("os.path.exists", return_value=False):
|
||||
archs = loop.run_until_complete(asyncio.async(Qemu.get_kvm_archs()))
|
||||
archs = loop.run_until_complete(asyncio.ensure_future(Qemu.get_kvm_archs()))
|
||||
assert archs == []
|
||||
@@ -118,7 +118,7 @@ def test_is_running(vm, running_subprocess_mock):
|
||||
def test_start(loop, vm, running_subprocess_mock):
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=running_subprocess_mock) as mock:
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
assert vm.is_running()
|
||||
assert vm.command_line == ' '.join(mock.call_args[0])
|
||||
|
||||
@@ -135,9 +135,9 @@ def test_stop(loop, vm, running_subprocess_mock):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
|
||||
nio = Qemu.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
|
||||
vm.adapter_add_nio_binding(0, nio)
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
assert vm.is_running()
|
||||
loop.run_until_complete(asyncio.async(vm.stop()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
assert vm.is_running() is False
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
@@ -150,9 +150,9 @@ def test_termination_callback(vm, async_run):
|
||||
async_run(vm._termination_callback(0))
|
||||
assert vm.status == "stopped"
|
||||
|
||||
async_run(queue.get(0)) # Ping
|
||||
async_run(queue.get(1)) # Ping
|
||||
|
||||
(action, event, kwargs) = async_run(queue.get(0))
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
@@ -170,7 +170,7 @@ def test_termination_callback_error(vm, tmpdir, async_run):
|
||||
async_run(vm._termination_callback(1))
|
||||
assert vm.status == "stopped"
|
||||
|
||||
async_run(queue.get(0)) # Ping
|
||||
async_run(queue.get(1)) # Ping
|
||||
|
||||
(action, event, kwargs) = queue.get_nowait()
|
||||
assert action == "node.updated"
|
||||
@@ -184,7 +184,7 @@ def test_termination_callback_error(vm, tmpdir, async_run):
|
||||
def test_reload(loop, vm):
|
||||
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM._control_vm") as mock:
|
||||
loop.run_until_complete(asyncio.async(vm.reload()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.reload()))
|
||||
assert mock.called_with("system_reset")
|
||||
|
||||
|
||||
@@ -193,33 +193,33 @@ def test_suspend(loop, vm):
|
||||
control_vm_result = MagicMock()
|
||||
control_vm_result.match.group.decode.return_value = "running"
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM._control_vm", return_value=control_vm_result) as mock:
|
||||
loop.run_until_complete(asyncio.async(vm.suspend()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.suspend()))
|
||||
assert mock.called_with("system_reset")
|
||||
|
||||
|
||||
def test_add_nio_binding_udp(vm, loop):
|
||||
nio = Qemu.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
assert nio.lport == 4242
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
assert nio.lport == 4242
|
||||
|
||||
|
||||
|
||||
def test_port_remove_nio_binding(vm, loop):
|
||||
nio = Qemu.instance().create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_remove_nio_binding(0)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_remove_nio_binding(0)))
|
||||
assert vm._ethernet_adapters[0].ports[0] is None
|
||||
|
||||
|
||||
def test_close(vm, port_manager, loop):
|
||||
with asyncio_patch("gns3server.compute.qemu.QemuVM.start_wrap_console"):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
|
||||
console_port = vm.console
|
||||
|
||||
loop.run_until_complete(asyncio.async(vm.close()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
|
||||
# Raise an exception if the port is not free
|
||||
port_manager.reserve_tcp_port(console_port, vm.project)
|
||||
@@ -328,7 +328,7 @@ def test_disk_options(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
open(vm._hda_disk_image, "w+").close()
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
options = loop.run_until_complete(asyncio.async(vm._disk_options()))
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._disk_options()))
|
||||
assert process.called
|
||||
args, kwargs = process.call_args
|
||||
assert args == (fake_qemu_img_binary, "create", "-o", "backing_file={}".format(vm._hda_disk_image), "-f", "qcow2", os.path.join(vm.working_dir, "hda_disk.qcow2"))
|
||||
@@ -341,7 +341,7 @@ def test_cdrom_option(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
vm._cdrom_image = str(tmpdir / "test.iso")
|
||||
open(vm._cdrom_image, "w+").close()
|
||||
|
||||
options = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
|
||||
assert ' '.join(['-cdrom', str(tmpdir / "test.iso")]) in ' '.join(options)
|
||||
|
||||
@@ -351,7 +351,7 @@ def test_bios_option(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
vm._bios_image = str(tmpdir / "test.img")
|
||||
open(vm._bios_image, "w+").close()
|
||||
|
||||
options = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
|
||||
assert ' '.join(['-bios', str(tmpdir / "test.img")]) in ' '.join(options)
|
||||
|
||||
@@ -359,14 +359,14 @@ def test_bios_option(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
def test_vnc_option(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
vm._console_type = 'vnc'
|
||||
vm._console = 5905
|
||||
options = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
assert '-vnc 127.0.0.1:5' in ' '.join(options)
|
||||
|
||||
|
||||
def test_spice_option(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
vm._console_type = 'spice'
|
||||
vm._console = 5905
|
||||
options = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
assert '-spice addr=127.0.0.1,port=5905,disable-ticketing' in ' '.join(options)
|
||||
assert '-vga qxl' in ' '.join(options)
|
||||
|
||||
@@ -383,7 +383,7 @@ def test_disk_options_multiple_disk(vm, tmpdir, loop, fake_qemu_img_binary):
|
||||
open(vm._hdd_disk_image, "w+").close()
|
||||
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
options = loop.run_until_complete(asyncio.async(vm._disk_options()))
|
||||
options = loop.run_until_complete(asyncio.ensure_future(vm._disk_options()))
|
||||
|
||||
assert options == [
|
||||
'-drive', 'file=' + os.path.join(vm.working_dir, "hda_disk.qcow2") + ',if=ide,index=0,media=disk',
|
||||
@@ -400,7 +400,7 @@ def test_set_process_priority(vm, loop, fake_qemu_img_binary):
|
||||
vm._process = MagicMock()
|
||||
vm._process.pid = 42
|
||||
vm._process_priority = "low"
|
||||
loop.run_until_complete(asyncio.async(vm._set_process_priority()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._set_process_priority()))
|
||||
assert process.called
|
||||
args, kwargs = process.call_args
|
||||
assert args == ("renice", "-n", "5", "-p", "42")
|
||||
@@ -412,7 +412,7 @@ def test_set_process_priority_normal(vm, loop, fake_qemu_img_binary):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
vm._process = MagicMock()
|
||||
vm._process.pid = 42
|
||||
loop.run_until_complete(asyncio.async(vm._set_process_priority()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._set_process_priority()))
|
||||
assert not process.called
|
||||
|
||||
|
||||
@@ -429,7 +429,7 @@ def test_control_vm(vm, loop):
|
||||
reader = MagicMock()
|
||||
writer = MagicMock()
|
||||
with asyncio_patch("asyncio.open_connection", return_value=(reader, writer)) as open_connect:
|
||||
res = loop.run_until_complete(asyncio.async(vm._control_vm("test")))
|
||||
res = loop.run_until_complete(asyncio.ensure_future(vm._control_vm("test")))
|
||||
assert writer.write.called_with("test")
|
||||
assert res is None
|
||||
|
||||
@@ -446,7 +446,7 @@ def test_control_vm_expect_text(vm, loop, running_subprocess_mock):
|
||||
reader.readline.return_value = future
|
||||
|
||||
vm._monitor = 4242
|
||||
res = loop.run_until_complete(asyncio.async(vm._control_vm("test", [b"epic"])))
|
||||
res = loop.run_until_complete(asyncio.ensure_future(vm._control_vm("test", [b"epic"])))
|
||||
assert writer.write.called_with("test")
|
||||
|
||||
assert res == "epic product"
|
||||
@@ -456,7 +456,7 @@ def test_build_command(vm, loop, fake_qemu_binary, port_manager):
|
||||
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
nio = vm._local_udp_tunnels[0][0]
|
||||
assert cmd == [
|
||||
fake_qemu_binary,
|
||||
@@ -489,7 +489,7 @@ def test_build_command_manual_uuid(vm, loop, fake_qemu_binary, port_manager):
|
||||
vm.options = "-uuid e1c307a4-896f-11e6-81a5-3c07547807cc"
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
assert "e1c307a4-896f-11e6-81a5-3c07547807cc" in cmd
|
||||
assert vm.id not in cmd
|
||||
|
||||
@@ -502,7 +502,7 @@ def test_build_command_kvm(linux_platform, vm, loop, fake_qemu_binary, port_mana
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.3.2")
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
nio = vm._local_udp_tunnels[0][0]
|
||||
assert cmd == [
|
||||
fake_qemu_binary,
|
||||
@@ -536,7 +536,7 @@ def test_build_command_kvm_2_4(linux_platform, vm, loop, fake_qemu_binary, port_
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.4.2")
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
nio = vm._local_udp_tunnels[0][0]
|
||||
assert cmd == [
|
||||
fake_qemu_binary,
|
||||
@@ -569,7 +569,7 @@ def test_build_command_without_display(vm, loop, fake_qemu_binary):
|
||||
|
||||
os.environ["DISPLAY"] = ""
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
assert "-nographic" in cmd
|
||||
|
||||
|
||||
@@ -578,7 +578,7 @@ def test_build_command_two_adapters(vm, loop, fake_qemu_binary, port_manager):
|
||||
os.environ["DISPLAY"] = "0:0"
|
||||
vm.adapters = 2
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
nio1 = vm._local_udp_tunnels[0][0]
|
||||
nio2 = vm._local_udp_tunnels[1][0]
|
||||
assert cmd == [
|
||||
@@ -619,7 +619,7 @@ def test_build_command_two_adapters_mac_address(vm, loop, fake_qemu_binary, port
|
||||
mac_1 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 1)
|
||||
assert mac_0[:8] == "00:00:ab"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
assert "e1000,mac={},netdev=gns3-0".format(mac_0) in cmd
|
||||
assert "e1000,mac={},netdev=gns3-1".format(mac_1) in cmd
|
||||
|
||||
@@ -628,7 +628,7 @@ def test_build_command_two_adapters_mac_address(vm, loop, fake_qemu_binary, port
|
||||
mac_1 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 1)
|
||||
assert mac_0[:8] == "00:42:ab"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
assert "e1000,mac={},netdev=gns3-0".format(mac_0) in cmd
|
||||
assert "e1000,mac={},netdev=gns3-1".format(mac_1) in cmd
|
||||
|
||||
@@ -648,7 +648,7 @@ def test_build_command_large_number_of_adapters(vm, loop, fake_qemu_binary, port
|
||||
mac_1 = int_to_macaddress(macaddress_to_int(vm._mac_address) + 1)
|
||||
assert mac_0[:8] == "00:00:ab"
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
|
||||
# Count if we have 100 e1000 adapters in the command
|
||||
assert len([l for l in cmd if "e1000" in l ]) == 100
|
||||
@@ -672,10 +672,10 @@ def test_build_command_large_number_of_adapters(vm, loop, fake_qemu_binary, port
|
||||
vm.manager.get_qemu_version = AsyncioMagicMock(return_value="2.0.0")
|
||||
with pytest.raises(QemuError):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
vm.adapters = 5
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()) as process:
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
|
||||
# Windows accept this kind of mistake
|
||||
|
||||
@@ -685,7 +685,7 @@ def test_build_command_with_invalid_options(vm, loop, fake_qemu_binary):
|
||||
|
||||
vm.options = "'test"
|
||||
with pytest.raises(QemuError):
|
||||
cmd = loop.run_until_complete(asyncio.async(vm._build_command()))
|
||||
cmd = loop.run_until_complete(asyncio.ensure_future(vm._build_command()))
|
||||
|
||||
|
||||
def test_hda_disk_image(vm, images_dir):
|
||||
|
||||
@@ -83,7 +83,7 @@ def test_close(node, loop, port_manager):
|
||||
|
||||
node.aux = aux
|
||||
port = node.console
|
||||
assert loop.run_until_complete(asyncio.async(node.close()))
|
||||
assert loop.run_until_complete(asyncio.ensure_future(node.close()))
|
||||
# Raise an exception if the port is not free
|
||||
port_manager.reserve_tcp_port(port, node.project)
|
||||
# Raise an exception if the port is not free
|
||||
@@ -92,7 +92,7 @@ def test_close(node, loop, port_manager):
|
||||
assert node.aux is None
|
||||
|
||||
# Called twice closed should return False
|
||||
assert loop.run_until_complete(asyncio.async(node.close())) is False
|
||||
assert loop.run_until_complete(asyncio.ensure_future(node.close())) is False
|
||||
|
||||
|
||||
def test_aux(project, manager, port_manager):
|
||||
|
||||
@@ -43,7 +43,7 @@ def manager(port_manager):
|
||||
@pytest.fixture(scope="function")
|
||||
def node(project, manager, loop):
|
||||
node = manager.create_node("test", project.id, "00010203-0405-0607-0809-0a0b0c0d0e0f")
|
||||
return loop.run_until_complete(asyncio.async(node))
|
||||
return loop.run_until_complete(asyncio.ensure_future(node))
|
||||
|
||||
|
||||
def test_affect_uuid():
|
||||
@@ -140,7 +140,7 @@ def test_project_delete(loop):
|
||||
project = Project(project_id=str(uuid4()))
|
||||
directory = project.path
|
||||
assert os.path.exists(directory)
|
||||
loop.run_until_complete(asyncio.async(project.delete()))
|
||||
loop.run_until_complete(asyncio.ensure_future(project.delete()))
|
||||
assert os.path.exists(directory) is False
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ def test_project_delete_permission_issue(loop):
|
||||
assert os.path.exists(directory)
|
||||
os.chmod(directory, 0)
|
||||
with pytest.raises(aiohttp.web.HTTPInternalServerError):
|
||||
loop.run_until_complete(asyncio.async(project.delete()))
|
||||
loop.run_until_complete(asyncio.ensure_future(project.delete()))
|
||||
os.chmod(directory, 700)
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ def test_project_add_node(manager):
|
||||
def test_project_close(loop, node, project):
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.close") as mock:
|
||||
loop.run_until_complete(asyncio.async(project.close()))
|
||||
loop.run_until_complete(asyncio.ensure_future(project.close()))
|
||||
assert mock.called
|
||||
assert node.id not in node.manager._nodes
|
||||
|
||||
@@ -181,7 +181,7 @@ def test_list_files(tmpdir, loop):
|
||||
with open(os.path.join(path, "test.txt"), "w+") as f:
|
||||
f.write("test2")
|
||||
|
||||
files = loop.run_until_complete(asyncio.async(project.list_files()))
|
||||
files = loop.run_until_complete(asyncio.ensure_future(project.list_files()))
|
||||
|
||||
assert files == [
|
||||
{
|
||||
@@ -210,5 +210,5 @@ def test_emit(async_run):
|
||||
def test_update_project(loop):
|
||||
variables = [{"name": "TEST", "value": "VAL"}]
|
||||
project = Project(project_id=str(uuid.uuid4()))
|
||||
loop.run_until_complete(asyncio.async(project.update(variables=variables)))
|
||||
loop.run_until_complete(asyncio.ensure_future(project.update(variables=variables)))
|
||||
assert project.variables == variables
|
||||
@@ -56,7 +56,7 @@ def test_vm_invalid_traceng_path(vm, manager, loop):
|
||||
with pytest.raises(TraceNGError):
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
|
||||
vm.port_add_nio_binding(0, nio)
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0e"
|
||||
|
||||
@@ -66,13 +66,13 @@ def test_start(loop, vm, async_run):
|
||||
process.returncode = None
|
||||
|
||||
with NotificationManager.instance().queue() as queue:
|
||||
async_run(queue.get(0)) # Ping
|
||||
async_run(queue.get(1)) # Ping
|
||||
|
||||
vm.ip_address = "192.168.1.1"
|
||||
with patch("sys.platform", return_value="win"):
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process) as mock_exec:
|
||||
loop.run_until_complete(asyncio.async(vm.start("192.168.1.2")))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start("192.168.1.2")))
|
||||
assert mock_exec.call_args[0] == (vm._traceng_path(),
|
||||
'-u',
|
||||
'-c',
|
||||
@@ -88,7 +88,7 @@ def test_start(loop, vm, async_run):
|
||||
'192.168.1.2')
|
||||
assert vm.is_running()
|
||||
assert vm.command_line == ' '.join(mock_exec.call_args[0])
|
||||
(action, event, kwargs) = async_run(queue.get(0))
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
@@ -115,15 +115,15 @@ def test_stop(loop, vm, async_run):
|
||||
assert vm.is_running()
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
loop.run_until_complete(asyncio.async(vm.stop()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
assert vm.is_running() is False
|
||||
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
async_run(queue.get(0)) # Ping
|
||||
async_run(queue.get(0)) # Started
|
||||
async_run(queue.get(1)) # Ping
|
||||
async_run(queue.get(1)) # Started
|
||||
|
||||
(action, event, kwargs) = async_run(queue.get(0))
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
@@ -175,5 +175,5 @@ def test_close(vm, port_manager, loop):
|
||||
with asyncio_patch("gns3server.compute.traceng.traceng_vm.TraceNGVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
vm.start()
|
||||
loop.run_until_complete(asyncio.async(vm.close()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
assert vm.is_running() is False
|
||||
@@ -92,7 +92,7 @@ def test_list_vms(manager, loop):
|
||||
|
||||
with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.execute") as mock:
|
||||
mock.side_effect = execute_mock
|
||||
vms = loop.run_until_complete(asyncio.async(manager.list_vms()))
|
||||
vms = loop.run_until_complete(asyncio.ensure_future(manager.list_vms()))
|
||||
assert vms == [
|
||||
{"vmname": "Windows 8.1", "ram": 512},
|
||||
{"vmname": "Linux Microcore 4.7.1", "ram": 256}
|
||||
|
||||
@@ -75,20 +75,20 @@ def test_rename_vmname(project, manager, async_run):
|
||||
def test_vm_valid_virtualbox_api_version(loop, project, manager):
|
||||
with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.execute", return_value=["API version: 4_3"]):
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "test", False)
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
|
||||
|
||||
def test_vm_invalid_virtualbox_api_version(loop, project, manager):
|
||||
with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.execute", return_value=["API version: 4_2"]):
|
||||
with pytest.raises(VirtualBoxError):
|
||||
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "test", False)
|
||||
loop.run_until_complete(asyncio.async(vm.create()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.create()))
|
||||
|
||||
|
||||
def test_vm_adapter_add_nio_binding_adapter_not_exist(loop, vm, manager, free_console_port):
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
with pytest.raises(VirtualBoxError):
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(15, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(15, nio)))
|
||||
|
||||
|
||||
def test_json(vm, tmpdir, project):
|
||||
|
||||
@@ -56,8 +56,8 @@ def test_start_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
vm.adapters = 1
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.async(vm.start_capture(0, output_file)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start_capture(0, output_file)))
|
||||
assert vm._ethernet_adapters[0].get_nio(0).capturing
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ def test_stop_capture(vm, tmpdir, manager, free_console_port, loop):
|
||||
output_file = str(tmpdir / "test.pcap")
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": free_console_port, "rport": free_console_port, "rhost": "127.0.0.1"})
|
||||
vm.adapters = 1
|
||||
loop.run_until_complete(asyncio.async(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.adapter_add_nio_binding(0, nio)))
|
||||
loop.run_until_complete(vm.start_capture(0, output_file))
|
||||
assert vm._ethernet_adapters[0].get_nio(0).capturing
|
||||
loop.run_until_complete(asyncio.async(vm.stop_capture(0)))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop_capture(0)))
|
||||
assert vm._ethernet_adapters[0].get_nio(0).capturing is False
|
||||
@@ -56,13 +56,13 @@ def test_vm(project, manager):
|
||||
|
||||
def test_vm_check_vpcs_version(loop, vm, manager):
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.subprocess_check_output", return_value="Welcome to Virtual PC Simulator, version 0.9"):
|
||||
loop.run_until_complete(asyncio.async(vm._check_vpcs_version()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_vpcs_version()))
|
||||
assert vm._vpcs_version == parse_version("0.9")
|
||||
|
||||
|
||||
def test_vm_check_vpcs_version_0_6_1(loop, vm, manager):
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.subprocess_check_output", return_value="Welcome to Virtual PC Simulator, version 0.6.1"):
|
||||
loop.run_until_complete(asyncio.async(vm._check_vpcs_version()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_vpcs_version()))
|
||||
assert vm._vpcs_version == parse_version("0.6.1")
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ def test_vm_invalid_vpcs_version(loop, manager, vm):
|
||||
with pytest.raises(VPCSError):
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1", "filters": {}})
|
||||
vm.port_add_nio_binding(0, nio)
|
||||
loop.run_until_complete(asyncio.async(vm._check_vpcs_version()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm._check_vpcs_version()))
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0f"
|
||||
|
||||
@@ -81,7 +81,7 @@ def test_vm_invalid_vpcs_path(vm, manager, loop):
|
||||
with pytest.raises(VPCSError):
|
||||
nio = manager.create_nio({"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
|
||||
vm.port_add_nio_binding(0, nio)
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
assert vm.name == "test"
|
||||
assert vm.id == "00010203-0405-0607-0809-0a0b0c0d0e0e"
|
||||
|
||||
@@ -91,12 +91,12 @@ def test_start(loop, vm, async_run):
|
||||
process.returncode = None
|
||||
|
||||
with NotificationManager.instance().queue() as queue:
|
||||
async_run(queue.get(0)) # Ping
|
||||
async_run(queue.get(1)) # Ping
|
||||
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process) as mock_exec:
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_wrap_console"):
|
||||
loop.run_until_complete(asyncio.async(vm.start()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.start()))
|
||||
assert mock_exec.call_args[0] == (vm._vpcs_path(),
|
||||
'-p',
|
||||
str(vm._internal_console_port),
|
||||
@@ -113,7 +113,7 @@ def test_start(loop, vm, async_run):
|
||||
'127.0.0.1')
|
||||
assert vm.is_running()
|
||||
assert vm.command_line == ' '.join(mock_exec.call_args[0])
|
||||
(action, event, kwargs) = async_run(queue.get(0))
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
@@ -169,7 +169,7 @@ def test_stop(loop, vm, async_run):
|
||||
assert vm.is_running()
|
||||
|
||||
with asyncio_patch("gns3server.utils.asyncio.wait_for_process_termination"):
|
||||
loop.run_until_complete(asyncio.async(vm.stop()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.stop()))
|
||||
assert vm.is_running() is False
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
@@ -177,10 +177,10 @@ def test_stop(loop, vm, async_run):
|
||||
else:
|
||||
process.terminate.assert_called_with()
|
||||
|
||||
async_run(queue.get(0)) # Ping
|
||||
async_run(queue.get(0)) # Started
|
||||
async_run(queue.get(1)) # Ping
|
||||
async_run(queue.get(1)) # Started
|
||||
|
||||
(action, event, kwargs) = async_run(queue.get(0))
|
||||
(action, event, kwargs) = async_run(queue.get(1))
|
||||
assert action == "node.updated"
|
||||
assert event == vm
|
||||
|
||||
@@ -300,5 +300,5 @@ def test_close(vm, port_manager, loop):
|
||||
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM._check_requirements", return_value=True):
|
||||
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
|
||||
vm.start()
|
||||
loop.run_until_complete(asyncio.async(vm.close()))
|
||||
loop.run_until_complete(asyncio.ensure_future(vm.close()))
|
||||
assert vm.is_running() is False
|
||||
+2
-2
@@ -104,7 +104,7 @@ def http_server(request, loop, port_manager, monkeypatch, controller):
|
||||
monkeypatch.setattr('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.close', lambda self: True)
|
||||
loop.run_until_complete(instance.unload())
|
||||
srv.close()
|
||||
srv.wait_closed()
|
||||
loop.run_until_complete(srv.wait_closed())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -314,7 +314,7 @@ def async_run(loop):
|
||||
"""
|
||||
Shortcut for running in asyncio loop
|
||||
"""
|
||||
return lambda x: loop.run_until_complete(asyncio.async(x))
|
||||
return lambda x: loop.run_until_complete(asyncio.ensure_future(x))
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
|
||||
@@ -277,6 +277,7 @@ def test_json(compute):
|
||||
"cpu_usage_percent": None,
|
||||
"memory_usage_percent": None,
|
||||
"connected": True,
|
||||
"last_error": None,
|
||||
"capabilities": {
|
||||
"version": None,
|
||||
"node_types": []
|
||||
|
||||
@@ -74,7 +74,7 @@ class Query:
|
||||
response = yield from self._session.ws_connect(self.get_url(path))
|
||||
future.set_result(response)
|
||||
future = asyncio.Future()
|
||||
asyncio.async(go_request(future))
|
||||
asyncio.ensure_future(go_request(future))
|
||||
self._loop.run_until_complete(future)
|
||||
return future.result()
|
||||
|
||||
@@ -85,7 +85,7 @@ class Query:
|
||||
- example if True the session is included inside documentation
|
||||
- raw do not JSON encode the query
|
||||
"""
|
||||
return self._loop.run_until_complete(asyncio.async(self._async_fetch(method, path, body=body, **kwargs)))
|
||||
return self._loop.run_until_complete(asyncio.ensure_future(self._async_fetch(method, path, body=body, **kwargs)))
|
||||
|
||||
@asyncio.coroutine
|
||||
def _async_fetch(self, method, path, body=None, **kwargs):
|
||||
|
||||
@@ -131,6 +131,7 @@ def test_compute_list(http_controller, controller):
|
||||
'name': 'My super server',
|
||||
'cpu_usage_percent': None,
|
||||
'memory_usage_percent': None,
|
||||
'last_error': None,
|
||||
'capabilities': {
|
||||
'version': None,
|
||||
'node_types': []
|
||||
|
||||
@@ -356,7 +356,7 @@ def test_pcap(http_controller, tmpdir, project, compute, loop):
|
||||
project._links = {link.id: link}
|
||||
|
||||
future = asyncio.Future()
|
||||
asyncio.async(go(future))
|
||||
asyncio.ensure_future(go(future))
|
||||
response = loop.run_until_complete(future)
|
||||
assert response.status == 200
|
||||
assert b'hello' == response.body
|
||||
|
||||
@@ -179,7 +179,7 @@ def test_notification(http_controller, project, controller, loop, async_run):
|
||||
response.close()
|
||||
return response
|
||||
|
||||
response = async_run(asyncio.async(go()))
|
||||
response = async_run(asyncio.ensure_future(go()))
|
||||
assert response.status == 200
|
||||
assert b'"action": "ping"' in response.body
|
||||
assert b'"cpu_usage_percent"' in response.body
|
||||
|
||||
@@ -21,7 +21,7 @@ import pytest
|
||||
import sys
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from gns3server.utils.asyncio import wait_run_in_executor, subprocess_check_output, wait_for_process_termination, locked_coroutine
|
||||
from gns3server.utils.asyncio import wait_run_in_executor, subprocess_check_output, wait_for_process_termination, locking
|
||||
from tests.utils import AsyncioMagicMock
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ def test_wait_run_in_executor(loop):
|
||||
return param
|
||||
|
||||
exec = wait_run_in_executor(change_var, "test")
|
||||
result = loop.run_until_complete(asyncio.async(exec))
|
||||
result = loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
assert result == "test"
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ def test_exception_wait_run_in_executor(loop):
|
||||
|
||||
exec = wait_run_in_executor(raise_exception)
|
||||
with pytest.raises(Exception):
|
||||
result = loop.run_until_complete(asyncio.async(exec))
|
||||
result = loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
|
||||
@@ -52,7 +52,7 @@ def test_subprocess_check_output(loop, tmpdir, restore_original_path):
|
||||
with open(path, "w+") as f:
|
||||
f.write("TEST")
|
||||
exec = subprocess_check_output("cat", path)
|
||||
result = loop.run_until_complete(asyncio.async(exec))
|
||||
result = loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
assert result == "TEST"
|
||||
|
||||
|
||||
@@ -64,13 +64,13 @@ def test_wait_for_process_termination(loop):
|
||||
process = MagicMock()
|
||||
process.returncode = 0
|
||||
exec = wait_for_process_termination(process)
|
||||
loop.run_until_complete(asyncio.async(exec))
|
||||
loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
|
||||
process = MagicMock()
|
||||
process.returncode = None
|
||||
exec = wait_for_process_termination(process, timeout=0.5)
|
||||
with pytest.raises(asyncio.TimeoutError):
|
||||
loop.run_until_complete(asyncio.async(exec))
|
||||
loop.run_until_complete(asyncio.ensure_future(exec))
|
||||
|
||||
|
||||
def test_lock_decorator(loop):
|
||||
@@ -84,7 +84,8 @@ def test_lock_decorator(loop):
|
||||
def __init__(self):
|
||||
self._test_val = 0
|
||||
|
||||
@locked_coroutine
|
||||
@locking
|
||||
@asyncio.coroutine
|
||||
def method_to_lock(self):
|
||||
res = self._test_val
|
||||
yield from asyncio.sleep(0.1)
|
||||
|
||||
Reference in new issue
Block a user