diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index aac48ce34..3476159a7 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -18,11 +18,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest"] - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] - #include: - # only test with Python 3.10 on Windows - # - os: windows-latest - # python-version: "3.10" + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG b/CHANGELOG index 850f8c580..116494b9d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,10 @@ # Change Log +## 2.2.56 21/01/2026 + +* Set default location of udhcpc in "/etc/network/udhcpc". Fixes #2582 +* Upgrade pywin32 to v311 + ## 2.2.55 19/11/2025 * Docker API version requirements and process to handle older daemons diff --git a/dev-requirements.txt b/dev-requirements.txt index dd9bd2f98..20104d902 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,6 +1,6 @@ -pytest==8.3.4 -flake8==7.1.1 -pytest-timeout==2.3.1 +pytest==8.4.2 # version 8.4.2 is the last one supporting Python 3.9 +flake8==7.3.0 +pytest-timeout==2.4.0 pytest-asyncio==0.25.2 requests==2.32.5 httpx==0.28.1 diff --git a/gns3server/appliances/asterfusion-vAsterNOS-VPP.gns3a b/gns3server/appliances/asterfusion-vAsterNOS-VPP.gns3a new file mode 100644 index 000000000..3afa29fa5 --- /dev/null +++ b/gns3server/appliances/asterfusion-vAsterNOS-VPP.gns3a @@ -0,0 +1,31 @@ +{ + "name": "Asterfusion AsterNOS-VPP", + "category": "router", + "description": "AsterNOS-VPP leverages SONiC’s robust routing features and management capability with VPP’s high-performance data forwarding. It supports L3 routing, NAT, PPPoE, and VPN services. Minimum requirements: 4 vCPUs and 4GB RAM.", + "vendor_name": "Asterfusion", + "vendor_url": "https://cloudswit.ch/product/sonic-enterprise-distribution/#vAsterNOS", + "documentation_url": "https://docs.asternos.com/routing", + "product_name": "AsterNOS-VPP", + "registry_version": 6, + "status": "stable", + "maintainer": "Asterfusion Product Team", + "images": [ + { + "filename": "AsterNOS-VPP_V6.1-R0101P02_x86.img.gz", + "version": "V6.1", + "md5sum": "55834c3e8849ab226144d79ef76acf81", + "filesize": 1318201015, + "download_url": "https://asternos.dev/api/file/b2c9fd83-a9d3-46f3-9676-6b49dd481d6c", + "comments": "Registration is required to download the image." + } + ], + "qemu": { + "adapter_type": "virtio-net-pci", + "adapters": 4, + "ram": 4096, + "cpus": 4, + "arch": "x86_64", + "console_type": "telnet", + "kvm": "require" + } +} diff --git a/gns3server/appliances/infix.gns3a b/gns3server/appliances/infix.gns3a index 2f19f77da..d9ab0321f 100644 --- a/gns3server/appliances/infix.gns3a +++ b/gns3server/appliances/infix.gns3a @@ -2,13 +2,13 @@ "appliance_id": "4d351078-c6f5-444c-ab30-0ef20e3d8c53", "name": "Infix", "category": "router", - "description": "Infix is a Network Operating System based on Linux. It can be set up both as a switch, with offloading using switchdev, and a router with firewalling.", + "description": "Infix OS is a free Linux-based operating system with made-easy management using NETCONF, RESTCONF, or the built-in command line interface (CLI). It is suitable for both end-devices with a single Ethernet port and switches/routers with multiple ports. Immutable by design, extensions are possible using Docker containers.", "vendor_name": "KernelKit", "vendor_url": "https://github.com/kernelkit", "vendor_logo_url": "https://kernelkit.org/assets/img/jack.png", "product_name": "Infix", "registry_version": 4, - "documentation_url": "https://github.com/kernelkit/infix/tree/main/doc", + "documentation_url": "https://kernelkit.org/infix/latest/", "status": "stable", "availability": "free", "maintainer": "KernelKit", @@ -76,9 +76,79 @@ "md5sum": "84bd999513325d0007d0e6587abc6140", "version": "25.04.0", "direct_download_url": "https://github.com/kernelkit/infix/releases/download/v25.04.0/infix-x86_64-disk-25.04.0.qcow2" + }, + { + "filename": "infix-x86_64-disk-25.05.0.qcow2", + "filesize": 259958784, + "md5sum": "a6b1b3a6bccc60bb5214f2b864602fde", + "version": "25.05.0", + "direct_download_url": "https://github.com/kernelkit/infix/releases/download/v25.05.0/infix-x86_64-disk-25.05.0.qcow2" + }, + { + "filename": "infix-x86_64-disk-25.08.0.qcow2", + "filesize": 284453888, + "md5sum": "5fbf146d2ac73d1bd8fa1c509d6169b1", + "version": "25.08.0", + "direct_download_url": "https://github.com/kernelkit/infix/releases/download/v25.08.0/infix-x86_64-disk-25.08.0.qcow2" + }, + { + "filename": "infix-x86_64-disk-25.09.0.qcow2", + "filesize": 285120000, + "md5sum": "9761968406780a5b28311b8527f8629f", + "version": "25.09.0", + "direct_download_url": "https://github.com/kernelkit/infix/releases/download/v25.09.0/infix-x86_64-disk-25.09.0.qcow2" + }, + { + "filename": "infix-x86_64-disk-25.10.0.qcow2", + "filesize": 288818688, + "md5sum": "781d0fce9fbf789f6ea6ff10dc104afb", + "version": "25.10.0", + "direct_download_url": "https://github.com/kernelkit/infix/releases/download/v25.10.0/infix-x86_64-disk-25.10.0.qcow2" + }, + { + "filename": "infix-x86_64-disk-25.11.0.qcow2", + "filesize": 288930816, + "md5sum": "e2eb1a4fff9d56815f37c2e82a6279fb", + "version": "25.11.0", + "direct_download_url": "https://github.com/kernelkit/infix/releases/download/v25.11.0/infix-x86_64-disk-25.11.0.qcow2" } ], "versions": [ + { + "name": "25.11.0", + "images": { + "bios_image": "OVMF-edk2-stable202305.fd", + "hda_disk_image": "infix-x86_64-disk-25.11.0.qcow2" + } + }, + { + "name": "25.10.0", + "images": { + "bios_image": "OVMF-edk2-stable202305.fd", + "hda_disk_image": "infix-x86_64-disk-25.10.0.qcow2" + } + }, + { + "name": "25.09.0", + "images": { + "bios_image": "OVMF-edk2-stable202305.fd", + "hda_disk_image": "infix-x86_64-disk-25.09.0.qcow2" + } + }, + { + "name": "25.08.0", + "images": { + "bios_image": "OVMF-edk2-stable202305.fd", + "hda_disk_image": "infix-x86_64-disk-25.08.0.qcow2" + } + }, + { + "name": "25.05.0", + "images": { + "bios_image": "OVMF-edk2-stable202305.fd", + "hda_disk_image": "infix-x86_64-disk-25.05.0.qcow2" + } + }, { "name": "25.04.0", "images": { @@ -115,4 +185,4 @@ } } ] -} +} \ No newline at end of file diff --git a/gns3server/appliances/kali-linux.gns3a b/gns3server/appliances/kali-linux.gns3a index 5452ec058..60f742842 100644 --- a/gns3server/appliances/kali-linux.gns3a +++ b/gns3server/appliances/kali-linux.gns3a @@ -11,237 +11,34 @@ "status": "stable", "maintainer": "GNS3 Team", "maintainer_email": "developers@gns3.net", - "usage": "Default password is toor\nEnable persistence by selecting boot option 'Live USB Persistence'", + "usage": "Default username is kali and the default password is kali", "port_name_format": "eth{0}", "qemu": { "adapter_type": "e1000", "adapters": 8, - "ram": 1024, + "ram": 2048, + "cpus": 2, "hda_disk_interface": "ide", "arch": "x86_64", "console_type": "vnc", - "boot_priority": "d", "kvm": "require" }, "images": [ - { - "filename": "kali-linux-2021.1-live-amd64.iso", - "version": "2021.1", - "md5sum": "3a3716fef866e5c29a1c1ccfc94264b5", - "filesize": 3591385088, - "download_url": "http://cdimage.kali.org/kali-2021.1/", - "direct_download_url": "http://cdimage.kali.org/kali-2021.1/kali-linux-2021.1-live-amd64.iso" - }, - { - "filename": "kali-linux-2019.3-amd64.iso", - "version": "2019.3", - "md5sum": "9c6fb00558f78ed06992d89f745ef975", - "filesize": 3037736960, - "download_url": "http://old.kali.org/kali-images/kali-2019.3", - "direct_download_url": "http://old.kali.org/kali-images/kali-2019.3/kali-linux-2019.3-amd64.iso" - }, - { - "filename": "kali-linux-2019.2-amd64.iso", - "version": "2019.2", - "md5sum": "0f89b6225d7ea9c18682f7cc541c1179", - "filesize": 3353227264, - "download_url": "http://old.kali.org/kali-images/kali-2019.2", - "direct_download_url": "http://old.kali.org/kali-images/kali-2019.2/kali-linux-2019.2-amd64.iso" - }, - { - "filename": "kali-linux-mate-2019.2-amd64.iso", - "version": "2019.2 (MATE)", - "md5sum": "fec8dd7009f932c51a74323df965a709", - "filesize": 3313217536, - "download_url": "http://old.kali.org/kali-images/kali-2019.2", - "direct_download_url": "http://old.kali.org/kali-images/kali-2019.2/kali-linux-mate-2019.2-amd64.iso" - }, - { - "filename": "kali-linux-2019.1a-amd64.iso", - "version": "2019.1a", - "md5sum": "58c6111ed0be1919ea87267e7e65ab0f", - "filesize": 3483873280, - "download_url": "http://old.kali.org/kali-images/kali-2019.1a", - "direct_download_url": "http://old.kali.org/kali-images/kali-2019.1a/kali-linux-2019.1a-amd64.iso" - }, - { - "filename": "kali-linux-2018.4-amd64.iso", - "version": "2018.4", - "md5sum": "1b2d598bb8d2003e6207c119c0ba42fe", - "filesize": 3139436544, - "download_url": "http://old.kali.org/kali-images/kali-2018.4", - "direct_download_url": "http://old.kali.org/kali-images/kali-2018.4/kali-linux-2018.4-amd64.iso" - }, - { - "filename": "kali-linux-2018.3a-amd64.iso", - "version": "2018.3a", - "md5sum": "2da675d016bd690c05e180e33aa98b94", - "filesize": 3192651776, - "download_url": "http://old.kali.org/kali-images/kali-2018.3a", - "direct_download_url": "http://old.kali.org/kali-images/kali-2018.3a/kali-linux-2018.3a-amd64.iso" - }, - { - "filename": "kali-linux-2018.1-amd64.iso", - "version": "2018.1", - "md5sum": "a3feb90df5b71b3c7f4a02bdddf221d7", - "filesize": 3028500480, - "download_url": "http://old.kali.org/kali-images/kali-2018.1", - "direct_download_url": "http://old.kali.org/kali-images/kali-2018.1/kali-linux-2018.1-amd64.iso" - }, - { - "filename": "kali-linux-2017.3-amd64.iso", - "version": "2017.3", - "md5sum": "b465580c897e94675ac1daf031fa66b9", - "filesize": 2886402048, - "download_url": "http://old.kali.org/kali-images/kali-2017.3/", - "direct_download_url": "http://old.kali.org/kali-images/kali-2017.3/kali-linux-2017.3-amd64.iso" - }, - { - "filename": "kali-linux-2017.2-amd64.iso", - "version": "2017.2", - "md5sum": "541654f8f818450dc0db866a0a0f6eec", - "filesize": 3020619776, - "download_url": "http://old.kali.org/kali-images/kali-2017.2/", - "direct_download_url": "http://old.kali.org/kali-images/kali-2017.2/kali-linux-2017.2-amd64.iso" - }, - { - "filename": "kali-linux-2017.1-amd64.iso", - "version": "2017.1", - "md5sum": "c8e742283929d7a12dbe7c58e398ff08", - "filesize": 2794307584, - "download_url": "http://old.kali.org/kali-images/kali-2017.1/", - "direct_download_url": "http://old.kali.org/kali-images/kali-2017.1/kali-linux-2017.1-amd64.iso" - }, - { - "filename": "kali-linux-2016.2-amd64.iso", - "version": "2016.2", - "md5sum": "3d163746bc5148e61ad689d94bc263f9", - "filesize": 3076767744, - "download_url": "http://old.kali.org/kali-images/kali-2016.2/", - "direct_download_url": "http://old.kali.org/kali-images/kali-2016.2/kali-linux-2016.2-amd64.iso" - }, - { - "filename": "kali-linux-2016.1-amd64.iso", - "version": "2016.1", - "md5sum": "2e1230dc14036935b3279dfe3e49ad39", - "filesize": 2945482752, - "download_url": "http://old.kali.org/kali-images/kali-2016.1/", - "direct_download_url": "http://old.kali.org/kali-images/kali-2016.1/kali-linux-2016.1-amd64.iso" - }, - { - "filename": "kali-linux-2.0-amd64.iso", - "version": "2.0", - "md5sum": "ef192433017c5d99a156eaef51fd389d", - "filesize": 3320512512, - "download_url": "https://www.offensive-security.com/kali-linux-vmware-arm-image-download/", - "direct_download_url": "http://images.kali.org/Kali-Linux-2.0.0-vm-amd64.7z" - }, - { - "filename": "kali-linux-persistence-1gb.qcow2", - "version": "1.0", - "md5sum": "14e9c92f3ba5a0bd1128c1ea26a129ea", - "filesize": 34734080, - "download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/", - "direct_download_url": "https://sourceforge.net/projects/gns-3/files/Qemu%20Appliances/kali-linux-persistence-1gb.qcow2/download" + { + "filename": "kali-linux-2025.4-qemu-amd64.qcow2", + "version": "2025.4", + "md5sum": "a4be43351b5deb5b2823cb38a73b2095", + "filesize": 15719268352, + "download_url": "https://cdimage.kali.org/kali-2025.4/", + "direct_download_url": "https://cdimage.kali.org/kali-2025.4/kali-linux-2025.4-qemu-amd64.7z", + "compression": "7z" } ], "versions": [ { - "name": "2021.1", + "name": "2025.4", "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2021.1-live-amd64.iso" - } - }, - { - "name": "2019.3", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2019.3-amd64.iso" - } - }, - { - "name": "2019.2", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2019.2-amd64.iso" - } - }, - { - "name": "2019.2 (MATE)", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-mate-2019.2-amd64.iso" - } - }, - { - "name": "2019.1a", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2019.1a-amd64.iso" - } - }, - { - "name": "2018.4", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2018.4-amd64.iso" - } - }, - { - "name": "2018.3a", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2018.3a-amd64.iso" - } - }, - { - "name": "2018.1", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2018.1-amd64.iso" - } - }, - { - "name": "2017.3", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2017.3-amd64.iso" - } - }, - { - "name": "2017.2", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2017.2-amd64.iso" - } - }, - { - "name": "2017.1", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2017.1-amd64.iso" - } - }, - { - "name": "2016.2", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2016.2-amd64.iso" - } - }, - { - "name": "2016.1", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2016.1-amd64.iso" - } - }, - { - "name": "2.0", - "images": { - "hda_disk_image": "kali-linux-persistence-1gb.qcow2", - "cdrom_image": "kali-linux-2.0-amd64.iso" + "hda_disk_image": "kali-linux-2025.4-qemu-amd64.qcow2" } } ] diff --git a/gns3server/appliances/mikrotik-winbox-2026.gns3a b/gns3server/appliances/mikrotik-winbox-2026.gns3a new file mode 100644 index 000000000..7d0bc91ee --- /dev/null +++ b/gns3server/appliances/mikrotik-winbox-2026.gns3a @@ -0,0 +1,22 @@ +{ + "appliance_id": "1174e46d-4a29-4554-a1e8-71ed90682295", + "name": "MikroTik WinBox 2026", + "category": "guest", + "description": "Mikrotik's WinBox router management software for GNS3 2026", + "vendor_name": "MikroTik", + "vendor_url": "https://mikrotik.com", + "documentation_url": "https://mikrotik.com/winbox", + "product_name": "MikroTik WinBox", + "product_url": "https://mikrotik.com/winbox", + "registry_version": 4, + "status": "stable", + "availability": "free", + "maintainer": "h3ck13r", + "maintainer_email": "pisdushko1886@gmail.com", + "usage": "Connect WinBox to a MikroTik CHR port and start them both. Open WinBox console and wait until MikroTik appear in neighbors tab, provide credentials and connect.", + "docker": { + "adapters": 1, + "image": "snatao808/winbox-mikrotik-2026", + "console_type": "vnc" + } +} diff --git a/gns3server/appliances/vyos.gns3a b/gns3server/appliances/vyos.gns3a index 3255a80e0..10bf9ae4c 100644 --- a/gns3server/appliances/vyos.gns3a +++ b/gns3server/appliances/vyos.gns3a @@ -30,6 +30,13 @@ "on_close": "shutdown_signal" }, "images": [ + { + "filename": "vyos-1.4.4-kvm-amd64.qcow2", + "version": "1.4.4", + "md5sum": "942dae45d63924b58b65d069890765d4", + "filesize": 518782976, + "download_url": "https://support.vyos.io/" + }, { "filename": "vyos-1.4.3-kvm-amd64.qcow2", "version": "1.4.3", @@ -130,6 +137,12 @@ } ], "versions": [ + { + "name": "1.4.4", + "images": { + "hda_disk_image": "vyos-1.4.4-kvm-amd64.qcow2" + } + }, { "name": "1.4.3", "images": { diff --git a/gns3server/compute/docker/resources/etc/udhcpc/default.script b/gns3server/compute/docker/resources/etc/udhcpc/default.script index 404fb190a..873642c47 100755 --- a/gns3server/compute/docker/resources/etc/udhcpc/default.script +++ b/gns3server/compute/docker/resources/etc/udhcpc/default.script @@ -3,7 +3,12 @@ # script for udhcpc # Copyright (c) 2008 Natanael Copa -UDHCPC="/gns3/etc/udhcpc" +if [ -d /etc/network ]; then + UDHCPC="/etc/network/udhcpc" +else + UDHCPC="/gns3/etc/udhcpc" +fi + UDHCPC_CONF="$UDHCPC/udhcpc.conf" RESOLV_CONF="/etc/resolv.conf" diff --git a/gns3server/utils/asyncio/__init__.py b/gns3server/utils/asyncio/__init__.py index 9b14e17e7..131145eb9 100644 --- a/gns3server/utils/asyncio/__init__.py +++ b/gns3server/utils/asyncio/__init__.py @@ -90,9 +90,6 @@ async def wait_for_process_termination(process, timeout=10): In theory this can be implemented by just: await asyncio.wait_for(self._iou_process.wait(), timeout=100) - But it's broken before Python 3.4: - http://bugs.python.org/issue23140 - :param process: An asyncio subprocess :param timeout: Timeout in seconds """ diff --git a/requirements.txt b/requirements.txt index f5e25b92e..d87796e10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,13 +3,12 @@ pydantic==2.11.7 fastapi==0.116.1 python-multipart==0.0.20 websockets==15.0.1 -aiohttp>=3.11.16,<3.12 -async-timeout==5.0.1; python_version < '3.11' -aiofiles>=24.1.0,<25.0 +aiohttp>=3.13.3,<3.14 +aiofiles>=25.1.0,<26.0 Jinja2>=3.1.6,<3.2 -sentry-sdk>=2.44.0,<2.45 # optional dependency -psutil>=7.1.3 -async-timeout>=5.0.1,<5.1 +sentry-sdk>=2.50.0,<3 # optional dependency +psutil>=7.2.1 +async-timeout>=5.0.1,<5.1; python_version < '3.11' # this library has effectively been upstreamed into Python 3.11+ distro>=1.9.0 py-cpuinfo>=9.0.0,<10.0 greenlet==3.2.0 # necessary to run sqlalchemy on Python 3.13 @@ -22,5 +21,4 @@ email-validator==2.2.0 watchdog==6.0.0 zstandard==0.23.0 platformdirs>=2.4.0,<3 # platformdirs >=3 conflicts when building Debian packages -importlib-resources>=1.3; python_version <= '3.9' -truststore>=0.10.1; python_version >= '3.10' +truststore>=0.10.4; python_version >= '3.10' diff --git a/scripts/random_query.py b/scripts/random_query.py deleted file mode 100644 index f5e7de2a9..000000000 --- a/scripts/random_query.py +++ /dev/null @@ -1,238 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2016 GNS3 Technologies Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -""" -This script connect to the local GNS3 server and will create a random topology -""" - -import sys -import json -import math -import aiohttp -import aiohttp.web -import asyncio -import random - -import coloredlogs -import logging - -coloredlogs.install(fmt=" %(asctime)s %(levelname)s %(message)s") -log = logging.getLogger(__name__) - -PROJECT_ID = "9e26e37d-4962-4921-8c0e-136d3b04ba9c" -HOST = "192.168.84.151:3080" - -# Use for node names uniqueness -node_i = 1 - - -def die(*args): - log.error(*args) - sys.exit(1) - - -class HTTPError(Exception): - - def __init__(self, method, path, response): - self._method = method - self._path = path - self._response = response - - @property - def response(self): - return self._response - - @property - def path(self): - return self._path - - @property - def method(self): - return self._method - - -class HTTPConflict(HTTPError): - pass - - -class HTTPNotFound(HTTPError): - pass - - -async def query(method, path, body=None, **kwargs): - global session - - if body: - kwargs["data"] = json.dumps(body) - - async with session.request(method, "http://" + HOST + "/v2" + path, **kwargs) as response: - if response.status == 409: - raise HTTPConflict(method, path, response) - elif response.status == 404: - raise HTTPNotFound(method, path, response) - elif response.status >= 300: - raise HTTPError(method, path, response) - log.info("%s %s %d", method, path, response.status) - if response.headers["content-type"] == "application/json": - return await response.json() - else: - return "{}" - - -async def post(path, **kwargs): - return await query("POST", path, **kwargs) - - -async def get(path, **kwargs): - return await query("GET", path, **kwargs) - - -async def delete(path, **kwargs): - return await query("DELETE", path, **kwargs) - - -async def create_project(): - # Delete project if already exists - response = await get("/projects") - project_exists = False - for project in response: - if project["name"] == "random" and project["project_id"] != PROJECT_ID: - await delete("/projects/" + project["project_id"]) - elif project["project_id"] == PROJECT_ID: - project_exists = True - tasks = [] - for node in await get("/projects/" + PROJECT_ID + "/nodes"): - tasks.append(delete_node(project, node)) - await asyncio.gather(*tasks) - if project_exists: - response = await post("/projects/" + PROJECT_ID + "/open") - else: - response = await post("/projects", body={"name": "random", "project_id": PROJECT_ID, "auto_close": False}) - return response - - -async def create_node(project): - global node_i - - r = random.randint(0, 1) - - if r == 0: - node_type = "ethernet_switch" - symbol = ":/symbols/ethernet_switch.svg" - elif r == 1: - node_type = "vpcs" - symbol = ":/symbols/vpcs_guest.svg" - response = await post("/projects/{}/nodes".format(project["project_id"]), body={ - "node_type": node_type, - "compute_id": "local", - "symbol": symbol, - "name": "Node{}".format(node_i), - "x": (math.floor((node_i - 1) % 12.0) * 100) - 500, - "y": (math.ceil((node_i) / 12.0) * 100) - 300 - }) - node_i += 1 - return response - - -async def delete_node(project, node): - await delete("/projects/{}/nodes/{}".format(project["project_id"], node["node_id"])) - - -async def create_link(project, nodes): - """ - Create all possible link of a node - """ - node1 = random.choice(list(nodes.values())) - - for port in range(0, 8): - node2 = random.choice(list(nodes.values())) - - if node1 == node2: - continue - - data = {"nodes": - [ - { - "adapter_number": 0, - "node_id": node1["node_id"], - "port_number": port - }, - { - "adapter_number": 0, - "node_id": node2["node_id"], - "port_number": port - } - ] - } - try: - await post("/projects/{}/links".format(project["project_id"]), body=data) - except (HTTPConflict, HTTPNotFound): - pass - - -async def build_topology(): - global node_i - - nodes = {} - project = await create_project() - while True: - rand = random.randint(0, 1000) - if rand < 500: # chance to create a new node - if len(nodes.keys()) < 255: # Limit of VPCS: - node = await create_node(project) - nodes[node["node_id"]] = node - elif rand < 600: # start all nodes - await post("/projects/{}/nodes/start".format(project["project_id"])) - elif rand < 700: # stop all nodes - await post("/projects/{}/nodes/stop".format(project["project_id"])) - elif rand < 950: # create a link - if len(nodes.keys()) >= 2: - await create_link(project, nodes) - elif rand < 999: # chance to delete a node - continue - if len(nodes.keys()) > 0: - node = random.choice(list(nodes.values())) - await delete_node(project, node) - del nodes[node["node_id"]] - elif len(nodes.keys()) > 0: # % chance to delete all nodes - continue - node_i = 1 - tasks = [] - for node in nodes.values(): - tasks.append(delete_node(project, node)) - await asyncio.gather(*tasks) - nodes = {} - await asyncio.sleep(0.2) - -async def main(loop): - global session - async with aiohttp.ClientSession() as session: - try: - await build_topology() - except HTTPError as error: - try: - j = await error.response.json() - die("%s %s invalid status %d:\n%s", error.method, error.path, error.response.status, json.dumps(j, indent=4)) - except (ValueError, aiohttp.ServerDisconnectedError): - die("%s %s invalid status %d", error.method, error.path, error.response.status) - - -loop = asyncio.get_event_loop() -loop.run_until_complete(main(loop)) - -if session: - session.close() diff --git a/win-requirements.txt b/win-requirements.txt index 784162589..1cc7ba1e2 100644 --- a/win-requirements.txt +++ b/win-requirements.txt @@ -1,4 +1,4 @@ -r requirements.txt -pywin32==306 +pywin32==311 wmi==1.5.1