gns3-server 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of gns3-server might be problematic. Click here for more details.
- gns3_server-3.0.0.dist-info/LICENSE +674 -0
- gns3_server-3.0.0.dist-info/METADATA +868 -0
- gns3_server-3.0.0.dist-info/RECORD +1251 -0
- gns3_server-3.0.0.dist-info/WHEEL +5 -0
- gns3_server-3.0.0.dist-info/entry_points.txt +3 -0
- gns3_server-3.0.0.dist-info/top_level.txt +1 -0
- gns3server/__init__.py +17 -0
- gns3server/__main__.py +20 -0
- gns3server/alembic.ini +103 -0
- gns3server/api/__init__.py +0 -0
- gns3server/api/routes/__init__.py +0 -0
- gns3server/api/routes/compute/__init__.py +267 -0
- gns3server/api/routes/compute/atm_switch_nodes.py +233 -0
- gns3server/api/routes/compute/capabilities.py +51 -0
- gns3server/api/routes/compute/cloud_nodes.py +249 -0
- gns3server/api/routes/compute/compute.py +143 -0
- gns3server/api/routes/compute/dependencies/__init__.py +0 -0
- gns3server/api/routes/compute/dependencies/authentication.py +83 -0
- gns3server/api/routes/compute/docker_nodes.py +393 -0
- gns3server/api/routes/compute/dynamips_nodes.py +367 -0
- gns3server/api/routes/compute/ethernet_hub_nodes.py +236 -0
- gns3server/api/routes/compute/ethernet_switch_nodes.py +246 -0
- gns3server/api/routes/compute/frame_relay_switch_nodes.py +240 -0
- gns3server/api/routes/compute/images.py +156 -0
- gns3server/api/routes/compute/iou_nodes.py +344 -0
- gns3server/api/routes/compute/nat_nodes.py +244 -0
- gns3server/api/routes/compute/notifications.py +88 -0
- gns3server/api/routes/compute/projects.py +243 -0
- gns3server/api/routes/compute/qemu_nodes.py +412 -0
- gns3server/api/routes/compute/virtualbox_nodes.py +377 -0
- gns3server/api/routes/compute/vmware_nodes.py +355 -0
- gns3server/api/routes/compute/vpcs_nodes.py +343 -0
- gns3server/api/routes/controller/__init__.py +147 -0
- gns3server/api/routes/controller/acl.py +268 -0
- gns3server/api/routes/controller/appliances.py +150 -0
- gns3server/api/routes/controller/computes.py +231 -0
- gns3server/api/routes/controller/controller.py +319 -0
- gns3server/api/routes/controller/dependencies/__init__.py +0 -0
- gns3server/api/routes/controller/dependencies/authentication.py +117 -0
- gns3server/api/routes/controller/dependencies/database.py +38 -0
- gns3server/api/routes/controller/dependencies/rbac.py +78 -0
- gns3server/api/routes/controller/drawings.py +131 -0
- gns3server/api/routes/controller/gns3vm.py +71 -0
- gns3server/api/routes/controller/groups.py +231 -0
- gns3server/api/routes/controller/images.py +255 -0
- gns3server/api/routes/controller/links.py +287 -0
- gns3server/api/routes/controller/nodes.py +619 -0
- gns3server/api/routes/controller/pools.py +239 -0
- gns3server/api/routes/controller/privileges.py +43 -0
- gns3server/api/routes/controller/projects.py +595 -0
- gns3server/api/routes/controller/roles.py +224 -0
- gns3server/api/routes/controller/snapshots.py +124 -0
- gns3server/api/routes/controller/symbols.py +133 -0
- gns3server/api/routes/controller/templates.py +192 -0
- gns3server/api/routes/controller/users.py +254 -0
- gns3server/api/routes/index.py +93 -0
- gns3server/api/server.py +224 -0
- gns3server/appliances/6wind-turbo-router.gns3a +47 -0
- gns3server/appliances/IPCop.gns3a +52 -0
- gns3server/appliances/a10-vthunder.gns3a +72 -0
- gns3server/appliances/aaa.gns3a +20 -0
- gns3server/appliances/alcatel-7750.gns3a +74 -0
- gns3server/appliances/almalinux.gns3a +84 -0
- gns3server/appliances/alpine-linux-virt.gns3a +59 -0
- gns3server/appliances/alpine-linux.gns3a +21 -0
- gns3server/appliances/arista-ceos.gns3a +20 -0
- gns3server/appliances/arista-veos.gns3a +577 -0
- gns3server/appliances/aruba-arubaoscx.gns3a +233 -0
- gns3server/appliances/aruba-vgw.gns3a +60 -0
- gns3server/appliances/aruba-vmc.gns3a +56 -0
- gns3server/appliances/asterfusion-vAsterNOS.gns3a +49 -0
- gns3server/appliances/asterisk.gns3a +114 -0
- gns3server/appliances/bigswitch-bigcloud-fabric.gns3a +42 -0
- gns3server/appliances/bird.gns3a +42 -0
- gns3server/appliances/bird2.gns3a +57 -0
- gns3server/appliances/brocade-vadx.gns3a +43 -0
- gns3server/appliances/brocade-vrouter.gns3a +138 -0
- gns3server/appliances/brocade-vtm.gns3a +136 -0
- gns3server/appliances/bsdrp.gns3a +117 -0
- gns3server/appliances/centos-cloud.gns3a +115 -0
- gns3server/appliances/centos7.gns3a +72 -0
- gns3server/appliances/checkpoint-gaia.gns3a +81 -0
- gns3server/appliances/chromium.gns3a +19 -0
- gns3server/appliances/cisco-1700.gns3a +39 -0
- gns3server/appliances/cisco-2600.gns3a +38 -0
- gns3server/appliances/cisco-2691.gns3a +38 -0
- gns3server/appliances/cisco-3620.gns3a +38 -0
- gns3server/appliances/cisco-3640.gns3a +38 -0
- gns3server/appliances/cisco-3660.gns3a +38 -0
- gns3server/appliances/cisco-3725.gns3a +38 -0
- gns3server/appliances/cisco-3745.gns3a +45 -0
- gns3server/appliances/cisco-7200.gns3a +92 -0
- gns3server/appliances/cisco-asa.gns3a +86 -0
- gns3server/appliances/cisco-asav.gns3a +227 -0
- gns3server/appliances/cisco-c8000v.gns3a +108 -0
- gns3server/appliances/cisco-cat9k.gns3a +58 -0
- gns3server/appliances/cisco-csr1000v.gns3a +316 -0
- gns3server/appliances/cisco-dcnm.gns3a +96 -0
- gns3server/appliances/cisco-fcnf.gns3a +71 -0
- gns3server/appliances/cisco-fmcv.gns3a +139 -0
- gns3server/appliances/cisco-fsve.gns3a +57 -0
- gns3server/appliances/cisco-ftdv.gns3a +99 -0
- gns3server/appliances/cisco-iosv.gns3a +178 -0
- gns3server/appliances/cisco-iosvl2.gns3a +95 -0
- gns3server/appliances/cisco-iosxrv.gns3a +57 -0
- gns3server/appliances/cisco-iosxrv9k.gns3a +188 -0
- gns3server/appliances/cisco-iou-l2.gns3a +84 -0
- gns3server/appliances/cisco-iou-l3.gns3a +84 -0
- gns3server/appliances/cisco-ise.gns3a +154 -0
- gns3server/appliances/cisco-ngipsv.gns3a +73 -0
- gns3server/appliances/cisco-nxosv.gns3a +56 -0
- gns3server/appliances/cisco-nxosv9k.gns3a +433 -0
- gns3server/appliances/cisco-pyats.gns3a +19 -0
- gns3server/appliances/cisco-smc.gns3a +71 -0
- gns3server/appliances/cisco-vWLC.gns3a +140 -0
- gns3server/appliances/cisco-wsav.gns3a +44 -0
- gns3server/appliances/citrix-netscaler-vpx.gns3a +72 -0
- gns3server/appliances/citrix-sd-wan.gns3a +46 -0
- gns3server/appliances/citrix-sdwan-center.gns3a +46 -0
- gns3server/appliances/clavister-netsheild.gns3a +59 -0
- gns3server/appliances/clavister-netwall.gns3a +71 -0
- gns3server/appliances/clearos.gns3a +107 -0
- gns3server/appliances/cloudrouter.gns3a +72 -0
- gns3server/appliances/coreos.gns3a +329 -0
- gns3server/appliances/cumulus-vx.gns3a +440 -0
- gns3server/appliances/danos.gns3a +57 -0
- gns3server/appliances/debian.gns3a +85 -0
- gns3server/appliances/deft-linux.gns3a +96 -0
- gns3server/appliances/dell-ftos.gns3a +71 -0
- gns3server/appliances/dns.gns3a +20 -0
- gns3server/appliances/empty-vm.gns3a +199 -0
- gns3server/appliances/endhost.gns3a +17 -0
- gns3server/appliances/exos.gns3a +51 -0
- gns3server/appliances/extreme-networks-voss.gns3a +152 -0
- gns3server/appliances/f5-bigip.gns3a +322 -0
- gns3server/appliances/f5-bigiq.gns3a +165 -0
- gns3server/appliances/fedora-cloud.gns3a +70 -0
- gns3server/appliances/firefox.gns3a +59 -0
- gns3server/appliances/fortiadc-manager.gns3a +54 -0
- gns3server/appliances/fortiadc.gns3a +502 -0
- gns3server/appliances/fortianalyzer.gns3a +519 -0
- gns3server/appliances/fortiauthenticator.gns3a +251 -0
- gns3server/appliances/forticache.gns3a +210 -0
- gns3server/appliances/fortigate.gns3a +742 -0
- gns3server/appliances/fortimail.gns3a +392 -0
- gns3server/appliances/fortimanager.gns3a +519 -0
- gns3server/appliances/fortiproxy.gns3a +83 -0
- gns3server/appliances/fortirecorder.gns3a +69 -0
- gns3server/appliances/fortisandbox.gns3a +210 -0
- gns3server/appliances/fortisiem-super_worker.gns3a +210 -0
- gns3server/appliances/fortiweb.gns3a +308 -0
- gns3server/appliances/freeRouter.gns3a +44 -0
- gns3server/appliances/freebsd.gns3a +75 -0
- gns3server/appliances/freenas.gns3a +183 -0
- gns3server/appliances/frr.gns3a +84 -0
- gns3server/appliances/haproxy.gns3a +18 -0
- gns3server/appliances/hbcd-pe.gns3a +62 -0
- gns3server/appliances/hp-vsr1001.gns3a +149 -0
- gns3server/appliances/huawei-ar1kv.gns3a +58 -0
- gns3server/appliances/huawei-ce12800.gns3a +43 -0
- gns3server/appliances/huawei-ne40e.gns3a +94 -0
- gns3server/appliances/huawei-usg6kv.gns3a +50 -0
- gns3server/appliances/innovaphone-app.gns3a +50 -0
- gns3server/appliances/innovaphone-ipva.gns3a +78 -0
- gns3server/appliances/ipfire.gns3a +181 -0
- gns3server/appliances/ipterm.gns3a +19 -0
- gns3server/appliances/ipxe.gns3a +47 -0
- gns3server/appliances/juniper-junos-space.gns3a +46 -0
- gns3server/appliances/juniper-vmx-legacy.gns3a +55 -0
- gns3server/appliances/juniper-vmx-vcp.gns3a +520 -0
- gns3server/appliances/juniper-vmx-vfp.gns3a +281 -0
- gns3server/appliances/juniper-vqfx-pfe.gns3a +71 -0
- gns3server/appliances/juniper-vqfx-re.gns3a +85 -0
- gns3server/appliances/juniper-vrr.gns3a +66 -0
- gns3server/appliances/juniper-vsrx.gns3a +332 -0
- gns3server/appliances/jupyter.gns3a +20 -0
- gns3server/appliances/jupyter27.gns3a +20 -0
- gns3server/appliances/kali-linux-cli.gns3a +18 -0
- gns3server/appliances/kali-linux.gns3a +248 -0
- gns3server/appliances/kemp-vlm.gns3a +111 -0
- gns3server/appliances/kerio-connect.gns3a +131 -0
- gns3server/appliances/kerio-control.gns3a +143 -0
- gns3server/appliances/kerio-operator.gns3a +130 -0
- gns3server/appliances/lancom-vrouter.gns3a +45 -0
- gns3server/appliances/loadbalancer_org-va.gns3a +56 -0
- gns3server/appliances/macos-install.gns3a +72 -0
- gns3server/appliances/mcjoin.gns3a +19 -0
- gns3server/appliances/microcore-linux.gns3a +72 -0
- gns3server/appliances/mikrotik-ccr1036-8g-2s+.gns3a +165 -0
- gns3server/appliances/mikrotik-ccr1072-1g-8s+.gns3a +161 -0
- gns3server/appliances/mikrotik-chr.gns3a +108 -0
- gns3server/appliances/mikrotik-crs328-24p-4s+.gns3a +173 -0
- gns3server/appliances/mikrotik-crs328-4c-20s-4s+.gns3a +189 -0
- gns3server/appliances/mikrotik-rb1100ahx4-dude-edition.gns3a +155 -0
- gns3server/appliances/mikrotik-rb2011uias.gns3a +161 -0
- gns3server/appliances/mikrotik-rb3011uias.gns3a +161 -0
- gns3server/appliances/mikrotik-rb4011igs+.gns3a +161 -0
- gns3server/appliances/mikrotik-rb450g.gns3a +155 -0
- gns3server/appliances/mikrotik-rb450gx4.gns3a +155 -0
- gns3server/appliances/mikrotik-winbox.gns3a +19 -0
- gns3server/appliances/mininet.gns3a +47 -0
- gns3server/appliances/net_toolbox.gns3a +20 -0
- gns3server/appliances/netapp-ontapsim.gns3a +185 -0
- gns3server/appliances/netem.gns3a +44 -0
- gns3server/appliances/network_automation.gns3a +19 -0
- gns3server/appliances/nixos.gns3a +52 -0
- gns3server/appliances/nokia-vsim.gns3a +47 -0
- gns3server/appliances/ntopng.gns3a +24 -0
- gns3server/appliances/onos.gns3a +19 -0
- gns3server/appliances/op5-monitor.gns3a +72 -0
- gns3server/appliances/open-media-vault.gns3a +120 -0
- gns3server/appliances/openbsd.gns3a +44 -0
- gns3server/appliances/opennac.gns3a +45 -0
- gns3server/appliances/opensuse.gns3a +47 -0
- gns3server/appliances/openvswitch-management.gns3a +21 -0
- gns3server/appliances/openvswitch.gns3a +21 -0
- gns3server/appliances/openwrt-realview.gns3a +56 -0
- gns3server/appliances/openwrt.gns3a +359 -0
- gns3server/appliances/opnsense.gns3a +122 -0
- gns3server/appliances/oracle-linux-cloud.gns3a +115 -0
- gns3server/appliances/ostinato-wireshark.gns3a +20 -0
- gns3server/appliances/ostinato.gns3a +75 -0
- gns3server/appliances/ovs-snmp.gns3a +18 -0
- gns3server/appliances/packetfence-zen.gns3a +151 -0
- gns3server/appliances/pan-vm-fw.gns3a +241 -0
- gns3server/appliances/parrot-os.gns3a +68 -0
- gns3server/appliances/pfsense.gns3a +122 -0
- gns3server/appliances/proxmox-mg.gns3a +69 -0
- gns3server/appliances/puppy-linux.gns3a +82 -0
- gns3server/appliances/python-go-perl-php.gns3a +17 -0
- gns3server/appliances/raspian.gns3a +79 -0
- gns3server/appliances/reactos.gns3a +67 -0
- gns3server/appliances/rhel.gns3a +207 -0
- gns3server/appliances/riverbed-steelhead-ng-vcx.gns3a +68 -0
- gns3server/appliances/rockylinux.gns3a +100 -0
- gns3server/appliances/security-onion.gns3a +108 -0
- gns3server/appliances/smoothwall.gns3a +54 -0
- gns3server/appliances/sophos-iview.gns3a +66 -0
- gns3server/appliances/sophos-utm.gns3a +263 -0
- gns3server/appliances/sophos-xg.gns3a +198 -0
- gns3server/appliances/stonework.gns3a +21 -0
- gns3server/appliances/tacacs-gui.gns3a +57 -0
- gns3server/appliances/tinycore-linux.gns3a +73 -0
- gns3server/appliances/trendmicro-imsva.gns3a +54 -0
- gns3server/appliances/trendmicro-iwsva.gns3a +53 -0
- gns3server/appliances/truenas.gns3a +104 -0
- gns3server/appliances/turnkey-wordpress.gns3a +20 -0
- gns3server/appliances/ubuntu-cloud.gns3a +116 -0
- gns3server/appliances/ubuntu-docker.gns3a +20 -0
- gns3server/appliances/ubuntu-gui.gns3a +98 -0
- gns3server/appliances/untangle.gns3a +208 -0
- gns3server/appliances/viptela-edge-genericx86-64.gns3a +84 -0
- gns3server/appliances/viptela-smart-genericx86-64.gns3a +82 -0
- gns3server/appliances/viptela-vmanage-genericx86-64.gns3a +95 -0
- gns3server/appliances/vpp.gns3a +45 -0
- gns3server/appliances/vrin.gns3a +118 -0
- gns3server/appliances/vyos.gns3a +179 -0
- gns3server/appliances/watchguard-fireboxv.gns3a +45 -0
- gns3server/appliances/watchguard-xtmv.gns3a +45 -0
- gns3server/appliances/webterm.gns3a +20 -0
- gns3server/appliances/windows-11-dev-env.gns3a +74 -0
- gns3server/appliances/windows-xp+ie.gns3a +52 -0
- gns3server/appliances/windows.gns3a +125 -0
- gns3server/appliances/windows_server.gns3a +83 -0
- gns3server/appliances/zentyal-server.gns3a +159 -0
- gns3server/appliances/zeroshell.gns3a +103 -0
- gns3server/compute/__init__.py +38 -0
- gns3server/compute/adapters/__init__.py +0 -0
- gns3server/compute/adapters/adapter.py +104 -0
- gns3server/compute/adapters/ethernet_adapter.py +33 -0
- gns3server/compute/adapters/serial_adapter.py +32 -0
- gns3server/compute/base_manager.py +547 -0
- gns3server/compute/base_node.py +979 -0
- gns3server/compute/builtin/__init__.py +46 -0
- gns3server/compute/builtin/builtin_node_factory.py +42 -0
- gns3server/compute/builtin/nodes/__init__.py +0 -0
- gns3server/compute/builtin/nodes/cloud.py +548 -0
- gns3server/compute/builtin/nodes/ethernet_hub.py +104 -0
- gns3server/compute/builtin/nodes/ethernet_switch.py +104 -0
- gns3server/compute/builtin/nodes/nat.py +97 -0
- gns3server/compute/compute_error.py +48 -0
- gns3server/compute/docker/__init__.py +320 -0
- gns3server/compute/docker/docker_error.py +33 -0
- gns3server/compute/docker/docker_vm.py +1378 -0
- gns3server/compute/docker/resources/bin/udhcpc +15 -0
- gns3server/compute/docker/resources/etc/udhcpc/default.script +138 -0
- gns3server/compute/docker/resources/init.sh +102 -0
- gns3server/compute/docker/resources/run-cmd.sh +6 -0
- gns3server/compute/dynamips/__init__.py +661 -0
- gns3server/compute/dynamips/adapters/__init__.py +0 -0
- gns3server/compute/dynamips/adapters/adapter.py +165 -0
- gns3server/compute/dynamips/adapters/c1700_mb_1fe.py +36 -0
- gns3server/compute/dynamips/adapters/c1700_mb_wic1.py +37 -0
- gns3server/compute/dynamips/adapters/c2600_mb_1e.py +36 -0
- gns3server/compute/dynamips/adapters/c2600_mb_1fe.py +37 -0
- gns3server/compute/dynamips/adapters/c2600_mb_2e.py +36 -0
- gns3server/compute/dynamips/adapters/c2600_mb_2fe.py +36 -0
- gns3server/compute/dynamips/adapters/c7200_io_2fe.py +36 -0
- gns3server/compute/dynamips/adapters/c7200_io_fe.py +36 -0
- gns3server/compute/dynamips/adapters/c7200_io_ge_e.py +36 -0
- gns3server/compute/dynamips/adapters/gt96100_fe.py +31 -0
- gns3server/compute/dynamips/adapters/leopard_2fe.py +37 -0
- gns3server/compute/dynamips/adapters/nm_16esw.py +32 -0
- gns3server/compute/dynamips/adapters/nm_1e.py +32 -0
- gns3server/compute/dynamips/adapters/nm_1fe_tx.py +32 -0
- gns3server/compute/dynamips/adapters/nm_4e.py +32 -0
- gns3server/compute/dynamips/adapters/nm_4t.py +32 -0
- gns3server/compute/dynamips/adapters/pa_2fe_tx.py +32 -0
- gns3server/compute/dynamips/adapters/pa_4e.py +32 -0
- gns3server/compute/dynamips/adapters/pa_4t.py +32 -0
- gns3server/compute/dynamips/adapters/pa_8e.py +32 -0
- gns3server/compute/dynamips/adapters/pa_8t.py +32 -0
- gns3server/compute/dynamips/adapters/pa_a1.py +32 -0
- gns3server/compute/dynamips/adapters/pa_fe_tx.py +32 -0
- gns3server/compute/dynamips/adapters/pa_ge.py +32 -0
- gns3server/compute/dynamips/adapters/pa_pos_oc3.py +32 -0
- gns3server/compute/dynamips/adapters/wic_1enet.py +40 -0
- gns3server/compute/dynamips/adapters/wic_1t.py +40 -0
- gns3server/compute/dynamips/adapters/wic_2t.py +40 -0
- gns3server/compute/dynamips/dynamips_error.py +26 -0
- gns3server/compute/dynamips/dynamips_factory.py +71 -0
- gns3server/compute/dynamips/dynamips_hypervisor.py +333 -0
- gns3server/compute/dynamips/hypervisor.py +210 -0
- gns3server/compute/dynamips/nios/__init__.py +0 -0
- gns3server/compute/dynamips/nios/nio.py +352 -0
- gns3server/compute/dynamips/nios/nio_generic_ethernet.py +73 -0
- gns3server/compute/dynamips/nios/nio_linux_ethernet.py +72 -0
- gns3server/compute/dynamips/nios/nio_null.py +51 -0
- gns3server/compute/dynamips/nios/nio_tap.py +66 -0
- gns3server/compute/dynamips/nios/nio_udp.py +136 -0
- gns3server/compute/dynamips/nios/nio_unix.py +88 -0
- gns3server/compute/dynamips/nios/nio_vde.py +88 -0
- gns3server/compute/dynamips/nodes/__init__.py +0 -0
- gns3server/compute/dynamips/nodes/atm_switch.py +514 -0
- gns3server/compute/dynamips/nodes/bridge.py +107 -0
- gns3server/compute/dynamips/nodes/c1700.py +160 -0
- gns3server/compute/dynamips/nodes/c2600.py +171 -0
- gns3server/compute/dynamips/nodes/c2691.py +112 -0
- gns3server/compute/dynamips/nodes/c3600.py +155 -0
- gns3server/compute/dynamips/nodes/c3725.py +112 -0
- gns3server/compute/dynamips/nodes/c3745.py +112 -0
- gns3server/compute/dynamips/nodes/c7200.py +268 -0
- gns3server/compute/dynamips/nodes/device.py +134 -0
- gns3server/compute/dynamips/nodes/ethernet_hub.py +241 -0
- gns3server/compute/dynamips/nodes/ethernet_switch.py +496 -0
- gns3server/compute/dynamips/nodes/frame_relay_switch.py +379 -0
- gns3server/compute/dynamips/nodes/router.py +1797 -0
- gns3server/compute/error.py +40 -0
- gns3server/compute/iou/__init__.py +64 -0
- gns3server/compute/iou/iou_error.py +25 -0
- gns3server/compute/iou/iou_vm.py +1482 -0
- gns3server/compute/iou/utils/__init__.py +0 -0
- gns3server/compute/iou/utils/iou_export.py +233 -0
- gns3server/compute/iou/utils/iou_import.py +232 -0
- gns3server/compute/nios/__init__.py +0 -0
- gns3server/compute/nios/nio.py +120 -0
- gns3server/compute/nios/nio_ethernet.py +56 -0
- gns3server/compute/nios/nio_tap.py +56 -0
- gns3server/compute/nios/nio_udp.py +82 -0
- gns3server/compute/notification_manager.py +73 -0
- gns3server/compute/port_manager.py +402 -0
- gns3server/compute/project.py +434 -0
- gns3server/compute/project_manager.py +122 -0
- gns3server/compute/qemu/__init__.py +304 -0
- gns3server/compute/qemu/qemu_error.py +26 -0
- gns3server/compute/qemu/qemu_vm.py +2697 -0
- gns3server/compute/qemu/resources/config.img.zip +0 -0
- gns3server/compute/qemu/utils/__init__.py +0 -0
- gns3server/compute/qemu/utils/guest_cid.py +38 -0
- gns3server/compute/qemu/utils/qcow2.py +138 -0
- gns3server/compute/qemu/utils/ziputils.py +55 -0
- gns3server/compute/ubridge/__init__.py +0 -0
- gns3server/compute/ubridge/hypervisor.py +256 -0
- gns3server/compute/ubridge/ubridge_error.py +32 -0
- gns3server/compute/ubridge/ubridge_hypervisor.py +285 -0
- gns3server/compute/virtualbox/__init__.py +212 -0
- gns3server/compute/virtualbox/virtualbox_error.py +26 -0
- gns3server/compute/virtualbox/virtualbox_vm.py +1255 -0
- gns3server/compute/vmware/__init__.py +725 -0
- gns3server/compute/vmware/vmware_error.py +26 -0
- gns3server/compute/vmware/vmware_vm.py +1007 -0
- gns3server/compute/vpcs/__init__.py +91 -0
- gns3server/compute/vpcs/vpcs_error.py +26 -0
- gns3server/compute/vpcs/vpcs_vm.py +595 -0
- gns3server/config.py +284 -0
- gns3server/config_samples/gns3_server.conf +160 -0
- gns3server/configs/ios_base_startup-config.txt +26 -0
- gns3server/configs/ios_etherswitch_startup-config.txt +181 -0
- gns3server/configs/iou_l2_base_startup-config.txt +133 -0
- gns3server/configs/iou_l3_base_startup-config.txt +109 -0
- gns3server/configs/vpcs_base_config.txt +9 -0
- gns3server/controller/__init__.py +691 -0
- gns3server/controller/appliance.py +86 -0
- gns3server/controller/appliance_manager.py +486 -0
- gns3server/controller/appliance_to_template.py +132 -0
- gns3server/controller/compute.py +677 -0
- gns3server/controller/controller_error.py +77 -0
- gns3server/controller/drawing.py +229 -0
- gns3server/controller/export_project.py +336 -0
- gns3server/controller/gns3vm/__init__.py +412 -0
- gns3server/controller/gns3vm/base_gns3_vm.py +303 -0
- gns3server/controller/gns3vm/gns3_vm_error.py +28 -0
- gns3server/controller/gns3vm/hyperv_gns3_vm.py +346 -0
- gns3server/controller/gns3vm/remote_gns3_vm.py +73 -0
- gns3server/controller/gns3vm/virtualbox_gns3_vm.py +480 -0
- gns3server/controller/gns3vm/vmware_gns3_vm.py +216 -0
- gns3server/controller/import_project.py +332 -0
- gns3server/controller/link.py +461 -0
- gns3server/controller/node.py +840 -0
- gns3server/controller/notification.py +149 -0
- gns3server/controller/ports/__init__.py +0 -0
- gns3server/controller/ports/atm_port.py +51 -0
- gns3server/controller/ports/ethernet_port.py +49 -0
- gns3server/controller/ports/fastethernet_port.py +43 -0
- gns3server/controller/ports/frame_relay_port.py +43 -0
- gns3server/controller/ports/gigabitethernet_port.py +43 -0
- gns3server/controller/ports/port.py +109 -0
- gns3server/controller/ports/port_factory.py +213 -0
- gns3server/controller/ports/pos_port.py +52 -0
- gns3server/controller/ports/serial_port.py +63 -0
- gns3server/controller/project.py +1399 -0
- gns3server/controller/snapshot.py +140 -0
- gns3server/controller/symbol_themes.py +153 -0
- gns3server/controller/symbols.py +168 -0
- gns3server/controller/topology.py +788 -0
- gns3server/controller/udp_link.py +245 -0
- gns3server/core/__init__.py +0 -0
- gns3server/core/tasks.py +99 -0
- gns3server/crash_report.py +167 -0
- gns3server/db/__init__.py +0 -0
- gns3server/db/models/__init__.py +38 -0
- gns3server/db/models/acl.py +46 -0
- gns3server/db/models/base.py +117 -0
- gns3server/db/models/computes.py +33 -0
- gns3server/db/models/images.py +43 -0
- gns3server/db/models/pools.py +52 -0
- gns3server/db/models/privileges.py +359 -0
- gns3server/db/models/roles.py +57 -0
- gns3server/db/models/templates.py +272 -0
- gns3server/db/models/users.py +94 -0
- gns3server/db/repositories/__init__.py +0 -0
- gns3server/db/repositories/base.py +24 -0
- gns3server/db/repositories/computes.py +93 -0
- gns3server/db/repositories/images.py +141 -0
- gns3server/db/repositories/pools.py +218 -0
- gns3server/db/repositories/rbac.py +430 -0
- gns3server/db/repositories/templates.py +172 -0
- gns3server/db/repositories/users.py +289 -0
- gns3server/db/tasks.py +230 -0
- gns3server/db_migrations/README +5 -0
- gns3server/db_migrations/env.py +101 -0
- gns3server/db_migrations/script.py.mako +24 -0
- gns3server/db_migrations/versions/7ceeddd9c9a8_init.py +28 -0
- gns3server/db_migrations/versions/9a5292aa4389_add_mac_address_field_in_docker_.py +27 -0
- gns3server/disks/OVMF.fd +0 -0
- gns3server/disks/OVMF_CODE.fd +0 -0
- gns3server/disks/OVMF_VARS.fd +0 -0
- gns3server/disks/empty100G.qcow2 +0 -0
- gns3server/disks/empty10G.qcow2 +0 -0
- gns3server/disks/empty150G.qcow2 +0 -0
- gns3server/disks/empty1T.qcow2 +0 -0
- gns3server/disks/empty200G.qcow2 +0 -0
- gns3server/disks/empty20G.qcow2 +0 -0
- gns3server/disks/empty250G.qcow2 +0 -0
- gns3server/disks/empty30G.qcow2 +0 -0
- gns3server/disks/empty40G.qcow2 +0 -0
- gns3server/disks/empty500G.qcow2 +0 -0
- gns3server/disks/empty50G.qcow2 +0 -0
- gns3server/disks/empty8G.qcow2 +0 -0
- gns3server/gns3_server.egg-info/PKG-INFO +307 -0
- gns3server/gns3_server.egg-info/SOURCES.txt +0 -0
- gns3server/gns3_server.egg-info/dependency_links.txt +1 -0
- gns3server/gns3_server.egg-info/entry_points.txt +4 -0
- gns3server/gns3_server.egg-info/not-zip-safe +1 -0
- gns3server/gns3_server.egg-info/requires.txt +31 -0
- gns3server/gns3_server.egg-info/top_level.txt +2 -0
- gns3server/logger.py +164 -0
- gns3server/main.py +81 -0
- gns3server/schemas/__init__.py +85 -0
- gns3server/schemas/common.py +71 -0
- gns3server/schemas/compute/__init__.py +0 -0
- gns3server/schemas/compute/atm_switch_nodes.py +55 -0
- gns3server/schemas/compute/cloud_nodes.py +137 -0
- gns3server/schemas/compute/docker_nodes.py +75 -0
- gns3server/schemas/compute/dynamips_nodes.py +197 -0
- gns3server/schemas/compute/ethernet_hub_nodes.py +63 -0
- gns3server/schemas/compute/ethernet_switch_nodes.py +100 -0
- gns3server/schemas/compute/frame_relay_switch_nodes.py +55 -0
- gns3server/schemas/compute/iou_nodes.py +76 -0
- gns3server/schemas/compute/nat_nodes.py +122 -0
- gns3server/schemas/compute/nios.py +66 -0
- gns3server/schemas/compute/qemu_nodes.py +245 -0
- gns3server/schemas/compute/virtualbox_nodes.py +97 -0
- gns3server/schemas/compute/vmware_nodes.py +102 -0
- gns3server/schemas/compute/vpcs_nodes.py +68 -0
- gns3server/schemas/config.py +197 -0
- gns3server/schemas/controller/__init__.py +0 -0
- gns3server/schemas/controller/appliances.py +466 -0
- gns3server/schemas/controller/base.py +25 -0
- gns3server/schemas/controller/capabilities.py +34 -0
- gns3server/schemas/controller/computes.py +168 -0
- gns3server/schemas/controller/drawings.py +34 -0
- gns3server/schemas/controller/gns3vm.py +56 -0
- gns3server/schemas/controller/images.py +44 -0
- gns3server/schemas/controller/iou_license.py +23 -0
- gns3server/schemas/controller/labels.py +30 -0
- gns3server/schemas/controller/links.py +94 -0
- gns3server/schemas/controller/nodes.py +177 -0
- gns3server/schemas/controller/pools.py +81 -0
- gns3server/schemas/controller/projects.py +116 -0
- gns3server/schemas/controller/rbac.py +113 -0
- gns3server/schemas/controller/snapshots.py +42 -0
- gns3server/schemas/controller/templates/__init__.py +83 -0
- gns3server/schemas/controller/templates/cloud_templates.py +44 -0
- gns3server/schemas/controller/templates/docker_templates.py +59 -0
- gns3server/schemas/controller/templates/dynamips_templates.py +199 -0
- gns3server/schemas/controller/templates/ethernet_hub_templates.py +46 -0
- gns3server/schemas/controller/templates/ethernet_switch_templates.py +57 -0
- gns3server/schemas/controller/templates/iou_templates.py +47 -0
- gns3server/schemas/controller/templates/qemu_templates.py +94 -0
- gns3server/schemas/controller/templates/virtualbox_templates.py +64 -0
- gns3server/schemas/controller/templates/vmware_templates.py +61 -0
- gns3server/schemas/controller/templates/vpcs_templates.py +39 -0
- gns3server/schemas/controller/tokens.py +29 -0
- gns3server/schemas/controller/topology.py +82 -0
- gns3server/schemas/controller/users.py +105 -0
- gns3server/schemas/link.py +0 -0
- gns3server/schemas/qemu_disk_image.py +103 -0
- gns3server/schemas/version.py +25 -0
- gns3server/server.py +348 -0
- gns3server/services/__init__.py +19 -0
- gns3server/services/authentication.py +83 -0
- gns3server/services/computes.py +82 -0
- gns3server/services/templates.py +329 -0
- gns3server/static/.gitkeep +0 -0
- gns3server/static/favicon.ico +0 -0
- gns3server/static/redoc.standalone.js +1782 -0
- gns3server/static/swagger-ui-bundle.js +2 -0
- gns3server/static/swagger-ui.css +3 -0
- gns3server/static/web-ui/3rdpartylicenses.txt +2604 -0
- gns3server/static/web-ui/465.92c7ab880f2504d3.js +1 -0
- gns3server/static/web-ui/MaterialIcons-Regular.196fa4a92dd6fa73.ttf +0 -0
- gns3server/static/web-ui/MaterialIcons-Regular.1e50f5c2ffa6aba4.eot +0 -0
- gns3server/static/web-ui/MaterialIcons-Regular.7ea2023eeca07427.woff2 +0 -0
- gns3server/static/web-ui/MaterialIcons-Regular.db852539204b1a34.woff +0 -0
- gns3server/static/web-ui/NotoSans-Bold.635e9291df1a5a00.woff2 +0 -0
- gns3server/static/web-ui/NotoSans-Bold.885427cced6d8c94.woff +0 -0
- gns3server/static/web-ui/NotoSans-Bold.93203a43bc93ad9c.svg +8453 -0
- gns3server/static/web-ui/NotoSans-Bold.a7ab189a45f553b4.eot +0 -0
- gns3server/static/web-ui/NotoSans-Bold.e989c11744b36f58.ttf +0 -0
- gns3server/static/web-ui/NotoSans-BoldItalic.2baf33b639fc86a4.woff +0 -0
- gns3server/static/web-ui/NotoSans-BoldItalic.2eea9ba02e25c1d3.ttf +0 -0
- gns3server/static/web-ui/NotoSans-BoldItalic.46a5eec91da0d900.svg +8453 -0
- gns3server/static/web-ui/NotoSans-BoldItalic.7fdef73b477daa73.eot +0 -0
- gns3server/static/web-ui/NotoSans-BoldItalic.c62f70f121f271aa.woff2 +0 -0
- gns3server/static/web-ui/NotoSans-Italic.219ee88e5bc4e168.ttf +0 -0
- gns3server/static/web-ui/NotoSans-Italic.3d6f7cf772169c8d.svg +8453 -0
- gns3server/static/web-ui/NotoSans-Italic.77cd3818b5a2cb97.woff +0 -0
- gns3server/static/web-ui/NotoSans-Italic.85194585ae9d8c36.eot +0 -0
- gns3server/static/web-ui/NotoSans-Italic.eee02500e81db981.woff2 +0 -0
- gns3server/static/web-ui/NotoSans-Regular.156b7584192d70ed.eot +0 -0
- gns3server/static/web-ui/NotoSans-Regular.374d132a6803e279.woff2 +0 -0
- gns3server/static/web-ui/NotoSans-Regular.595e3f5876719740.woff +0 -0
- gns3server/static/web-ui/NotoSans-Regular.bb384defbe36eaec.svg +8453 -0
- gns3server/static/web-ui/NotoSans-Regular.e6139cb1663a1c57.ttf +0 -0
- gns3server/static/web-ui/ReleaseNotes.txt +179 -0
- gns3server/static/web-ui/assets/favicon.ico +0 -0
- gns3server/static/web-ui/assets/gns3_icon.svg +88 -0
- gns3server/static/web-ui/assets/gns3_icon_black.svg +88 -0
- gns3server/static/web-ui/assets/icons/mac/icon.icns +0 -0
- gns3server/static/web-ui/assets/icons/png/1024x1024.png +0 -0
- gns3server/static/web-ui/assets/icons/png/128x128.png +0 -0
- gns3server/static/web-ui/assets/icons/png/16x16.png +0 -0
- gns3server/static/web-ui/assets/icons/png/24x24.png +0 -0
- gns3server/static/web-ui/assets/icons/png/256x256.png +0 -0
- gns3server/static/web-ui/assets/icons/png/32x32.png +0 -0
- gns3server/static/web-ui/assets/icons/png/48x48.png +0 -0
- gns3server/static/web-ui/assets/icons/png/512x512.png +0 -0
- gns3server/static/web-ui/assets/icons/png/64x64.png +0 -0
- gns3server/static/web-ui/assets/icons/win/icon.ico +0 -0
- gns3server/static/web-ui/assets/logo-header.png +0 -0
- gns3server/static/web-ui/assets/resources/images/filter-capture.svg +428 -0
- gns3server/static/web-ui/assets/resources/images/filter.svg +708 -0
- gns3server/static/web-ui/assets/resources/images/inspect.svg +312 -0
- gns3server/static/web-ui/assets/resources/images/pause.svg +752 -0
- gns3server/static/web-ui/favicon.ico +0 -0
- gns3server/static/web-ui/index.html +51 -0
- gns3server/static/web-ui/main.f802edd2b8c6db1d.js +1 -0
- gns3server/static/web-ui/polyfills.319c79dd175e50d0.js +1 -0
- gns3server/static/web-ui/roboto-latin-100.539f0a96b40596f7.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-100.5ba994dac3e79ea8.woff +0 -0
- gns3server/static/web-ui/roboto-latin-100italic.41ba64219cb743c9.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-100italic.d61e7e8b07c0638c.woff +0 -0
- gns3server/static/web-ui/roboto-latin-300.4d8f8086236bad80.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-300.6c1bc461047e61f5.woff +0 -0
- gns3server/static/web-ui/roboto-latin-300italic.3a529751a590d3c1.woff +0 -0
- gns3server/static/web-ui/roboto-latin-300italic.45164643b3bd5824.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-400.1e2d4d3a272629cd.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-400.7e4a045b9373d9c1.woff +0 -0
- gns3server/static/web-ui/roboto-latin-400italic.68431199e5b90ea8.woff +0 -0
- gns3server/static/web-ui/roboto-latin-400italic.bb3c6955c4334c8a.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-500.1dfbc3dbf815e3f3.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-500.e21fe97fd2329ff7.woff +0 -0
- gns3server/static/web-ui/roboto-latin-500italic.7543a42b12b1452f.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-500italic.aaff6867154023d3.woff +0 -0
- gns3server/static/web-ui/roboto-latin-700.02633003129d1e63.woff +0 -0
- gns3server/static/web-ui/roboto-latin-700.12893bfc0762b0f3.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-700italic.bc7179e004e40113.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-700italic.e53062e27c63fafb.woff +0 -0
- gns3server/static/web-ui/roboto-latin-900.282ba77fda1349f3.woff2 +0 -0
- gns3server/static/web-ui/roboto-latin-900.4962e810cbb4d3e5.woff +0 -0
- gns3server/static/web-ui/roboto-latin-900italic.2394134a78bbaef8.woff +0 -0
- gns3server/static/web-ui/roboto-latin-900italic.9c1f80840351fa12.woff2 +0 -0
- gns3server/static/web-ui/runtime.24fa95b7061d7056.js +1 -0
- gns3server/static/web-ui/styles.6e966072487df0b7.css +5 -0
- gns3server/symbols/.gitkeep +0 -0
- gns3server/symbols/affinity/circle/blue/atm.svg +5 -0
- gns3server/symbols/affinity/circle/blue/bug.svg +8 -0
- gns3server/symbols/affinity/circle/blue/camera.svg +5 -0
- gns3server/symbols/affinity/circle/blue/camera_dome.svg +8 -0
- gns3server/symbols/affinity/circle/blue/client.svg +5 -0
- gns3server/symbols/affinity/circle/blue/client_vm.svg +6 -0
- gns3server/symbols/affinity/circle/blue/cloud.svg +5 -0
- gns3server/symbols/affinity/circle/blue/coffee.svg +6 -0
- gns3server/symbols/affinity/circle/blue/cog.svg +5 -0
- gns3server/symbols/affinity/circle/blue/communications.svg +5 -0
- gns3server/symbols/affinity/circle/blue/conversation.svg +12 -0
- gns3server/symbols/affinity/circle/blue/dna.svg +7 -0
- gns3server/symbols/affinity/circle/blue/dna2.svg +7 -0
- gns3server/symbols/affinity/circle/blue/docker.svg +11 -0
- gns3server/symbols/affinity/circle/blue/dslam.svg +5 -0
- gns3server/symbols/affinity/circle/blue/factory.svg +6 -0
- gns3server/symbols/affinity/circle/blue/fingerprint.svg +5 -0
- gns3server/symbols/affinity/circle/blue/firewall.svg +5 -0
- gns3server/symbols/affinity/circle/blue/firewall3.svg +5 -0
- gns3server/symbols/affinity/circle/blue/globe.svg +5 -0
- gns3server/symbols/affinity/circle/blue/grid.svg +5 -0
- gns3server/symbols/affinity/circle/blue/grid2.svg +5 -0
- gns3server/symbols/affinity/circle/blue/health.svg +5 -0
- gns3server/symbols/affinity/circle/blue/house.svg +9 -0
- gns3server/symbols/affinity/circle/blue/hub.svg +5 -0
- gns3server/symbols/affinity/circle/blue/inspect.svg +7 -0
- gns3server/symbols/affinity/circle/blue/inspect2.svg +6 -0
- gns3server/symbols/affinity/circle/blue/interconnect.svg +5 -0
- gns3server/symbols/affinity/circle/blue/ip_phone.svg +21 -0
- gns3server/symbols/affinity/circle/blue/isdn.svg +5 -0
- gns3server/symbols/affinity/circle/blue/laptop.svg +6 -0
- gns3server/symbols/affinity/circle/blue/ldap.svg +5 -0
- gns3server/symbols/affinity/circle/blue/light_bulb.svg +11 -0
- gns3server/symbols/affinity/circle/blue/link.svg +5 -0
- gns3server/symbols/affinity/circle/blue/loadbalancer.svg +5 -0
- gns3server/symbols/affinity/circle/blue/nas.svg +5 -0
- gns3server/symbols/affinity/circle/blue/nat.svg +60 -0
- gns3server/symbols/affinity/circle/blue/nat2.svg +55 -0
- gns3server/symbols/affinity/circle/blue/office.svg +5 -0
- gns3server/symbols/affinity/circle/blue/optical.svg +8 -0
- gns3server/symbols/affinity/circle/blue/phone_cloud.svg +6 -0
- gns3server/symbols/affinity/circle/blue/phone_old.svg +5 -0
- gns3server/symbols/affinity/circle/blue/phone_wireless.svg +8 -0
- gns3server/symbols/affinity/circle/blue/pinpoint.svg +5 -0
- gns3server/symbols/affinity/circle/blue/printer.svg +7 -0
- gns3server/symbols/affinity/circle/blue/rj45.svg +5 -0
- gns3server/symbols/affinity/circle/blue/router.svg +5 -0
- gns3server/symbols/affinity/circle/blue/router2.svg +5 -0
- gns3server/symbols/affinity/circle/blue/router_cloud.svg +6 -0
- gns3server/symbols/affinity/circle/blue/satellite.svg +6 -0
- gns3server/symbols/affinity/circle/blue/satellite_dish.svg +7 -0
- gns3server/symbols/affinity/circle/blue/scull.svg +8 -0
- gns3server/symbols/affinity/circle/blue/server.svg +5 -0
- gns3server/symbols/affinity/circle/blue/server_cluster.svg +7 -0
- gns3server/symbols/affinity/circle/blue/shield.svg +7 -0
- gns3server/symbols/affinity/circle/blue/statistics.svg +7 -0
- gns3server/symbols/affinity/circle/blue/storage.svg +5 -0
- gns3server/symbols/affinity/circle/blue/switch.svg +8 -0
- gns3server/symbols/affinity/circle/blue/switch_multilayer.svg +5 -0
- gns3server/symbols/affinity/circle/blue/tablet.svg +11 -0
- gns3server/symbols/affinity/circle/blue/template.svg +4 -0
- gns3server/symbols/affinity/circle/blue/tree.svg +5 -0
- gns3server/symbols/affinity/circle/blue/user.svg +7 -0
- gns3server/symbols/affinity/circle/blue/virtualbox.svg +7 -0
- gns3server/symbols/affinity/circle/blue/vm.svg +7 -0
- gns3server/symbols/affinity/circle/blue/vmware.svg +7 -0
- gns3server/symbols/affinity/circle/blue/vrf.svg +8 -0
- gns3server/symbols/affinity/circle/blue/wifi.svg +5 -0
- gns3server/symbols/affinity/circle/blue/wlc.svg +5 -0
- gns3server/symbols/affinity/circle/blue/xml.svg +5 -0
- gns3server/symbols/affinity/circle/gray/atm.svg +5 -0
- gns3server/symbols/affinity/circle/gray/bug.svg +8 -0
- gns3server/symbols/affinity/circle/gray/camera.svg +5 -0
- gns3server/symbols/affinity/circle/gray/camera_dome.svg +8 -0
- gns3server/symbols/affinity/circle/gray/client.svg +5 -0
- gns3server/symbols/affinity/circle/gray/client_vm.svg +6 -0
- gns3server/symbols/affinity/circle/gray/cloud.svg +5 -0
- gns3server/symbols/affinity/circle/gray/coffee.svg +6 -0
- gns3server/symbols/affinity/circle/gray/cog.svg +5 -0
- gns3server/symbols/affinity/circle/gray/communications.svg +5 -0
- gns3server/symbols/affinity/circle/gray/conversation.svg +12 -0
- gns3server/symbols/affinity/circle/gray/dna.svg +7 -0
- gns3server/symbols/affinity/circle/gray/dna2.svg +7 -0
- gns3server/symbols/affinity/circle/gray/docker.svg +11 -0
- gns3server/symbols/affinity/circle/gray/dslam.svg +5 -0
- gns3server/symbols/affinity/circle/gray/factory.svg +7 -0
- gns3server/symbols/affinity/circle/gray/fingerprint.svg +5 -0
- gns3server/symbols/affinity/circle/gray/firewall.svg +5 -0
- gns3server/symbols/affinity/circle/gray/firewall3.svg +5 -0
- gns3server/symbols/affinity/circle/gray/globe.svg +5 -0
- gns3server/symbols/affinity/circle/gray/grid.svg +5 -0
- gns3server/symbols/affinity/circle/gray/grid2.svg +5 -0
- gns3server/symbols/affinity/circle/gray/health.svg +5 -0
- gns3server/symbols/affinity/circle/gray/house.svg +9 -0
- gns3server/symbols/affinity/circle/gray/hub.svg +5 -0
- gns3server/symbols/affinity/circle/gray/inspect.svg +7 -0
- gns3server/symbols/affinity/circle/gray/inspect2.svg +6 -0
- gns3server/symbols/affinity/circle/gray/interconnect.svg +5 -0
- gns3server/symbols/affinity/circle/gray/ip_phone.svg +21 -0
- gns3server/symbols/affinity/circle/gray/isdn.svg +5 -0
- gns3server/symbols/affinity/circle/gray/laptop.svg +6 -0
- gns3server/symbols/affinity/circle/gray/ldap.svg +5 -0
- gns3server/symbols/affinity/circle/gray/light_bulb.svg +11 -0
- gns3server/symbols/affinity/circle/gray/link.svg +5 -0
- gns3server/symbols/affinity/circle/gray/loadbalancer.svg +5 -0
- gns3server/symbols/affinity/circle/gray/nas.svg +5 -0
- gns3server/symbols/affinity/circle/gray/nat.svg +60 -0
- gns3server/symbols/affinity/circle/gray/nat2.svg +55 -0
- gns3server/symbols/affinity/circle/gray/office.svg +5 -0
- gns3server/symbols/affinity/circle/gray/optical.svg +8 -0
- gns3server/symbols/affinity/circle/gray/phone_cloud.svg +6 -0
- gns3server/symbols/affinity/circle/gray/phone_old.svg +5 -0
- gns3server/symbols/affinity/circle/gray/phone_wireless.svg +8 -0
- gns3server/symbols/affinity/circle/gray/pinpoint.svg +5 -0
- gns3server/symbols/affinity/circle/gray/printer.svg +25 -0
- gns3server/symbols/affinity/circle/gray/rj45.svg +5 -0
- gns3server/symbols/affinity/circle/gray/router.svg +5 -0
- gns3server/symbols/affinity/circle/gray/router2.svg +5 -0
- gns3server/symbols/affinity/circle/gray/router_cloud.svg +6 -0
- gns3server/symbols/affinity/circle/gray/satellite.svg +6 -0
- gns3server/symbols/affinity/circle/gray/satellite_dish.svg +7 -0
- gns3server/symbols/affinity/circle/gray/scull.svg +8 -0
- gns3server/symbols/affinity/circle/gray/server.svg +5 -0
- gns3server/symbols/affinity/circle/gray/server_cluster.svg +7 -0
- gns3server/symbols/affinity/circle/gray/shield.svg +7 -0
- gns3server/symbols/affinity/circle/gray/statistics.svg +7 -0
- gns3server/symbols/affinity/circle/gray/storage.svg +5 -0
- gns3server/symbols/affinity/circle/gray/switch.svg +8 -0
- gns3server/symbols/affinity/circle/gray/switch_multilayer.svg +5 -0
- gns3server/symbols/affinity/circle/gray/tablet.svg +11 -0
- gns3server/symbols/affinity/circle/gray/template.svg +4 -0
- gns3server/symbols/affinity/circle/gray/tree.svg +5 -0
- gns3server/symbols/affinity/circle/gray/user.svg +7 -0
- gns3server/symbols/affinity/circle/gray/virtualbox.svg +7 -0
- gns3server/symbols/affinity/circle/gray/vm.svg +7 -0
- gns3server/symbols/affinity/circle/gray/vmware.svg +7 -0
- gns3server/symbols/affinity/circle/gray/vrf.svg +8 -0
- gns3server/symbols/affinity/circle/gray/wifi.svg +5 -0
- gns3server/symbols/affinity/circle/gray/wlc.svg +5 -0
- gns3server/symbols/affinity/circle/gray/xml.svg +5 -0
- gns3server/symbols/affinity/circle/green/atm.svg +5 -0
- gns3server/symbols/affinity/circle/green/bug.svg +8 -0
- gns3server/symbols/affinity/circle/green/camera.svg +5 -0
- gns3server/symbols/affinity/circle/green/camera_dome.svg +8 -0
- gns3server/symbols/affinity/circle/green/client.svg +5 -0
- gns3server/symbols/affinity/circle/green/client_vm.svg +6 -0
- gns3server/symbols/affinity/circle/green/cloud.svg +5 -0
- gns3server/symbols/affinity/circle/green/coffee.svg +6 -0
- gns3server/symbols/affinity/circle/green/cog.svg +5 -0
- gns3server/symbols/affinity/circle/green/communications.svg +5 -0
- gns3server/symbols/affinity/circle/green/conversation.svg +12 -0
- gns3server/symbols/affinity/circle/green/dna.svg +7 -0
- gns3server/symbols/affinity/circle/green/dna2.svg +7 -0
- gns3server/symbols/affinity/circle/green/docker.svg +11 -0
- gns3server/symbols/affinity/circle/green/dslam.svg +5 -0
- gns3server/symbols/affinity/circle/green/factory.svg +6 -0
- gns3server/symbols/affinity/circle/green/fingerprint.svg +5 -0
- gns3server/symbols/affinity/circle/green/firewall.svg +5 -0
- gns3server/symbols/affinity/circle/green/firewall3.svg +5 -0
- gns3server/symbols/affinity/circle/green/globe.svg +5 -0
- gns3server/symbols/affinity/circle/green/grid.svg +5 -0
- gns3server/symbols/affinity/circle/green/grid2.svg +5 -0
- gns3server/symbols/affinity/circle/green/health.svg +5 -0
- gns3server/symbols/affinity/circle/green/house.svg +9 -0
- gns3server/symbols/affinity/circle/green/hub.svg +5 -0
- gns3server/symbols/affinity/circle/green/inspect.svg +7 -0
- gns3server/symbols/affinity/circle/green/inspect2.svg +6 -0
- gns3server/symbols/affinity/circle/green/interconnect.svg +5 -0
- gns3server/symbols/affinity/circle/green/ip_phone.svg +21 -0
- gns3server/symbols/affinity/circle/green/isdn.svg +5 -0
- gns3server/symbols/affinity/circle/green/laptop.svg +6 -0
- gns3server/symbols/affinity/circle/green/ldap.svg +5 -0
- gns3server/symbols/affinity/circle/green/light_bulb.svg +11 -0
- gns3server/symbols/affinity/circle/green/link.svg +5 -0
- gns3server/symbols/affinity/circle/green/loadbalancer.svg +5 -0
- gns3server/symbols/affinity/circle/green/nas.svg +5 -0
- gns3server/symbols/affinity/circle/green/nat.svg +60 -0
- gns3server/symbols/affinity/circle/green/nat2.svg +55 -0
- gns3server/symbols/affinity/circle/green/office.svg +5 -0
- gns3server/symbols/affinity/circle/green/optical.svg +8 -0
- gns3server/symbols/affinity/circle/green/phone_cloud.svg +6 -0
- gns3server/symbols/affinity/circle/green/phone_old.svg +5 -0
- gns3server/symbols/affinity/circle/green/phone_wireless.svg +8 -0
- gns3server/symbols/affinity/circle/green/pinpoint.svg +5 -0
- gns3server/symbols/affinity/circle/green/printer.svg +7 -0
- gns3server/symbols/affinity/circle/green/rj45.svg +5 -0
- gns3server/symbols/affinity/circle/green/router.svg +5 -0
- gns3server/symbols/affinity/circle/green/router2.svg +5 -0
- gns3server/symbols/affinity/circle/green/router_cloud.svg +6 -0
- gns3server/symbols/affinity/circle/green/satellite.svg +6 -0
- gns3server/symbols/affinity/circle/green/satellite_dish.svg +7 -0
- gns3server/symbols/affinity/circle/green/scull.svg +8 -0
- gns3server/symbols/affinity/circle/green/server.svg +5 -0
- gns3server/symbols/affinity/circle/green/server_cluster.svg +7 -0
- gns3server/symbols/affinity/circle/green/shield.svg +7 -0
- gns3server/symbols/affinity/circle/green/statistics.svg +7 -0
- gns3server/symbols/affinity/circle/green/storage.svg +5 -0
- gns3server/symbols/affinity/circle/green/switch.svg +8 -0
- gns3server/symbols/affinity/circle/green/switch_multilayer.svg +5 -0
- gns3server/symbols/affinity/circle/green/tablet.svg +11 -0
- gns3server/symbols/affinity/circle/green/template.svg +4 -0
- gns3server/symbols/affinity/circle/green/tree.svg +5 -0
- gns3server/symbols/affinity/circle/green/user.svg +7 -0
- gns3server/symbols/affinity/circle/green/virtualbox.svg +7 -0
- gns3server/symbols/affinity/circle/green/vm.svg +7 -0
- gns3server/symbols/affinity/circle/green/vmware.svg +7 -0
- gns3server/symbols/affinity/circle/green/vrf.svg +8 -0
- gns3server/symbols/affinity/circle/green/wifi.svg +5 -0
- gns3server/symbols/affinity/circle/green/wlc.svg +5 -0
- gns3server/symbols/affinity/circle/green/xml.svg +5 -0
- gns3server/symbols/affinity/circle/red/atm.svg +5 -0
- gns3server/symbols/affinity/circle/red/bug.svg +8 -0
- gns3server/symbols/affinity/circle/red/camera.svg +5 -0
- gns3server/symbols/affinity/circle/red/camera_dome.svg +8 -0
- gns3server/symbols/affinity/circle/red/client.svg +5 -0
- gns3server/symbols/affinity/circle/red/client_vm.svg +6 -0
- gns3server/symbols/affinity/circle/red/cloud.svg +5 -0
- gns3server/symbols/affinity/circle/red/coffee.svg +6 -0
- gns3server/symbols/affinity/circle/red/cog.svg +5 -0
- gns3server/symbols/affinity/circle/red/communications.svg +5 -0
- gns3server/symbols/affinity/circle/red/conversation.svg +12 -0
- gns3server/symbols/affinity/circle/red/dna.svg +7 -0
- gns3server/symbols/affinity/circle/red/dna2.svg +7 -0
- gns3server/symbols/affinity/circle/red/docker.svg +11 -0
- gns3server/symbols/affinity/circle/red/dslam.svg +5 -0
- gns3server/symbols/affinity/circle/red/factory.svg +6 -0
- gns3server/symbols/affinity/circle/red/fingerprint.svg +5 -0
- gns3server/symbols/affinity/circle/red/firewall.svg +5 -0
- gns3server/symbols/affinity/circle/red/firewall3.svg +5 -0
- gns3server/symbols/affinity/circle/red/globe.svg +5 -0
- gns3server/symbols/affinity/circle/red/grid.svg +5 -0
- gns3server/symbols/affinity/circle/red/grid2.svg +5 -0
- gns3server/symbols/affinity/circle/red/health.svg +5 -0
- gns3server/symbols/affinity/circle/red/house.svg +9 -0
- gns3server/symbols/affinity/circle/red/hub.svg +5 -0
- gns3server/symbols/affinity/circle/red/inspect.svg +7 -0
- gns3server/symbols/affinity/circle/red/inspect2.svg +6 -0
- gns3server/symbols/affinity/circle/red/interconnect.svg +5 -0
- gns3server/symbols/affinity/circle/red/ip_phone.svg +21 -0
- gns3server/symbols/affinity/circle/red/isdn.svg +5 -0
- gns3server/symbols/affinity/circle/red/laptop.svg +6 -0
- gns3server/symbols/affinity/circle/red/ldap.svg +5 -0
- gns3server/symbols/affinity/circle/red/light_bulb.svg +11 -0
- gns3server/symbols/affinity/circle/red/link.svg +5 -0
- gns3server/symbols/affinity/circle/red/loadbalancer.svg +5 -0
- gns3server/symbols/affinity/circle/red/nas.svg +5 -0
- gns3server/symbols/affinity/circle/red/nat.svg +60 -0
- gns3server/symbols/affinity/circle/red/nat2.svg +55 -0
- gns3server/symbols/affinity/circle/red/office.svg +5 -0
- gns3server/symbols/affinity/circle/red/optical.svg +8 -0
- gns3server/symbols/affinity/circle/red/phone_cloud.svg +6 -0
- gns3server/symbols/affinity/circle/red/phone_old.svg +5 -0
- gns3server/symbols/affinity/circle/red/phone_wireless.svg +8 -0
- gns3server/symbols/affinity/circle/red/pinpoint.svg +5 -0
- gns3server/symbols/affinity/circle/red/printer.svg +7 -0
- gns3server/symbols/affinity/circle/red/rj45.svg +5 -0
- gns3server/symbols/affinity/circle/red/router.svg +5 -0
- gns3server/symbols/affinity/circle/red/router2.svg +5 -0
- gns3server/symbols/affinity/circle/red/router_cloud.svg +6 -0
- gns3server/symbols/affinity/circle/red/satellite.svg +6 -0
- gns3server/symbols/affinity/circle/red/satellite_dish.svg +7 -0
- gns3server/symbols/affinity/circle/red/scull.svg +8 -0
- gns3server/symbols/affinity/circle/red/server.svg +5 -0
- gns3server/symbols/affinity/circle/red/server_cluster.svg +7 -0
- gns3server/symbols/affinity/circle/red/shield.svg +7 -0
- gns3server/symbols/affinity/circle/red/statistics.svg +7 -0
- gns3server/symbols/affinity/circle/red/storage.svg +5 -0
- gns3server/symbols/affinity/circle/red/switch.svg +8 -0
- gns3server/symbols/affinity/circle/red/switch_multilayer.svg +5 -0
- gns3server/symbols/affinity/circle/red/tablet.svg +11 -0
- gns3server/symbols/affinity/circle/red/template.svg +4 -0
- gns3server/symbols/affinity/circle/red/tree.svg +5 -0
- gns3server/symbols/affinity/circle/red/user.svg +7 -0
- gns3server/symbols/affinity/circle/red/virtualbox.svg +7 -0
- gns3server/symbols/affinity/circle/red/vm.svg +7 -0
- gns3server/symbols/affinity/circle/red/vmware.svg +7 -0
- gns3server/symbols/affinity/circle/red/vrf.svg +8 -0
- gns3server/symbols/affinity/circle/red/wifi.svg +5 -0
- gns3server/symbols/affinity/circle/red/wlc.svg +5 -0
- gns3server/symbols/affinity/circle/red/xml.svg +5 -0
- gns3server/symbols/affinity/square/blue/atm.svg +5 -0
- gns3server/symbols/affinity/square/blue/bug.svg +5 -0
- gns3server/symbols/affinity/square/blue/camera.svg +12 -0
- gns3server/symbols/affinity/square/blue/camera_dome.svg +8 -0
- gns3server/symbols/affinity/square/blue/client.svg +8 -0
- gns3server/symbols/affinity/square/blue/client_vm.svg +8 -0
- gns3server/symbols/affinity/square/blue/cloud.svg +12 -0
- gns3server/symbols/affinity/square/blue/coffee.svg +5 -0
- gns3server/symbols/affinity/square/blue/cog.svg +8 -0
- gns3server/symbols/affinity/square/blue/communications.svg +8 -0
- gns3server/symbols/affinity/square/blue/conversation.svg +12 -0
- gns3server/symbols/affinity/square/blue/dna.svg +7 -0
- gns3server/symbols/affinity/square/blue/dna2.svg +7 -0
- gns3server/symbols/affinity/square/blue/docker.svg +11 -0
- gns3server/symbols/affinity/square/blue/dslam.svg +8 -0
- gns3server/symbols/affinity/square/blue/factory.svg +5 -0
- gns3server/symbols/affinity/square/blue/fingerprint.svg +9 -0
- gns3server/symbols/affinity/square/blue/firewall.svg +7 -0
- gns3server/symbols/affinity/square/blue/firewall3.svg +6 -0
- gns3server/symbols/affinity/square/blue/globe.svg +5 -0
- gns3server/symbols/affinity/square/blue/grid.svg +7 -0
- gns3server/symbols/affinity/square/blue/grid2.svg +7 -0
- gns3server/symbols/affinity/square/blue/health.svg +5 -0
- gns3server/symbols/affinity/square/blue/house.svg +6 -0
- gns3server/symbols/affinity/square/blue/hub.svg +7 -0
- gns3server/symbols/affinity/square/blue/inspect.svg +5 -0
- gns3server/symbols/affinity/square/blue/inspect2.svg +9 -0
- gns3server/symbols/affinity/square/blue/interconnect.svg +8 -0
- gns3server/symbols/affinity/square/blue/ip_phone.svg +23 -0
- gns3server/symbols/affinity/square/blue/isdn.svg +7 -0
- gns3server/symbols/affinity/square/blue/laptop.svg +8 -0
- gns3server/symbols/affinity/square/blue/ldap.svg +5 -0
- gns3server/symbols/affinity/square/blue/light_bulb.svg +11 -0
- gns3server/symbols/affinity/square/blue/link.svg +5 -0
- gns3server/symbols/affinity/square/blue/loadbalancer.svg +5 -0
- gns3server/symbols/affinity/square/blue/nas.svg +7 -0
- gns3server/symbols/affinity/square/blue/nat.svg +58 -0
- gns3server/symbols/affinity/square/blue/nat2.svg +74 -0
- gns3server/symbols/affinity/square/blue/office.svg +5 -0
- gns3server/symbols/affinity/square/blue/optical.svg +8 -0
- gns3server/symbols/affinity/square/blue/phone_cloud.svg +8 -0
- gns3server/symbols/affinity/square/blue/phone_old.svg +7 -0
- gns3server/symbols/affinity/square/blue/phone_wireless.svg +10 -0
- gns3server/symbols/affinity/square/blue/pinpoint.svg +9 -0
- gns3server/symbols/affinity/square/blue/printer.svg +27 -0
- gns3server/symbols/affinity/square/blue/rj45.svg +14 -0
- gns3server/symbols/affinity/square/blue/router.svg +7 -0
- gns3server/symbols/affinity/square/blue/router2.svg +5 -0
- gns3server/symbols/affinity/square/blue/router_cloud.svg +7 -0
- gns3server/symbols/affinity/square/blue/satellite.svg +8 -0
- gns3server/symbols/affinity/square/blue/satellite_dish.svg +7 -0
- gns3server/symbols/affinity/square/blue/scull.svg +10 -0
- gns3server/symbols/affinity/square/blue/server.svg +5 -0
- gns3server/symbols/affinity/square/blue/server_cluster.svg +9 -0
- gns3server/symbols/affinity/square/blue/shield.svg +5 -0
- gns3server/symbols/affinity/square/blue/statistics.svg +7 -0
- gns3server/symbols/affinity/square/blue/storage.svg +7 -0
- gns3server/symbols/affinity/square/blue/switch.svg +10 -0
- gns3server/symbols/affinity/square/blue/switch_multilayer.svg +8 -0
- gns3server/symbols/affinity/square/blue/tablet.svg +9 -0
- gns3server/symbols/affinity/square/blue/template.svg +4 -0
- gns3server/symbols/affinity/square/blue/tree.svg +5 -0
- gns3server/symbols/affinity/square/blue/user.svg +7 -0
- gns3server/symbols/affinity/square/blue/virtualbox.svg +7 -0
- gns3server/symbols/affinity/square/blue/vm.svg +7 -0
- gns3server/symbols/affinity/square/blue/vmware.svg +7 -0
- gns3server/symbols/affinity/square/blue/vrf.svg +5 -0
- gns3server/symbols/affinity/square/blue/wifi.svg +13 -0
- gns3server/symbols/affinity/square/blue/wlc.svg +7 -0
- gns3server/symbols/affinity/square/blue/xml.svg +10 -0
- gns3server/symbols/affinity/square/gray/atm.svg +5 -0
- gns3server/symbols/affinity/square/gray/bug.svg +5 -0
- gns3server/symbols/affinity/square/gray/camera.svg +12 -0
- gns3server/symbols/affinity/square/gray/camera_dome.svg +8 -0
- gns3server/symbols/affinity/square/gray/client.svg +8 -0
- gns3server/symbols/affinity/square/gray/client_vm.svg +8 -0
- gns3server/symbols/affinity/square/gray/cloud.svg +12 -0
- gns3server/symbols/affinity/square/gray/coffee.svg +5 -0
- gns3server/symbols/affinity/square/gray/cog.svg +8 -0
- gns3server/symbols/affinity/square/gray/communications.svg +8 -0
- gns3server/symbols/affinity/square/gray/conversation.svg +12 -0
- gns3server/symbols/affinity/square/gray/dna.svg +7 -0
- gns3server/symbols/affinity/square/gray/dna2.svg +7 -0
- gns3server/symbols/affinity/square/gray/docker.svg +11 -0
- gns3server/symbols/affinity/square/gray/dslam.svg +8 -0
- gns3server/symbols/affinity/square/gray/factory.svg +5 -0
- gns3server/symbols/affinity/square/gray/fingerprint.svg +9 -0
- gns3server/symbols/affinity/square/gray/firewall.svg +7 -0
- gns3server/symbols/affinity/square/gray/firewall3.svg +6 -0
- gns3server/symbols/affinity/square/gray/globe.svg +5 -0
- gns3server/symbols/affinity/square/gray/grid.svg +7 -0
- gns3server/symbols/affinity/square/gray/grid2.svg +7 -0
- gns3server/symbols/affinity/square/gray/health.svg +5 -0
- gns3server/symbols/affinity/square/gray/house.svg +6 -0
- gns3server/symbols/affinity/square/gray/hub.svg +7 -0
- gns3server/symbols/affinity/square/gray/inspect.svg +5 -0
- gns3server/symbols/affinity/square/gray/inspect2.svg +9 -0
- gns3server/symbols/affinity/square/gray/interconnect.svg +8 -0
- gns3server/symbols/affinity/square/gray/ip_phone.svg +23 -0
- gns3server/symbols/affinity/square/gray/isdn.svg +7 -0
- gns3server/symbols/affinity/square/gray/laptop.svg +8 -0
- gns3server/symbols/affinity/square/gray/ldap.svg +5 -0
- gns3server/symbols/affinity/square/gray/light_bulb.svg +11 -0
- gns3server/symbols/affinity/square/gray/link.svg +5 -0
- gns3server/symbols/affinity/square/gray/loadbalancer.svg +5 -0
- gns3server/symbols/affinity/square/gray/nas.svg +7 -0
- gns3server/symbols/affinity/square/gray/nat.svg +58 -0
- gns3server/symbols/affinity/square/gray/nat2.svg +74 -0
- gns3server/symbols/affinity/square/gray/office.svg +5 -0
- gns3server/symbols/affinity/square/gray/optical.svg +8 -0
- gns3server/symbols/affinity/square/gray/phone_cloud.svg +8 -0
- gns3server/symbols/affinity/square/gray/phone_old.svg +7 -0
- gns3server/symbols/affinity/square/gray/phone_wireless.svg +10 -0
- gns3server/symbols/affinity/square/gray/pinpoint.svg +9 -0
- gns3server/symbols/affinity/square/gray/printer.svg +27 -0
- gns3server/symbols/affinity/square/gray/rj45.svg +14 -0
- gns3server/symbols/affinity/square/gray/router.svg +7 -0
- gns3server/symbols/affinity/square/gray/router2.svg +5 -0
- gns3server/symbols/affinity/square/gray/router_cloud.svg +7 -0
- gns3server/symbols/affinity/square/gray/satellite.svg +8 -0
- gns3server/symbols/affinity/square/gray/satellite_dish.svg +7 -0
- gns3server/symbols/affinity/square/gray/scull.svg +10 -0
- gns3server/symbols/affinity/square/gray/server.svg +5 -0
- gns3server/symbols/affinity/square/gray/server_cluster.svg +9 -0
- gns3server/symbols/affinity/square/gray/shield.svg +5 -0
- gns3server/symbols/affinity/square/gray/statistics.svg +7 -0
- gns3server/symbols/affinity/square/gray/storage.svg +5 -0
- gns3server/symbols/affinity/square/gray/switch.svg +10 -0
- gns3server/symbols/affinity/square/gray/switch_multilayer.svg +9 -0
- gns3server/symbols/affinity/square/gray/tablet.svg +9 -0
- gns3server/symbols/affinity/square/gray/template.svg +4 -0
- gns3server/symbols/affinity/square/gray/tree.svg +5 -0
- gns3server/symbols/affinity/square/gray/user.svg +7 -0
- gns3server/symbols/affinity/square/gray/virtualbox.svg +7 -0
- gns3server/symbols/affinity/square/gray/vm.svg +7 -0
- gns3server/symbols/affinity/square/gray/vmware.svg +7 -0
- gns3server/symbols/affinity/square/gray/vrf.svg +5 -0
- gns3server/symbols/affinity/square/gray/wifi.svg +13 -0
- gns3server/symbols/affinity/square/gray/wlc.svg +7 -0
- gns3server/symbols/affinity/square/gray/xml.svg +10 -0
- gns3server/symbols/affinity/square/green/atm.svg +5 -0
- gns3server/symbols/affinity/square/green/bug.svg +5 -0
- gns3server/symbols/affinity/square/green/camera.svg +5 -0
- gns3server/symbols/affinity/square/green/camera_dome.svg +8 -0
- gns3server/symbols/affinity/square/green/client.svg +5 -0
- gns3server/symbols/affinity/square/green/client_vm.svg +6 -0
- gns3server/symbols/affinity/square/green/cloud.svg +12 -0
- gns3server/symbols/affinity/square/green/coffee.svg +5 -0
- gns3server/symbols/affinity/square/green/cog.svg +5 -0
- gns3server/symbols/affinity/square/green/communications.svg +5 -0
- gns3server/symbols/affinity/square/green/conversation.svg +12 -0
- gns3server/symbols/affinity/square/green/dna.svg +7 -0
- gns3server/symbols/affinity/square/green/dna2.svg +7 -0
- gns3server/symbols/affinity/square/green/docker.svg +11 -0
- gns3server/symbols/affinity/square/green/dslam.svg +5 -0
- gns3server/symbols/affinity/square/green/factory.svg +5 -0
- gns3server/symbols/affinity/square/green/fingerprint.svg +5 -0
- gns3server/symbols/affinity/square/green/firewall.svg +5 -0
- gns3server/symbols/affinity/square/green/firewall3.svg +5 -0
- gns3server/symbols/affinity/square/green/globe.svg +5 -0
- gns3server/symbols/affinity/square/green/grid.svg +5 -0
- gns3server/symbols/affinity/square/green/grid2.svg +5 -0
- gns3server/symbols/affinity/square/green/health.svg +5 -0
- gns3server/symbols/affinity/square/green/house.svg +6 -0
- gns3server/symbols/affinity/square/green/hub.svg +5 -0
- gns3server/symbols/affinity/square/green/inspect.svg +5 -0
- gns3server/symbols/affinity/square/green/inspect2.svg +5 -0
- gns3server/symbols/affinity/square/green/interconnect.svg +5 -0
- gns3server/symbols/affinity/square/green/ip_phone.svg +7 -0
- gns3server/symbols/affinity/square/green/isdn.svg +5 -0
- gns3server/symbols/affinity/square/green/laptop.svg +8 -0
- gns3server/symbols/affinity/square/green/ldap.svg +5 -0
- gns3server/symbols/affinity/square/green/light_bulb.svg +5 -0
- gns3server/symbols/affinity/square/green/link.svg +5 -0
- gns3server/symbols/affinity/square/green/loadbalancer.svg +5 -0
- gns3server/symbols/affinity/square/green/nas.svg +5 -0
- gns3server/symbols/affinity/square/green/nat.svg +58 -0
- gns3server/symbols/affinity/square/green/nat2.svg +74 -0
- gns3server/symbols/affinity/square/green/office.svg +5 -0
- gns3server/symbols/affinity/square/green/optical.svg +8 -0
- gns3server/symbols/affinity/square/green/phone_cloud.svg +6 -0
- gns3server/symbols/affinity/square/green/phone_old.svg +5 -0
- gns3server/symbols/affinity/square/green/phone_wireless.svg +5 -0
- gns3server/symbols/affinity/square/green/pinpoint.svg +5 -0
- gns3server/symbols/affinity/square/green/printer.svg +27 -0
- gns3server/symbols/affinity/square/green/rj45.svg +5 -0
- gns3server/symbols/affinity/square/green/router.svg +5 -0
- gns3server/symbols/affinity/square/green/router2.svg +5 -0
- gns3server/symbols/affinity/square/green/router_cloud.svg +6 -0
- gns3server/symbols/affinity/square/green/satellite.svg +5 -0
- gns3server/symbols/affinity/square/green/satellite_dish.svg +5 -0
- gns3server/symbols/affinity/square/green/scull.svg +8 -0
- gns3server/symbols/affinity/square/green/server.svg +5 -0
- gns3server/symbols/affinity/square/green/server_cluster.svg +7 -0
- gns3server/symbols/affinity/square/green/shield.svg +5 -0
- gns3server/symbols/affinity/square/green/statistics.svg +5 -0
- gns3server/symbols/affinity/square/green/storage.svg +5 -0
- gns3server/symbols/affinity/square/green/switch.svg +10 -0
- gns3server/symbols/affinity/square/green/switch_multilayer.svg +5 -0
- gns3server/symbols/affinity/square/green/tablet.svg +9 -0
- gns3server/symbols/affinity/square/green/template.svg +4 -0
- gns3server/symbols/affinity/square/green/tree.svg +5 -0
- gns3server/symbols/affinity/square/green/user.svg +7 -0
- gns3server/symbols/affinity/square/green/virtualbox.svg +7 -0
- gns3server/symbols/affinity/square/green/vm.svg +7 -0
- gns3server/symbols/affinity/square/green/vmware.svg +7 -0
- gns3server/symbols/affinity/square/green/vrf.svg +5 -0
- gns3server/symbols/affinity/square/green/wifi.svg +5 -0
- gns3server/symbols/affinity/square/green/wlc.svg +5 -0
- gns3server/symbols/affinity/square/green/xml.svg +5 -0
- gns3server/symbols/affinity/square/red/atm.svg +5 -0
- gns3server/symbols/affinity/square/red/bug.svg +5 -0
- gns3server/symbols/affinity/square/red/camera.svg +12 -0
- gns3server/symbols/affinity/square/red/camera_dome.svg +8 -0
- gns3server/symbols/affinity/square/red/client.svg +8 -0
- gns3server/symbols/affinity/square/red/client_vm.svg +8 -0
- gns3server/symbols/affinity/square/red/cloud.svg +12 -0
- gns3server/symbols/affinity/square/red/coffee.svg +5 -0
- gns3server/symbols/affinity/square/red/cog.svg +8 -0
- gns3server/symbols/affinity/square/red/communications.svg +8 -0
- gns3server/symbols/affinity/square/red/conversation.svg +12 -0
- gns3server/symbols/affinity/square/red/dna.svg +7 -0
- gns3server/symbols/affinity/square/red/dna2.svg +7 -0
- gns3server/symbols/affinity/square/red/docker.svg +11 -0
- gns3server/symbols/affinity/square/red/dslam.svg +8 -0
- gns3server/symbols/affinity/square/red/factory.svg +5 -0
- gns3server/symbols/affinity/square/red/fingerprint.svg +9 -0
- gns3server/symbols/affinity/square/red/firewall.svg +7 -0
- gns3server/symbols/affinity/square/red/firewall3.svg +5 -0
- gns3server/symbols/affinity/square/red/globe.svg +5 -0
- gns3server/symbols/affinity/square/red/grid.svg +7 -0
- gns3server/symbols/affinity/square/red/grid2.svg +7 -0
- gns3server/symbols/affinity/square/red/health.svg +5 -0
- gns3server/symbols/affinity/square/red/house.svg +6 -0
- gns3server/symbols/affinity/square/red/hub.svg +7 -0
- gns3server/symbols/affinity/square/red/inspect.svg +5 -0
- gns3server/symbols/affinity/square/red/inspect2.svg +9 -0
- gns3server/symbols/affinity/square/red/interconnect.svg +8 -0
- gns3server/symbols/affinity/square/red/ip_phone.svg +7 -0
- gns3server/symbols/affinity/square/red/isdn.svg +7 -0
- gns3server/symbols/affinity/square/red/laptop.svg +8 -0
- gns3server/symbols/affinity/square/red/ldap.svg +5 -0
- gns3server/symbols/affinity/square/red/light_bulb.svg +5 -0
- gns3server/symbols/affinity/square/red/link.svg +5 -0
- gns3server/symbols/affinity/square/red/loadbalancer.svg +5 -0
- gns3server/symbols/affinity/square/red/nas.svg +7 -0
- gns3server/symbols/affinity/square/red/nat.svg +58 -0
- gns3server/symbols/affinity/square/red/nat2.svg +74 -0
- gns3server/symbols/affinity/square/red/office.svg +5 -0
- gns3server/symbols/affinity/square/red/optical.svg +8 -0
- gns3server/symbols/affinity/square/red/phone_cloud.svg +6 -0
- gns3server/symbols/affinity/square/red/phone_old.svg +5 -0
- gns3server/symbols/affinity/square/red/phone_wireless.svg +5 -0
- gns3server/symbols/affinity/square/red/pinpoint.svg +9 -0
- gns3server/symbols/affinity/square/red/printer.svg +27 -0
- gns3server/symbols/affinity/square/red/rj45.svg +14 -0
- gns3server/symbols/affinity/square/red/router.svg +7 -0
- gns3server/symbols/affinity/square/red/router2.svg +5 -0
- gns3server/symbols/affinity/square/red/router_cloud.svg +6 -0
- gns3server/symbols/affinity/square/red/satellite.svg +8 -0
- gns3server/symbols/affinity/square/red/satellite_dish.svg +5 -0
- gns3server/symbols/affinity/square/red/scull.svg +10 -0
- gns3server/symbols/affinity/square/red/server.svg +5 -0
- gns3server/symbols/affinity/square/red/server_cluster.svg +9 -0
- gns3server/symbols/affinity/square/red/shield.svg +5 -0
- gns3server/symbols/affinity/square/red/statistics.svg +5 -0
- gns3server/symbols/affinity/square/red/storage.svg +7 -0
- gns3server/symbols/affinity/square/red/switch.svg +10 -0
- gns3server/symbols/affinity/square/red/switch_multilayer.svg +9 -0
- gns3server/symbols/affinity/square/red/tablet.svg +9 -0
- gns3server/symbols/affinity/square/red/template.svg +4 -0
- gns3server/symbols/affinity/square/red/tree.svg +5 -0
- gns3server/symbols/affinity/square/red/user.svg +7 -0
- gns3server/symbols/affinity/square/red/virtualbox.svg +7 -0
- gns3server/symbols/affinity/square/red/vm.svg +7 -0
- gns3server/symbols/affinity/square/red/vmware.svg +7 -0
- gns3server/symbols/affinity/square/red/vrf.svg +5 -0
- gns3server/symbols/affinity/square/red/wifi.svg +13 -0
- gns3server/symbols/affinity/square/red/wlc.svg +7 -0
- gns3server/symbols/affinity/square/red/xml.svg +10 -0
- gns3server/symbols/classic/PBX.svg +304 -0
- gns3server/symbols/classic/PIX_firewall.svg +187 -0
- gns3server/symbols/classic/access_point.svg +516 -0
- gns3server/symbols/classic/access_server.svg +270 -0
- gns3server/symbols/classic/asa.svg +424 -0
- gns3server/symbols/classic/atm_bridge.svg +219 -0
- gns3server/symbols/classic/atm_switch.svg +243 -0
- gns3server/symbols/classic/call_manager.svg +228 -0
- gns3server/symbols/classic/cloud.svg +163 -0
- gns3server/symbols/classic/computer.svg +560 -0
- gns3server/symbols/classic/docker_guest.svg +657 -0
- gns3server/symbols/classic/dslam.svg +155 -0
- gns3server/symbols/classic/edge_label_switch_router.svg +216 -0
- gns3server/symbols/classic/ethernet_switch.svg +228 -0
- gns3server/symbols/classic/firewall.svg +187 -0
- gns3server/symbols/classic/frame_relay_switch.svg +263 -0
- gns3server/symbols/classic/gateway.svg +309 -0
- gns3server/symbols/classic/hub.svg +204 -0
- gns3server/symbols/classic/ids.svg +310 -0
- gns3server/symbols/classic/iosv_l2_virl.svg +286 -0
- gns3server/symbols/classic/iosv_virl.svg +394 -0
- gns3server/symbols/classic/ip_phone.svg +171 -0
- gns3server/symbols/classic/label_switch_router.svg +223 -0
- gns3server/symbols/classic/lightweight_ap.svg +536 -0
- gns3server/symbols/classic/multilayer_switch.svg +317 -0
- gns3server/symbols/classic/nat.svg +207 -0
- gns3server/symbols/classic/optical_router.svg +207 -0
- gns3server/symbols/classic/printer.svg +178 -0
- gns3server/symbols/classic/qemu_guest.svg +1387 -0
- gns3server/symbols/classic/route_switch_processor.svg +395 -0
- gns3server/symbols/classic/router.awp.svg +362 -0
- gns3server/symbols/classic/router.svg +203 -0
- gns3server/symbols/classic/router_firewall.svg +395 -0
- gns3server/symbols/classic/router_netflow.svg +215 -0
- gns3server/symbols/classic/server.svg +226 -0
- gns3server/symbols/classic/sip_server.svg +305 -0
- gns3server/symbols/classic/traceng.svg +610 -0
- gns3server/symbols/classic/vbox_guest.svg +7691 -0
- gns3server/symbols/classic/vmware_guest.svg +572 -0
- gns3server/symbols/classic/voice_access_server.svg +289 -0
- gns3server/symbols/classic/voice_router.svg +223 -0
- gns3server/symbols/classic/vpcs_guest.svg +574 -0
- gns3server/symbols/classic/wlan_controller.svg +528 -0
- gns3server/templates/compute.html +62 -0
- gns3server/templates/controller.html +55 -0
- gns3server/templates/index.html +12 -0
- gns3server/templates/layout.html +20 -0
- gns3server/templates/project.html +91 -0
- gns3server/templates/upload.html +6 -0
- gns3server/utils/__init__.py +123 -0
- gns3server/utils/application_id.py +49 -0
- gns3server/utils/asyncio/__init__.py +148 -0
- gns3server/utils/asyncio/aiozipstream.py +528 -0
- gns3server/utils/asyncio/embed_shell.py +369 -0
- gns3server/utils/asyncio/input_stream.py +408 -0
- gns3server/utils/asyncio/pool.py +69 -0
- gns3server/utils/asyncio/raw_command_server.py +140 -0
- gns3server/utils/asyncio/serial.py +87 -0
- gns3server/utils/asyncio/telnet_server.py +450 -0
- gns3server/utils/cpu_percent.py +46 -0
- gns3server/utils/file_watcher.py +103 -0
- gns3server/utils/get_resource.py +48 -0
- gns3server/utils/hostname.py +112 -0
- gns3server/utils/http_client.py +71 -0
- gns3server/utils/images.py +378 -0
- gns3server/utils/interfaces.py +254 -0
- gns3server/utils/notification_queue.py +79 -0
- gns3server/utils/path.py +76 -0
- gns3server/utils/picture.py +146 -0
- gns3server/utils/qt.py +44 -0
- gns3server/utils/vmnet.py +277 -0
- gns3server/utils/zipfile_zstd/__init__.py +10 -0
- gns3server/utils/zipfile_zstd/_patcher.py +20 -0
- gns3server/utils/zipfile_zstd/_zipfile.py +64 -0
- gns3server/version.py +36 -0
|
@@ -0,0 +1,1797 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (C) 2015 GNS3 Technologies Inc.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
Interface for Dynamips virtual Machine module ("vm")
|
|
19
|
+
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L77
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import asyncio
|
|
23
|
+
import time
|
|
24
|
+
import sys
|
|
25
|
+
import os
|
|
26
|
+
import re
|
|
27
|
+
import glob
|
|
28
|
+
import base64
|
|
29
|
+
import shutil
|
|
30
|
+
import binascii
|
|
31
|
+
import logging
|
|
32
|
+
|
|
33
|
+
log = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
from ...base_node import BaseNode
|
|
36
|
+
from ..dynamips_error import DynamipsError
|
|
37
|
+
|
|
38
|
+
from gns3server.utils.file_watcher import FileWatcher
|
|
39
|
+
from gns3server.utils.asyncio import wait_run_in_executor, monitor_process
|
|
40
|
+
from gns3server.utils.hostname import is_ios_hostname_valid
|
|
41
|
+
from gns3server.utils.images import md5sum
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class Router(BaseNode):
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
Dynamips router implementation.
|
|
48
|
+
|
|
49
|
+
:param name: The name of this router
|
|
50
|
+
:param node_id: Node identifier
|
|
51
|
+
:param project: Project instance
|
|
52
|
+
:param manager: Parent VM Manager
|
|
53
|
+
:param dynamips_id: ID to use with Dynamips
|
|
54
|
+
:param console: console port
|
|
55
|
+
:param console_type: console type
|
|
56
|
+
:param aux: auxiliary console port
|
|
57
|
+
:param aux_type: auxiliary console type
|
|
58
|
+
:param platform: Platform of this router
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
_status = {0: "inactive", 1: "shutting down", 2: "running", 3: "suspended"}
|
|
62
|
+
|
|
63
|
+
def __init__(
|
|
64
|
+
self,
|
|
65
|
+
name,
|
|
66
|
+
node_id,
|
|
67
|
+
project,
|
|
68
|
+
manager,
|
|
69
|
+
dynamips_id=None,
|
|
70
|
+
console=None,
|
|
71
|
+
console_type="telnet",
|
|
72
|
+
aux=None,
|
|
73
|
+
aux_type="none",
|
|
74
|
+
platform="c7200",
|
|
75
|
+
hypervisor=None,
|
|
76
|
+
ghost_flag=False,
|
|
77
|
+
):
|
|
78
|
+
|
|
79
|
+
if not ghost_flag and not is_ios_hostname_valid(name):
|
|
80
|
+
raise DynamipsError(f"{name} is an invalid name to create a Dynamips node")
|
|
81
|
+
|
|
82
|
+
super().__init__(
|
|
83
|
+
name, node_id, project, manager, console=console, console_type=console_type, aux=aux, aux_type=aux_type
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
self._working_directory = os.path.join(
|
|
87
|
+
self.project.module_working_directory(self.manager.module_name.lower()), self.id
|
|
88
|
+
)
|
|
89
|
+
try:
|
|
90
|
+
os.makedirs(os.path.join(self._working_directory, "configs"), exist_ok=True)
|
|
91
|
+
except OSError as e:
|
|
92
|
+
raise DynamipsError(f"Can't create the dynamips config directory: {str(e)}")
|
|
93
|
+
if dynamips_id:
|
|
94
|
+
self._convert_before_2_0_0_b3(dynamips_id)
|
|
95
|
+
|
|
96
|
+
self._hypervisor = hypervisor
|
|
97
|
+
self._dynamips_id = dynamips_id
|
|
98
|
+
self._platform = platform
|
|
99
|
+
self._image = ""
|
|
100
|
+
self._ram = 128 # Megabytes
|
|
101
|
+
self._nvram = 128 # Kilobytes
|
|
102
|
+
self._mmap = True
|
|
103
|
+
self._sparsemem = True
|
|
104
|
+
self._clock_divisor = 8
|
|
105
|
+
self._idlepc = ""
|
|
106
|
+
self._idlemax = 500
|
|
107
|
+
self._idlesleep = 30
|
|
108
|
+
self._ghost_file = ""
|
|
109
|
+
self._ghost_status = 0
|
|
110
|
+
self._exec_area = 64
|
|
111
|
+
self._disk0 = 0 # Megabytes
|
|
112
|
+
self._disk1 = 0 # Megabytes
|
|
113
|
+
self._auto_delete_disks = False
|
|
114
|
+
self._mac_addr = ""
|
|
115
|
+
self._system_id = "FTX0945W0MY" # processor board ID in IOS
|
|
116
|
+
self._slots = []
|
|
117
|
+
self._ghost_flag = ghost_flag
|
|
118
|
+
self._memory_watcher = None
|
|
119
|
+
|
|
120
|
+
if not ghost_flag:
|
|
121
|
+
if not dynamips_id:
|
|
122
|
+
self._dynamips_id = manager.get_dynamips_id(project.id)
|
|
123
|
+
else:
|
|
124
|
+
self._dynamips_id = dynamips_id
|
|
125
|
+
manager.take_dynamips_id(project.id, dynamips_id)
|
|
126
|
+
else:
|
|
127
|
+
log.info("Creating a new ghost IOS instance")
|
|
128
|
+
if self._console:
|
|
129
|
+
# Ghost VMs do not need a console port.
|
|
130
|
+
self.console = None
|
|
131
|
+
|
|
132
|
+
self._dynamips_id = 0
|
|
133
|
+
self._name = "Ghost"
|
|
134
|
+
|
|
135
|
+
def _convert_before_2_0_0_b3(self, dynamips_id):
|
|
136
|
+
"""
|
|
137
|
+
Before 2.0.0 beta3 the node didn't have a folder by node
|
|
138
|
+
when we start we move the file, we can't do it in the topology
|
|
139
|
+
conversion due to case of remote servers
|
|
140
|
+
"""
|
|
141
|
+
dynamips_dir = self.project.module_working_directory(self.manager.module_name.lower())
|
|
142
|
+
for path in glob.glob(os.path.join(glob.escape(dynamips_dir), "configs", f"i{dynamips_id}_*")):
|
|
143
|
+
dst = os.path.join(self._working_directory, "configs", os.path.basename(path))
|
|
144
|
+
if not os.path.exists(dst):
|
|
145
|
+
try:
|
|
146
|
+
shutil.move(path, dst)
|
|
147
|
+
except OSError as e:
|
|
148
|
+
log.error(f"Can't move {path}: {str(e)}")
|
|
149
|
+
continue
|
|
150
|
+
for path in glob.glob(os.path.join(glob.escape(dynamips_dir), f"*_i{dynamips_id}_*")):
|
|
151
|
+
dst = os.path.join(self._working_directory, os.path.basename(path))
|
|
152
|
+
if not os.path.exists(dst):
|
|
153
|
+
try:
|
|
154
|
+
shutil.move(path, dst)
|
|
155
|
+
except OSError as e:
|
|
156
|
+
log.error(f"Can't move {path}: {str(e)}")
|
|
157
|
+
continue
|
|
158
|
+
|
|
159
|
+
def asdict(self):
|
|
160
|
+
|
|
161
|
+
router_info = {
|
|
162
|
+
"name": self.name,
|
|
163
|
+
"usage": self.usage,
|
|
164
|
+
"node_id": self.id,
|
|
165
|
+
"node_directory": os.path.join(self._working_directory),
|
|
166
|
+
"project_id": self.project.id,
|
|
167
|
+
"dynamips_id": self._dynamips_id,
|
|
168
|
+
"platform": self._platform,
|
|
169
|
+
"image": self._image,
|
|
170
|
+
"image_md5sum": md5sum(self._image, self._working_directory),
|
|
171
|
+
"ram": self._ram,
|
|
172
|
+
"nvram": self._nvram,
|
|
173
|
+
"mmap": self._mmap,
|
|
174
|
+
"sparsemem": self._sparsemem,
|
|
175
|
+
"clock_divisor": self._clock_divisor,
|
|
176
|
+
"idlepc": self._idlepc,
|
|
177
|
+
"idlemax": self._idlemax,
|
|
178
|
+
"idlesleep": self._idlesleep,
|
|
179
|
+
"exec_area": self._exec_area,
|
|
180
|
+
"disk0": self._disk0,
|
|
181
|
+
"disk1": self._disk1,
|
|
182
|
+
"auto_delete_disks": self._auto_delete_disks,
|
|
183
|
+
"status": self.status,
|
|
184
|
+
"console": self.console,
|
|
185
|
+
"console_type": self.console_type,
|
|
186
|
+
"aux": self.aux,
|
|
187
|
+
"aux_type": self.aux_type,
|
|
188
|
+
"mac_addr": self._mac_addr,
|
|
189
|
+
"system_id": self._system_id,
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
router_info["image"] = self.manager.get_relative_image_path(self._image, self.project.path)
|
|
193
|
+
|
|
194
|
+
# add the slots
|
|
195
|
+
slot_number = 0
|
|
196
|
+
for slot in self._slots:
|
|
197
|
+
if slot:
|
|
198
|
+
slot = str(slot)
|
|
199
|
+
router_info["slot" + str(slot_number)] = slot
|
|
200
|
+
slot_number += 1
|
|
201
|
+
|
|
202
|
+
# add the wics
|
|
203
|
+
if len(self._slots) > 0 and self._slots[0] and self._slots[0].wics:
|
|
204
|
+
for wic_slot_number in range(0, len(self._slots[0].wics)):
|
|
205
|
+
if self._slots[0].wics[wic_slot_number]:
|
|
206
|
+
router_info["wic" + str(wic_slot_number)] = str(self._slots[0].wics[wic_slot_number])
|
|
207
|
+
else:
|
|
208
|
+
router_info["wic" + str(wic_slot_number)] = None
|
|
209
|
+
|
|
210
|
+
return router_info
|
|
211
|
+
|
|
212
|
+
def _memory_changed(self, path):
|
|
213
|
+
"""
|
|
214
|
+
Called when the NVRAM file has changed
|
|
215
|
+
"""
|
|
216
|
+
asyncio.ensure_future(self.save_configs())
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def dynamips_id(self):
|
|
220
|
+
"""
|
|
221
|
+
Returns the Dynamips VM ID.
|
|
222
|
+
|
|
223
|
+
:return: Dynamips VM identifier
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
return self._dynamips_id
|
|
227
|
+
|
|
228
|
+
async def create(self):
|
|
229
|
+
|
|
230
|
+
if not self._hypervisor:
|
|
231
|
+
# We start the hypervisor is the dynamips folder and next we change to node dir
|
|
232
|
+
# this allow the creation of common files in the dynamips folder
|
|
233
|
+
self._hypervisor = await self.manager.start_new_hypervisor(
|
|
234
|
+
working_dir=self.project.module_working_directory(self.manager.module_name.lower())
|
|
235
|
+
)
|
|
236
|
+
await self._hypervisor.set_working_dir(self._working_directory)
|
|
237
|
+
|
|
238
|
+
await self._hypervisor.send(
|
|
239
|
+
'vm create "{name}" {id} {platform}'.format(name=self._name, id=self._dynamips_id, platform=self._platform)
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
if not self._ghost_flag:
|
|
243
|
+
|
|
244
|
+
log.info(
|
|
245
|
+
'Router {platform} "{name}" [{id}] has been created'.format(
|
|
246
|
+
name=self._name, platform=self._platform, id=self._id
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
if self._console is not None:
|
|
251
|
+
await self._hypervisor.send(f'vm set_con_tcp_port "{self._name}" {self._console}')
|
|
252
|
+
|
|
253
|
+
if self.aux is not None:
|
|
254
|
+
await self._hypervisor.send(f'vm set_aux_tcp_port "{self._name}" {self.aux}')
|
|
255
|
+
|
|
256
|
+
# get the default base MAC address
|
|
257
|
+
mac_addr = await self._hypervisor.send(f'{self._platform} get_mac_addr "{self._name}"')
|
|
258
|
+
self._mac_addr = mac_addr[0]
|
|
259
|
+
|
|
260
|
+
self._hypervisor.devices.append(self)
|
|
261
|
+
|
|
262
|
+
async def get_status(self):
|
|
263
|
+
"""
|
|
264
|
+
Returns the status of this router
|
|
265
|
+
|
|
266
|
+
:returns: inactive, shutting down, running or suspended.
|
|
267
|
+
"""
|
|
268
|
+
|
|
269
|
+
status = await self._hypervisor.send(f'vm get_status "{self._name}"')
|
|
270
|
+
if len(status) == 0:
|
|
271
|
+
raise DynamipsError(f"Can't get vm {self._name} status")
|
|
272
|
+
return self._status[int(status[0])]
|
|
273
|
+
|
|
274
|
+
async def start(self):
|
|
275
|
+
"""
|
|
276
|
+
Starts this router.
|
|
277
|
+
At least the IOS image must be set before it can start.
|
|
278
|
+
"""
|
|
279
|
+
|
|
280
|
+
status = await self.get_status()
|
|
281
|
+
if status == "suspended":
|
|
282
|
+
await self.resume()
|
|
283
|
+
elif status == "inactive":
|
|
284
|
+
|
|
285
|
+
if not os.path.isfile(self._image) or not os.path.exists(self._image):
|
|
286
|
+
if os.path.islink(self._image):
|
|
287
|
+
raise DynamipsError(
|
|
288
|
+
f'IOS image "{self._image}" linked to "{os.path.realpath(self._image)}" is not accessible'
|
|
289
|
+
)
|
|
290
|
+
else:
|
|
291
|
+
raise DynamipsError(f'IOS image "{self._image}" is not accessible')
|
|
292
|
+
|
|
293
|
+
try:
|
|
294
|
+
with open(self._image, "rb") as f:
|
|
295
|
+
# read the first 7 bytes of the file.
|
|
296
|
+
elf_header_start = f.read(7)
|
|
297
|
+
except OSError as e:
|
|
298
|
+
raise DynamipsError(f'Cannot read ELF header for IOS image "{self._image}": {e}')
|
|
299
|
+
|
|
300
|
+
# IOS images must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
|
|
301
|
+
if elf_header_start != b"\x7fELF\x01\x02\x01":
|
|
302
|
+
raise DynamipsError(f'"{self._image}" is not a valid IOS image')
|
|
303
|
+
|
|
304
|
+
# check if there is enough RAM to run
|
|
305
|
+
if not self._ghost_flag:
|
|
306
|
+
self.check_available_ram(self.ram)
|
|
307
|
+
|
|
308
|
+
# config paths are relative to the working directory configured on Dynamips hypervisor
|
|
309
|
+
startup_config_path = os.path.join("configs", f"i{self._dynamips_id}_startup-config.cfg")
|
|
310
|
+
private_config_path = os.path.join("configs", f"i{self._dynamips_id}_private-config.cfg")
|
|
311
|
+
|
|
312
|
+
if not os.path.exists(os.path.join(self._working_directory, private_config_path)) or not os.path.getsize(
|
|
313
|
+
os.path.join(self._working_directory, private_config_path)
|
|
314
|
+
):
|
|
315
|
+
# an empty private-config can prevent a router to boot.
|
|
316
|
+
private_config_path = ""
|
|
317
|
+
|
|
318
|
+
await self._hypervisor.send(
|
|
319
|
+
'vm set_config "{name}" "{startup}" "{private}"'.format(
|
|
320
|
+
name=self._name, startup=startup_config_path, private=private_config_path
|
|
321
|
+
)
|
|
322
|
+
)
|
|
323
|
+
await self._hypervisor.send(f'vm start "{self._name}"')
|
|
324
|
+
self.status = "started"
|
|
325
|
+
log.info(f'router "{self._name}" [{self._id}] has been started')
|
|
326
|
+
|
|
327
|
+
self._memory_watcher = FileWatcher(self._memory_files(), self._memory_changed, strategy="hash", delay=30)
|
|
328
|
+
monitor_process(self._hypervisor.process, self._termination_callback)
|
|
329
|
+
|
|
330
|
+
async def _termination_callback(self, returncode):
|
|
331
|
+
"""
|
|
332
|
+
Called when the process has stopped.
|
|
333
|
+
|
|
334
|
+
:param returncode: Process returncode
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
if self.status == "started":
|
|
338
|
+
self.status = "stopped"
|
|
339
|
+
log.info("Dynamips hypervisor process has stopped, return code: %d", returncode)
|
|
340
|
+
if returncode != 0:
|
|
341
|
+
self.project.emit(
|
|
342
|
+
"log.error",
|
|
343
|
+
{
|
|
344
|
+
"message": f"Dynamips hypervisor process has stopped, return code: {returncode}\n{self._hypervisor.read_stdout()}"
|
|
345
|
+
},
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
async def stop(self):
|
|
349
|
+
"""
|
|
350
|
+
Stops this router.
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
status = await self.get_status()
|
|
354
|
+
if status != "inactive":
|
|
355
|
+
try:
|
|
356
|
+
await self._hypervisor.send(f'vm stop "{self._name}"')
|
|
357
|
+
except DynamipsError as e:
|
|
358
|
+
log.warning(f"Could not stop {self._name}: {e}")
|
|
359
|
+
self.status = "stopped"
|
|
360
|
+
log.info(f'Router "{self._name}" [{self._id}] has been stopped')
|
|
361
|
+
if self._memory_watcher:
|
|
362
|
+
self._memory_watcher.close()
|
|
363
|
+
self._memory_watcher = None
|
|
364
|
+
await self.save_configs()
|
|
365
|
+
|
|
366
|
+
async def reload(self):
|
|
367
|
+
"""
|
|
368
|
+
Reload this router.
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
await self.stop()
|
|
372
|
+
await self.start()
|
|
373
|
+
|
|
374
|
+
async def suspend(self):
|
|
375
|
+
"""
|
|
376
|
+
Suspends this router.
|
|
377
|
+
"""
|
|
378
|
+
|
|
379
|
+
status = await self.get_status()
|
|
380
|
+
if status == "running":
|
|
381
|
+
await self._hypervisor.send(f'vm suspend "{self._name}"')
|
|
382
|
+
self.status = "suspended"
|
|
383
|
+
log.info(f'Router "{self._name}" [{self._id}] has been suspended')
|
|
384
|
+
|
|
385
|
+
async def resume(self):
|
|
386
|
+
"""
|
|
387
|
+
Resumes this suspended router
|
|
388
|
+
"""
|
|
389
|
+
|
|
390
|
+
status = await self.get_status()
|
|
391
|
+
if status == "suspended":
|
|
392
|
+
await self._hypervisor.send(f'vm resume "{self._name}"')
|
|
393
|
+
self.status = "started"
|
|
394
|
+
log.info(f'Router "{self._name}" [{self._id}] has been resumed')
|
|
395
|
+
|
|
396
|
+
async def is_running(self):
|
|
397
|
+
"""
|
|
398
|
+
Checks if this router is running.
|
|
399
|
+
|
|
400
|
+
:returns: True if running, False otherwise
|
|
401
|
+
"""
|
|
402
|
+
|
|
403
|
+
status = await self.get_status()
|
|
404
|
+
if status == "running":
|
|
405
|
+
return True
|
|
406
|
+
return False
|
|
407
|
+
|
|
408
|
+
async def close(self):
|
|
409
|
+
|
|
410
|
+
if not (await super().close()):
|
|
411
|
+
return False
|
|
412
|
+
|
|
413
|
+
for adapter in self._slots:
|
|
414
|
+
if adapter is not None:
|
|
415
|
+
for nio in adapter.ports.values():
|
|
416
|
+
if nio:
|
|
417
|
+
await nio.close()
|
|
418
|
+
|
|
419
|
+
await self._stop_ubridge()
|
|
420
|
+
|
|
421
|
+
if self in self._hypervisor.devices:
|
|
422
|
+
self._hypervisor.devices.remove(self)
|
|
423
|
+
if self._hypervisor and not self._hypervisor.devices:
|
|
424
|
+
try:
|
|
425
|
+
await self.stop()
|
|
426
|
+
await self._hypervisor.send(f'vm delete "{self._name}"')
|
|
427
|
+
except DynamipsError as e:
|
|
428
|
+
log.warning(f"Could not stop and delete {self._name}: {e}")
|
|
429
|
+
await self.hypervisor.stop()
|
|
430
|
+
|
|
431
|
+
if self._auto_delete_disks:
|
|
432
|
+
# delete nvram and disk files
|
|
433
|
+
files = glob.glob(
|
|
434
|
+
os.path.join(glob.escape(self._working_directory), f"{self.platform}_i{self.dynamips_id}_disk[0-1]")
|
|
435
|
+
)
|
|
436
|
+
files += glob.glob(
|
|
437
|
+
os.path.join(glob.escape(self._working_directory), f"{self.platform}_i{self.dynamips_id}_slot[0-1]")
|
|
438
|
+
)
|
|
439
|
+
files += glob.glob(
|
|
440
|
+
os.path.join(glob.escape(self._working_directory), f"{self.platform}_i{self.dynamips_id}_nvram")
|
|
441
|
+
)
|
|
442
|
+
files += glob.glob(
|
|
443
|
+
os.path.join(glob.escape(self._working_directory), f"{self.platform}_i{self.dynamips_id}_flash[0-1]")
|
|
444
|
+
)
|
|
445
|
+
files += glob.glob(
|
|
446
|
+
os.path.join(glob.escape(self._working_directory), f"{self.platform}_i{self.dynamips_id}_rom")
|
|
447
|
+
)
|
|
448
|
+
files += glob.glob(
|
|
449
|
+
os.path.join(glob.escape(self._working_directory), f"{self.platform}_i{self.dynamips_id}_bootflash")
|
|
450
|
+
)
|
|
451
|
+
files += glob.glob(
|
|
452
|
+
os.path.join(glob.escape(self._working_directory), f"{self.platform}_i{self.dynamips_id}_ssa")
|
|
453
|
+
)
|
|
454
|
+
for file in files:
|
|
455
|
+
try:
|
|
456
|
+
log.debug(f"Deleting file {file}")
|
|
457
|
+
await wait_run_in_executor(os.remove, file)
|
|
458
|
+
except OSError as e:
|
|
459
|
+
log.warning(f"Could not delete file {file}: {e}")
|
|
460
|
+
continue
|
|
461
|
+
self.manager.release_dynamips_id(self.project.id, self.dynamips_id)
|
|
462
|
+
|
|
463
|
+
@property
|
|
464
|
+
def platform(self):
|
|
465
|
+
"""
|
|
466
|
+
Returns the platform of this router.
|
|
467
|
+
|
|
468
|
+
:returns: platform name (string):
|
|
469
|
+
c7200, c3745, c3725, c3600, c2691, c2600 or c1700
|
|
470
|
+
"""
|
|
471
|
+
|
|
472
|
+
return self._platform
|
|
473
|
+
|
|
474
|
+
@property
|
|
475
|
+
def hypervisor(self):
|
|
476
|
+
"""
|
|
477
|
+
Returns the current hypervisor.
|
|
478
|
+
|
|
479
|
+
:returns: hypervisor instance
|
|
480
|
+
"""
|
|
481
|
+
|
|
482
|
+
return self._hypervisor
|
|
483
|
+
|
|
484
|
+
async def list(self):
|
|
485
|
+
"""
|
|
486
|
+
Returns all VM instances
|
|
487
|
+
|
|
488
|
+
:returns: list of all VM instances
|
|
489
|
+
"""
|
|
490
|
+
|
|
491
|
+
vm_list = await self._hypervisor.send("vm list")
|
|
492
|
+
return vm_list
|
|
493
|
+
|
|
494
|
+
async def list_con_ports(self):
|
|
495
|
+
"""
|
|
496
|
+
Returns all VM console TCP ports
|
|
497
|
+
|
|
498
|
+
:returns: list of port numbers
|
|
499
|
+
"""
|
|
500
|
+
|
|
501
|
+
port_list = await self._hypervisor.send("vm list_con_ports")
|
|
502
|
+
return port_list
|
|
503
|
+
|
|
504
|
+
async def set_debug_level(self, level):
|
|
505
|
+
"""
|
|
506
|
+
Sets the debug level for this router (default is 0).
|
|
507
|
+
|
|
508
|
+
:param level: level number
|
|
509
|
+
"""
|
|
510
|
+
|
|
511
|
+
await self._hypervisor.send(f'vm set_debug_level "{self._name}" {level}')
|
|
512
|
+
|
|
513
|
+
@property
|
|
514
|
+
def image(self):
|
|
515
|
+
"""
|
|
516
|
+
Returns this IOS image for this router.
|
|
517
|
+
|
|
518
|
+
:returns: path to IOS image file
|
|
519
|
+
"""
|
|
520
|
+
|
|
521
|
+
return self._image
|
|
522
|
+
|
|
523
|
+
async def set_image(self, image):
|
|
524
|
+
"""
|
|
525
|
+
Sets the IOS image for this router.
|
|
526
|
+
There is no default.
|
|
527
|
+
|
|
528
|
+
:param image: path to IOS image file
|
|
529
|
+
"""
|
|
530
|
+
|
|
531
|
+
image = self.manager.get_abs_image_path(image, self.project.path)
|
|
532
|
+
|
|
533
|
+
await self._hypervisor.send(f'vm set_ios "{self._name}" "{image}"')
|
|
534
|
+
|
|
535
|
+
log.info(
|
|
536
|
+
'Router "{name}" [{id}]: has a new IOS image set: "{image}"'.format(
|
|
537
|
+
name=self._name, id=self._id, image=image
|
|
538
|
+
)
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
self._image = image
|
|
542
|
+
|
|
543
|
+
@property
|
|
544
|
+
def ram(self):
|
|
545
|
+
"""
|
|
546
|
+
Returns the amount of RAM allocated to this router.
|
|
547
|
+
|
|
548
|
+
:returns: amount of RAM in Mbytes (integer)
|
|
549
|
+
"""
|
|
550
|
+
|
|
551
|
+
return self._ram
|
|
552
|
+
|
|
553
|
+
async def set_ram(self, ram):
|
|
554
|
+
"""
|
|
555
|
+
Sets amount of RAM allocated to this router
|
|
556
|
+
|
|
557
|
+
:param ram: amount of RAM in Mbytes (integer)
|
|
558
|
+
"""
|
|
559
|
+
|
|
560
|
+
if self._ram == ram:
|
|
561
|
+
return
|
|
562
|
+
|
|
563
|
+
await self._hypervisor.send(f'vm set_ram "{self._name}" {ram}')
|
|
564
|
+
log.info(
|
|
565
|
+
'Router "{name}" [{id}]: RAM updated from {old_ram}MB to {new_ram}MB'.format(
|
|
566
|
+
name=self._name, id=self._id, old_ram=self._ram, new_ram=ram
|
|
567
|
+
)
|
|
568
|
+
)
|
|
569
|
+
self._ram = ram
|
|
570
|
+
|
|
571
|
+
@property
|
|
572
|
+
def nvram(self):
|
|
573
|
+
"""
|
|
574
|
+
Returns the mount of NVRAM allocated to this router.
|
|
575
|
+
|
|
576
|
+
:returns: amount of NVRAM in Kbytes (integer)
|
|
577
|
+
"""
|
|
578
|
+
|
|
579
|
+
return self._nvram
|
|
580
|
+
|
|
581
|
+
async def set_nvram(self, nvram):
|
|
582
|
+
"""
|
|
583
|
+
Sets amount of NVRAM allocated to this router
|
|
584
|
+
|
|
585
|
+
:param nvram: amount of NVRAM in Kbytes (integer)
|
|
586
|
+
"""
|
|
587
|
+
|
|
588
|
+
if self._nvram == nvram:
|
|
589
|
+
return
|
|
590
|
+
|
|
591
|
+
await self._hypervisor.send(f'vm set_nvram "{self._name}" {nvram}')
|
|
592
|
+
log.info(
|
|
593
|
+
'Router "{name}" [{id}]: NVRAM updated from {old_nvram}KB to {new_nvram}KB'.format(
|
|
594
|
+
name=self._name, id=self._id, old_nvram=self._nvram, new_nvram=nvram
|
|
595
|
+
)
|
|
596
|
+
)
|
|
597
|
+
self._nvram = nvram
|
|
598
|
+
|
|
599
|
+
@property
|
|
600
|
+
def mmap(self):
|
|
601
|
+
"""
|
|
602
|
+
Returns True if a mapped file is used to simulate this router memory.
|
|
603
|
+
|
|
604
|
+
:returns: boolean either mmap is activated or not
|
|
605
|
+
"""
|
|
606
|
+
|
|
607
|
+
return self._mmap
|
|
608
|
+
|
|
609
|
+
async def set_mmap(self, mmap):
|
|
610
|
+
"""
|
|
611
|
+
Enable/Disable use of a mapped file to simulate router memory.
|
|
612
|
+
By default, a mapped file is used. This is a bit slower, but requires less memory.
|
|
613
|
+
|
|
614
|
+
:param mmap: activate/deactivate mmap (boolean)
|
|
615
|
+
"""
|
|
616
|
+
|
|
617
|
+
if mmap:
|
|
618
|
+
flag = 1
|
|
619
|
+
else:
|
|
620
|
+
flag = 0
|
|
621
|
+
|
|
622
|
+
await self._hypervisor.send(f'vm set_ram_mmap "{self._name}" {flag}')
|
|
623
|
+
|
|
624
|
+
if mmap:
|
|
625
|
+
log.info(f'Router "{self._name}" [{self._id}]: mmap enabled')
|
|
626
|
+
else:
|
|
627
|
+
log.info(f'Router "{self._name}" [{self._id}]: mmap disabled')
|
|
628
|
+
self._mmap = mmap
|
|
629
|
+
|
|
630
|
+
@property
|
|
631
|
+
def sparsemem(self):
|
|
632
|
+
"""
|
|
633
|
+
Returns True if sparse memory is used on this router.
|
|
634
|
+
|
|
635
|
+
:returns: boolean either mmap is activated or not
|
|
636
|
+
"""
|
|
637
|
+
|
|
638
|
+
return self._sparsemem
|
|
639
|
+
|
|
640
|
+
async def set_sparsemem(self, sparsemem):
|
|
641
|
+
"""
|
|
642
|
+
Enable/disable use of sparse memory
|
|
643
|
+
|
|
644
|
+
:param sparsemem: activate/deactivate sparsemem (boolean)
|
|
645
|
+
"""
|
|
646
|
+
|
|
647
|
+
if sparsemem:
|
|
648
|
+
flag = 1
|
|
649
|
+
else:
|
|
650
|
+
flag = 0
|
|
651
|
+
await self._hypervisor.send(f'vm set_sparse_mem "{self._name}" {flag}')
|
|
652
|
+
|
|
653
|
+
if sparsemem:
|
|
654
|
+
log.info(f'Router "{self._name}" [{self._id}]: sparse memory enabled')
|
|
655
|
+
else:
|
|
656
|
+
log.info(f'Router "{self._name}" [{self._id}]: sparse memory disabled')
|
|
657
|
+
self._sparsemem = sparsemem
|
|
658
|
+
|
|
659
|
+
@property
|
|
660
|
+
def clock_divisor(self):
|
|
661
|
+
"""
|
|
662
|
+
Returns the clock divisor value for this router.
|
|
663
|
+
|
|
664
|
+
:returns: clock divisor value (integer)
|
|
665
|
+
"""
|
|
666
|
+
|
|
667
|
+
return self._clock_divisor
|
|
668
|
+
|
|
669
|
+
async def set_clock_divisor(self, clock_divisor):
|
|
670
|
+
"""
|
|
671
|
+
Sets the clock divisor value. The higher is the value, the faster is the clock in the
|
|
672
|
+
virtual machine. The default is 4, but it is often required to adjust it.
|
|
673
|
+
|
|
674
|
+
:param clock_divisor: clock divisor value (integer)
|
|
675
|
+
"""
|
|
676
|
+
|
|
677
|
+
await self._hypervisor.send(f'vm set_clock_divisor "{self._name}" {clock_divisor}')
|
|
678
|
+
log.info(
|
|
679
|
+
'Router "{name}" [{id}]: clock divisor updated from {old_clock} to {new_clock}'.format(
|
|
680
|
+
name=self._name, id=self._id, old_clock=self._clock_divisor, new_clock=clock_divisor
|
|
681
|
+
)
|
|
682
|
+
)
|
|
683
|
+
self._clock_divisor = clock_divisor
|
|
684
|
+
|
|
685
|
+
@property
|
|
686
|
+
def idlepc(self):
|
|
687
|
+
"""
|
|
688
|
+
Returns the idle Pointer Counter (PC).
|
|
689
|
+
|
|
690
|
+
:returns: idlepc value (string)
|
|
691
|
+
"""
|
|
692
|
+
|
|
693
|
+
return self._idlepc
|
|
694
|
+
|
|
695
|
+
async def set_idlepc(self, idlepc):
|
|
696
|
+
"""
|
|
697
|
+
Sets the idle Pointer Counter (PC)
|
|
698
|
+
|
|
699
|
+
:param idlepc: idlepc value (string)
|
|
700
|
+
"""
|
|
701
|
+
|
|
702
|
+
if not idlepc:
|
|
703
|
+
idlepc = "0x0"
|
|
704
|
+
|
|
705
|
+
is_running = await self.is_running()
|
|
706
|
+
if not is_running:
|
|
707
|
+
# router is not running
|
|
708
|
+
await self._hypervisor.send(f'vm set_idle_pc "{self._name}" {idlepc}')
|
|
709
|
+
else:
|
|
710
|
+
await self._hypervisor.send(f'vm set_idle_pc_online "{self._name}" 0 {idlepc}')
|
|
711
|
+
|
|
712
|
+
log.info(f'Router "{self._name}" [{self._id}]: idle-PC set to {idlepc}')
|
|
713
|
+
self._idlepc = idlepc
|
|
714
|
+
|
|
715
|
+
async def get_idle_pc_prop(self):
|
|
716
|
+
"""
|
|
717
|
+
Gets the idle PC proposals.
|
|
718
|
+
Takes 1000 measurements and records up to 10 idle PC proposals.
|
|
719
|
+
There is a 10ms wait between each measurement.
|
|
720
|
+
|
|
721
|
+
:returns: list of idle PC proposal
|
|
722
|
+
"""
|
|
723
|
+
|
|
724
|
+
is_running = await self.is_running()
|
|
725
|
+
was_auto_started = False
|
|
726
|
+
if not is_running:
|
|
727
|
+
await self.start()
|
|
728
|
+
was_auto_started = True
|
|
729
|
+
await asyncio.sleep(20) # leave time to the router to boot
|
|
730
|
+
|
|
731
|
+
log.info(f'Router "{self._name}" [{self._id}] has started calculating Idle-PC values')
|
|
732
|
+
begin = time.time()
|
|
733
|
+
idlepcs = await self._hypervisor.send(f'vm get_idle_pc_prop "{self._name}" 0')
|
|
734
|
+
log.info(
|
|
735
|
+
'Router "{name}" [{id}] has finished calculating Idle-PC values after {time:.4f} seconds'.format(
|
|
736
|
+
name=self._name, id=self._id, time=time.time() - begin
|
|
737
|
+
)
|
|
738
|
+
)
|
|
739
|
+
if was_auto_started:
|
|
740
|
+
await self.stop()
|
|
741
|
+
return idlepcs
|
|
742
|
+
|
|
743
|
+
async def show_idle_pc_prop(self):
|
|
744
|
+
"""
|
|
745
|
+
Dumps the idle PC proposals (previously generated).
|
|
746
|
+
|
|
747
|
+
:returns: list of idle PC proposal
|
|
748
|
+
"""
|
|
749
|
+
|
|
750
|
+
is_running = await self.is_running()
|
|
751
|
+
if not is_running:
|
|
752
|
+
# router is not running
|
|
753
|
+
raise DynamipsError(f'Router "{self._name}" is not running')
|
|
754
|
+
|
|
755
|
+
proposals = await self._hypervisor.send(f'vm show_idle_pc_prop "{self._name}" 0')
|
|
756
|
+
return proposals
|
|
757
|
+
|
|
758
|
+
@property
|
|
759
|
+
def idlemax(self):
|
|
760
|
+
"""
|
|
761
|
+
Returns CPU idle max value.
|
|
762
|
+
|
|
763
|
+
:returns: idle max (integer)
|
|
764
|
+
"""
|
|
765
|
+
|
|
766
|
+
return self._idlemax
|
|
767
|
+
|
|
768
|
+
async def set_idlemax(self, idlemax):
|
|
769
|
+
"""
|
|
770
|
+
Sets CPU idle max value
|
|
771
|
+
|
|
772
|
+
:param idlemax: idle max value (integer)
|
|
773
|
+
"""
|
|
774
|
+
|
|
775
|
+
is_running = await self.is_running()
|
|
776
|
+
if is_running: # router is running
|
|
777
|
+
await self._hypervisor.send(f'vm set_idle_max "{self._name}" 0 {idlemax}')
|
|
778
|
+
|
|
779
|
+
log.info(
|
|
780
|
+
'Router "{name}" [{id}]: idlemax updated from {old_idlemax} to {new_idlemax}'.format(
|
|
781
|
+
name=self._name, id=self._id, old_idlemax=self._idlemax, new_idlemax=idlemax
|
|
782
|
+
)
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
self._idlemax = idlemax
|
|
786
|
+
|
|
787
|
+
@property
|
|
788
|
+
def idlesleep(self):
|
|
789
|
+
"""
|
|
790
|
+
Returns CPU idle sleep time value.
|
|
791
|
+
|
|
792
|
+
:returns: idle sleep (integer)
|
|
793
|
+
"""
|
|
794
|
+
|
|
795
|
+
return self._idlesleep
|
|
796
|
+
|
|
797
|
+
async def set_idlesleep(self, idlesleep):
|
|
798
|
+
"""
|
|
799
|
+
Sets CPU idle sleep time value.
|
|
800
|
+
|
|
801
|
+
:param idlesleep: idle sleep value (integer)
|
|
802
|
+
"""
|
|
803
|
+
|
|
804
|
+
is_running = await self.is_running()
|
|
805
|
+
if is_running: # router is running
|
|
806
|
+
await self._hypervisor.send(
|
|
807
|
+
'vm set_idle_sleep_time "{name}" 0 {idlesleep}'.format(name=self._name, idlesleep=idlesleep)
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
log.info(
|
|
811
|
+
'Router "{name}" [{id}]: idlesleep updated from {old_idlesleep} to {new_idlesleep}'.format(
|
|
812
|
+
name=self._name, id=self._id, old_idlesleep=self._idlesleep, new_idlesleep=idlesleep
|
|
813
|
+
)
|
|
814
|
+
)
|
|
815
|
+
|
|
816
|
+
self._idlesleep = idlesleep
|
|
817
|
+
|
|
818
|
+
@property
|
|
819
|
+
def ghost_file(self):
|
|
820
|
+
"""
|
|
821
|
+
Returns ghost RAM file.
|
|
822
|
+
|
|
823
|
+
:returns: path to ghost file
|
|
824
|
+
"""
|
|
825
|
+
|
|
826
|
+
return self._ghost_file
|
|
827
|
+
|
|
828
|
+
async def set_ghost_file(self, ghost_file):
|
|
829
|
+
"""
|
|
830
|
+
Sets ghost RAM file
|
|
831
|
+
|
|
832
|
+
:ghost_file: path to ghost file
|
|
833
|
+
"""
|
|
834
|
+
|
|
835
|
+
await self._hypervisor.send(
|
|
836
|
+
'vm set_ghost_file "{name}" "{ghost_file}"'.format(name=self._name, ghost_file=ghost_file)
|
|
837
|
+
)
|
|
838
|
+
|
|
839
|
+
log.info(
|
|
840
|
+
'Router "{name}" [{id}]: ghost file set to "{ghost_file}"'.format(
|
|
841
|
+
name=self._name, id=self._id, ghost_file=ghost_file
|
|
842
|
+
)
|
|
843
|
+
)
|
|
844
|
+
|
|
845
|
+
self._ghost_file = ghost_file
|
|
846
|
+
|
|
847
|
+
def formatted_ghost_file(self):
|
|
848
|
+
"""
|
|
849
|
+
Returns a properly formatted ghost file name.
|
|
850
|
+
|
|
851
|
+
:returns: formatted ghost_file name (string)
|
|
852
|
+
"""
|
|
853
|
+
|
|
854
|
+
# replace specials characters in 'drive:\filename' in Linux and Dynamips in MS Windows or viceversa.
|
|
855
|
+
ghost_file = f"{os.path.basename(self._image)}-{self._ram}.ghost"
|
|
856
|
+
ghost_file = ghost_file.replace("\\", "-").replace("/", "-").replace(":", "-")
|
|
857
|
+
return ghost_file
|
|
858
|
+
|
|
859
|
+
@property
|
|
860
|
+
def ghost_status(self):
|
|
861
|
+
"""Returns ghost RAM status
|
|
862
|
+
|
|
863
|
+
:returns: ghost status (integer)
|
|
864
|
+
"""
|
|
865
|
+
|
|
866
|
+
return self._ghost_status
|
|
867
|
+
|
|
868
|
+
async def set_ghost_status(self, ghost_status):
|
|
869
|
+
"""
|
|
870
|
+
Sets ghost RAM status
|
|
871
|
+
|
|
872
|
+
:param ghost_status: state flag indicating status
|
|
873
|
+
0 => Do not use IOS ghosting
|
|
874
|
+
1 => This is a ghost instance
|
|
875
|
+
2 => Use an existing ghost instance
|
|
876
|
+
"""
|
|
877
|
+
|
|
878
|
+
await self._hypervisor.send(
|
|
879
|
+
'vm set_ghost_status "{name}" {ghost_status}'.format(name=self._name, ghost_status=ghost_status)
|
|
880
|
+
)
|
|
881
|
+
|
|
882
|
+
log.info(
|
|
883
|
+
'Router "{name}" [{id}]: ghost status set to {ghost_status}'.format(
|
|
884
|
+
name=self._name, id=self._id, ghost_status=ghost_status
|
|
885
|
+
)
|
|
886
|
+
)
|
|
887
|
+
self._ghost_status = ghost_status
|
|
888
|
+
|
|
889
|
+
@property
|
|
890
|
+
def exec_area(self):
|
|
891
|
+
"""
|
|
892
|
+
Returns the exec area value.
|
|
893
|
+
|
|
894
|
+
:returns: exec area value (integer)
|
|
895
|
+
"""
|
|
896
|
+
|
|
897
|
+
return self._exec_area
|
|
898
|
+
|
|
899
|
+
async def set_exec_area(self, exec_area):
|
|
900
|
+
"""
|
|
901
|
+
Sets the exec area value.
|
|
902
|
+
The exec area is a pool of host memory used to store pages
|
|
903
|
+
translated by the JIT (they contain the native code
|
|
904
|
+
corresponding to MIPS code pages).
|
|
905
|
+
|
|
906
|
+
:param exec_area: exec area value (integer)
|
|
907
|
+
"""
|
|
908
|
+
|
|
909
|
+
await self._hypervisor.send(
|
|
910
|
+
'vm set_exec_area "{name}" {exec_area}'.format(name=self._name, exec_area=exec_area)
|
|
911
|
+
)
|
|
912
|
+
|
|
913
|
+
log.info(
|
|
914
|
+
'Router "{name}" [{id}]: exec area updated from {old_exec}MB to {new_exec}MB'.format(
|
|
915
|
+
name=self._name, id=self._id, old_exec=self._exec_area, new_exec=exec_area
|
|
916
|
+
)
|
|
917
|
+
)
|
|
918
|
+
self._exec_area = exec_area
|
|
919
|
+
|
|
920
|
+
@property
|
|
921
|
+
def disk0(self):
|
|
922
|
+
"""
|
|
923
|
+
Returns the size (MB) for PCMCIA disk0.
|
|
924
|
+
|
|
925
|
+
:returns: disk0 size (integer)
|
|
926
|
+
"""
|
|
927
|
+
|
|
928
|
+
return self._disk0
|
|
929
|
+
|
|
930
|
+
async def set_disk0(self, disk0):
|
|
931
|
+
"""
|
|
932
|
+
Sets the size (MB) for PCMCIA disk0.
|
|
933
|
+
|
|
934
|
+
:param disk0: disk0 size (integer)
|
|
935
|
+
"""
|
|
936
|
+
|
|
937
|
+
await self._hypervisor.send(f'vm set_disk0 "{self._name}" {disk0}')
|
|
938
|
+
|
|
939
|
+
log.info(
|
|
940
|
+
'Router "{name}" [{id}]: disk0 updated from {old_disk0}MB to {new_disk0}MB'.format(
|
|
941
|
+
name=self._name, id=self._id, old_disk0=self._disk0, new_disk0=disk0
|
|
942
|
+
)
|
|
943
|
+
)
|
|
944
|
+
self._disk0 = disk0
|
|
945
|
+
|
|
946
|
+
@property
|
|
947
|
+
def disk1(self):
|
|
948
|
+
"""
|
|
949
|
+
Returns the size (MB) for PCMCIA disk1.
|
|
950
|
+
|
|
951
|
+
:returns: disk1 size (integer)
|
|
952
|
+
"""
|
|
953
|
+
|
|
954
|
+
return self._disk1
|
|
955
|
+
|
|
956
|
+
async def set_disk1(self, disk1):
|
|
957
|
+
"""
|
|
958
|
+
Sets the size (MB) for PCMCIA disk1.
|
|
959
|
+
|
|
960
|
+
:param disk1: disk1 size (integer)
|
|
961
|
+
"""
|
|
962
|
+
|
|
963
|
+
await self._hypervisor.send(f'vm set_disk1 "{self._name}" {disk1}')
|
|
964
|
+
|
|
965
|
+
log.info(
|
|
966
|
+
'Router "{name}" [{id}]: disk1 updated from {old_disk1}MB to {new_disk1}MB'.format(
|
|
967
|
+
name=self._name, id=self._id, old_disk1=self._disk1, new_disk1=disk1
|
|
968
|
+
)
|
|
969
|
+
)
|
|
970
|
+
self._disk1 = disk1
|
|
971
|
+
|
|
972
|
+
@property
|
|
973
|
+
def auto_delete_disks(self):
|
|
974
|
+
"""
|
|
975
|
+
Returns True if auto delete disks is enabled on this router.
|
|
976
|
+
|
|
977
|
+
:returns: boolean either auto delete disks is activated or not
|
|
978
|
+
"""
|
|
979
|
+
|
|
980
|
+
return self._auto_delete_disks
|
|
981
|
+
|
|
982
|
+
async def set_auto_delete_disks(self, auto_delete_disks):
|
|
983
|
+
"""
|
|
984
|
+
Enable/disable use of auto delete disks
|
|
985
|
+
|
|
986
|
+
:param auto_delete_disks: activate/deactivate auto delete disks (boolean)
|
|
987
|
+
"""
|
|
988
|
+
|
|
989
|
+
if auto_delete_disks:
|
|
990
|
+
log.info(f'Router "{self._name}" [{self._id}]: auto delete disks enabled')
|
|
991
|
+
else:
|
|
992
|
+
log.info(f'Router "{self._name}" [{self._id}]: auto delete disks disabled')
|
|
993
|
+
self._auto_delete_disks = auto_delete_disks
|
|
994
|
+
|
|
995
|
+
async def set_console(self, console):
|
|
996
|
+
"""
|
|
997
|
+
Sets the TCP console port.
|
|
998
|
+
|
|
999
|
+
:param console: console port (integer)
|
|
1000
|
+
"""
|
|
1001
|
+
|
|
1002
|
+
self.console = console
|
|
1003
|
+
await self._hypervisor.send(f'vm set_con_tcp_port "{self._name}" {self.console}')
|
|
1004
|
+
|
|
1005
|
+
async def set_console_type(self, console_type):
|
|
1006
|
+
"""
|
|
1007
|
+
Sets the console type.
|
|
1008
|
+
|
|
1009
|
+
:param console_type: console type
|
|
1010
|
+
"""
|
|
1011
|
+
|
|
1012
|
+
if self.console_type != console_type:
|
|
1013
|
+
status = await self.get_status()
|
|
1014
|
+
if status == "running":
|
|
1015
|
+
raise DynamipsError('"{name}" must be stopped to change the console type to {console_type}'.format(name=self._name,
|
|
1016
|
+
console_type=console_type))
|
|
1017
|
+
|
|
1018
|
+
self.console_type = console_type
|
|
1019
|
+
|
|
1020
|
+
if self._console and console_type == "telnet":
|
|
1021
|
+
await self._hypervisor.send(f'vm set_con_tcp_port "{self._name}" {self._console}')
|
|
1022
|
+
|
|
1023
|
+
async def set_aux(self, aux):
|
|
1024
|
+
"""
|
|
1025
|
+
Sets the TCP auxiliary port.
|
|
1026
|
+
|
|
1027
|
+
:param aux: console auxiliary port (integer)
|
|
1028
|
+
"""
|
|
1029
|
+
|
|
1030
|
+
self.aux = aux
|
|
1031
|
+
await self._hypervisor.send(f'vm set_aux_tcp_port "{self._name}" {aux}')
|
|
1032
|
+
|
|
1033
|
+
async def set_aux_type(self, aux_type):
|
|
1034
|
+
"""
|
|
1035
|
+
Sets the aux type.
|
|
1036
|
+
|
|
1037
|
+
:param aux_type: auxiliary console type
|
|
1038
|
+
"""
|
|
1039
|
+
|
|
1040
|
+
if self.aux_type != aux_type:
|
|
1041
|
+
status = await self.get_status()
|
|
1042
|
+
if status == "running":
|
|
1043
|
+
raise DynamipsError('"{name}" must be stopped to change the auxiliary console type to {aux_type}'.format(
|
|
1044
|
+
name=self._name,
|
|
1045
|
+
aux_type=aux_type)
|
|
1046
|
+
)
|
|
1047
|
+
|
|
1048
|
+
self.aux_type = aux_type
|
|
1049
|
+
|
|
1050
|
+
if self._aux and aux_type == "telnet":
|
|
1051
|
+
await self._hypervisor.send(f'vm set_aux_tcp_port "{self._name}" {self._aux}')
|
|
1052
|
+
|
|
1053
|
+
async def reset_console(self):
|
|
1054
|
+
"""
|
|
1055
|
+
Reset console
|
|
1056
|
+
"""
|
|
1057
|
+
|
|
1058
|
+
pass # reset console is not supported with Dynamips
|
|
1059
|
+
|
|
1060
|
+
async def get_cpu_usage(self, cpu_id=0):
|
|
1061
|
+
"""
|
|
1062
|
+
Shows cpu usage in seconds, "cpu_id" is ignored.
|
|
1063
|
+
|
|
1064
|
+
:returns: cpu usage in seconds
|
|
1065
|
+
"""
|
|
1066
|
+
|
|
1067
|
+
cpu_usage = await self._hypervisor.send(f'vm cpu_usage "{self._name}" {cpu_id}')
|
|
1068
|
+
return int(cpu_usage[0])
|
|
1069
|
+
|
|
1070
|
+
@property
|
|
1071
|
+
def mac_addr(self):
|
|
1072
|
+
"""
|
|
1073
|
+
Returns the MAC address.
|
|
1074
|
+
|
|
1075
|
+
:returns: the MAC address (hexadecimal format: hh:hh:hh:hh:hh:hh)
|
|
1076
|
+
"""
|
|
1077
|
+
|
|
1078
|
+
return self._mac_addr
|
|
1079
|
+
|
|
1080
|
+
async def set_mac_addr(self, mac_addr):
|
|
1081
|
+
"""
|
|
1082
|
+
Sets the MAC address.
|
|
1083
|
+
|
|
1084
|
+
:param mac_addr: a MAC address (hexadecimal format: hh:hh:hh:hh:hh:hh)
|
|
1085
|
+
"""
|
|
1086
|
+
|
|
1087
|
+
await self._hypervisor.send(
|
|
1088
|
+
'{platform} set_mac_addr "{name}" {mac_addr}'.format(
|
|
1089
|
+
platform=self._platform, name=self._name, mac_addr=mac_addr
|
|
1090
|
+
)
|
|
1091
|
+
)
|
|
1092
|
+
|
|
1093
|
+
log.info(
|
|
1094
|
+
'Router "{name}" [{id}]: MAC address updated from {old_mac} to {new_mac}'.format(
|
|
1095
|
+
name=self._name, id=self._id, old_mac=self._mac_addr, new_mac=mac_addr
|
|
1096
|
+
)
|
|
1097
|
+
)
|
|
1098
|
+
self._mac_addr = mac_addr
|
|
1099
|
+
|
|
1100
|
+
@property
|
|
1101
|
+
def system_id(self):
|
|
1102
|
+
"""
|
|
1103
|
+
Returns the system ID.
|
|
1104
|
+
|
|
1105
|
+
:returns: the system ID (also called board processor ID)
|
|
1106
|
+
"""
|
|
1107
|
+
|
|
1108
|
+
return self._system_id
|
|
1109
|
+
|
|
1110
|
+
async def set_system_id(self, system_id):
|
|
1111
|
+
"""
|
|
1112
|
+
Sets the system ID.
|
|
1113
|
+
|
|
1114
|
+
:param system_id: a system ID (also called board processor ID)
|
|
1115
|
+
"""
|
|
1116
|
+
|
|
1117
|
+
await self._hypervisor.send(
|
|
1118
|
+
'{platform} set_system_id "{name}" {system_id}'.format(
|
|
1119
|
+
platform=self._platform, name=self._name, system_id=system_id
|
|
1120
|
+
)
|
|
1121
|
+
)
|
|
1122
|
+
|
|
1123
|
+
log.info(
|
|
1124
|
+
'Router "{name}" [{id}]: system ID updated from {old_id} to {new_id}'.format(
|
|
1125
|
+
name=self._name, id=self._id, old_id=self._system_id, new_id=system_id
|
|
1126
|
+
)
|
|
1127
|
+
)
|
|
1128
|
+
self._system_id = system_id
|
|
1129
|
+
|
|
1130
|
+
async def get_slot_bindings(self):
|
|
1131
|
+
"""
|
|
1132
|
+
Returns slot bindings.
|
|
1133
|
+
|
|
1134
|
+
:returns: slot bindings (adapter names) list
|
|
1135
|
+
"""
|
|
1136
|
+
|
|
1137
|
+
slot_bindings = await self._hypervisor.send(f'vm slot_bindings "{self._name}"')
|
|
1138
|
+
return slot_bindings
|
|
1139
|
+
|
|
1140
|
+
async def slot_add_binding(self, slot_number, adapter):
|
|
1141
|
+
"""
|
|
1142
|
+
Adds a slot binding (a module into a slot).
|
|
1143
|
+
|
|
1144
|
+
:param slot_number: slot number
|
|
1145
|
+
:param adapter: device to add in the corresponding slot
|
|
1146
|
+
"""
|
|
1147
|
+
|
|
1148
|
+
try:
|
|
1149
|
+
slot = self._slots[slot_number]
|
|
1150
|
+
except IndexError:
|
|
1151
|
+
raise DynamipsError(f'Slot {slot_number} does not exist on router "{self._name}"')
|
|
1152
|
+
|
|
1153
|
+
if slot is not None:
|
|
1154
|
+
current_adapter = slot
|
|
1155
|
+
raise DynamipsError(
|
|
1156
|
+
'Slot {slot_number} is already occupied by adapter {adapter} on router "{name}"'.format(
|
|
1157
|
+
name=self._name, slot_number=slot_number, adapter=current_adapter
|
|
1158
|
+
)
|
|
1159
|
+
)
|
|
1160
|
+
|
|
1161
|
+
is_running = await self.is_running()
|
|
1162
|
+
|
|
1163
|
+
# Only c7200, c3600 and c3745 (NM-4T only) support new adapter while running
|
|
1164
|
+
if is_running and not (
|
|
1165
|
+
(self._platform == "c7200" and not str(adapter).startswith("C7200"))
|
|
1166
|
+
and not (self._platform == "c3600" and self.chassis == "3660")
|
|
1167
|
+
and not (self._platform == "c3745" and adapter == "NM-4T")
|
|
1168
|
+
):
|
|
1169
|
+
raise DynamipsError(
|
|
1170
|
+
'Adapter {adapter} cannot be added while router "{name}" is running'.format(
|
|
1171
|
+
adapter=adapter, name=self._name
|
|
1172
|
+
)
|
|
1173
|
+
)
|
|
1174
|
+
|
|
1175
|
+
await self._hypervisor.send(
|
|
1176
|
+
'vm slot_add_binding "{name}" {slot_number} 0 {adapter}'.format(
|
|
1177
|
+
name=self._name, slot_number=slot_number, adapter=adapter
|
|
1178
|
+
)
|
|
1179
|
+
)
|
|
1180
|
+
|
|
1181
|
+
log.info(
|
|
1182
|
+
'Router "{name}" [{id}]: adapter {adapter} inserted into slot {slot_number}'.format(
|
|
1183
|
+
name=self._name, id=self._id, adapter=adapter, slot_number=slot_number
|
|
1184
|
+
)
|
|
1185
|
+
)
|
|
1186
|
+
|
|
1187
|
+
self._slots[slot_number] = adapter
|
|
1188
|
+
|
|
1189
|
+
# Generate an OIR event if the router is running
|
|
1190
|
+
if is_running:
|
|
1191
|
+
|
|
1192
|
+
await self._hypervisor.send(
|
|
1193
|
+
'vm slot_oir_start "{name}" {slot_number} 0'.format(name=self._name, slot_number=slot_number)
|
|
1194
|
+
)
|
|
1195
|
+
|
|
1196
|
+
log.info(
|
|
1197
|
+
'Router "{name}" [{id}]: OIR start event sent to slot {slot_number}'.format(
|
|
1198
|
+
name=self._name, id=self._id, slot_number=slot_number
|
|
1199
|
+
)
|
|
1200
|
+
)
|
|
1201
|
+
|
|
1202
|
+
async def slot_remove_binding(self, slot_number):
|
|
1203
|
+
"""
|
|
1204
|
+
Removes a slot binding (a module from a slot).
|
|
1205
|
+
|
|
1206
|
+
:param slot_number: slot number
|
|
1207
|
+
"""
|
|
1208
|
+
|
|
1209
|
+
try:
|
|
1210
|
+
adapter = self._slots[slot_number]
|
|
1211
|
+
except IndexError:
|
|
1212
|
+
raise DynamipsError(
|
|
1213
|
+
'Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, slot_number=slot_number)
|
|
1214
|
+
)
|
|
1215
|
+
|
|
1216
|
+
if adapter is None:
|
|
1217
|
+
raise DynamipsError(
|
|
1218
|
+
'No adapter in slot {slot_number} on router "{name}"'.format(name=self._name, slot_number=slot_number)
|
|
1219
|
+
)
|
|
1220
|
+
|
|
1221
|
+
is_running = await self.is_running()
|
|
1222
|
+
|
|
1223
|
+
# Only c7200, c3600 and c3745 (NM-4T only) support to remove adapter while running
|
|
1224
|
+
if is_running and not (
|
|
1225
|
+
(self._platform == "c7200" and not str(adapter).startswith("C7200"))
|
|
1226
|
+
and not (self._platform == "c3600" and self.chassis == "3660")
|
|
1227
|
+
and not (self._platform == "c3745" and adapter == "NM-4T")
|
|
1228
|
+
):
|
|
1229
|
+
raise DynamipsError(
|
|
1230
|
+
'Adapter {adapter} cannot be removed while router "{name}" is running'.format(
|
|
1231
|
+
adapter=adapter, name=self._name
|
|
1232
|
+
)
|
|
1233
|
+
)
|
|
1234
|
+
|
|
1235
|
+
# Generate an OIR event if the router is running
|
|
1236
|
+
if is_running:
|
|
1237
|
+
|
|
1238
|
+
await self._hypervisor.send(
|
|
1239
|
+
'vm slot_oir_stop "{name}" {slot_number} 0'.format(name=self._name, slot_number=slot_number)
|
|
1240
|
+
)
|
|
1241
|
+
|
|
1242
|
+
log.info(
|
|
1243
|
+
'Router "{name}" [{id}]: OIR stop event sent to slot {slot_number}'.format(
|
|
1244
|
+
name=self._name, id=self._id, slot_number=slot_number
|
|
1245
|
+
)
|
|
1246
|
+
)
|
|
1247
|
+
|
|
1248
|
+
await self._hypervisor.send(
|
|
1249
|
+
'vm slot_remove_binding "{name}" {slot_number} 0'.format(name=self._name, slot_number=slot_number)
|
|
1250
|
+
)
|
|
1251
|
+
|
|
1252
|
+
log.info(
|
|
1253
|
+
'Router "{name}" [{id}]: adapter {adapter} removed from slot {slot_number}'.format(
|
|
1254
|
+
name=self._name, id=self._id, adapter=adapter, slot_number=slot_number
|
|
1255
|
+
)
|
|
1256
|
+
)
|
|
1257
|
+
self._slots[slot_number] = None
|
|
1258
|
+
|
|
1259
|
+
async def install_wic(self, wic_slot_number, wic):
|
|
1260
|
+
"""
|
|
1261
|
+
Installs a WIC adapter into this router.
|
|
1262
|
+
|
|
1263
|
+
:param wic_slot_number: WIC slot number
|
|
1264
|
+
:param wic: WIC to be installed
|
|
1265
|
+
"""
|
|
1266
|
+
|
|
1267
|
+
# WICs are always installed on adapters in slot 0
|
|
1268
|
+
slot_number = 0
|
|
1269
|
+
|
|
1270
|
+
# Do not check if slot has an adapter because adapters with WICs interfaces
|
|
1271
|
+
# must be inserted by default in the router and cannot be removed.
|
|
1272
|
+
adapter = self._slots[slot_number]
|
|
1273
|
+
|
|
1274
|
+
if wic_slot_number > len(adapter.wics) - 1:
|
|
1275
|
+
raise DynamipsError(f"WIC slot {wic_slot_number} doesn't exist")
|
|
1276
|
+
|
|
1277
|
+
if not adapter.wic_slot_available(wic_slot_number):
|
|
1278
|
+
raise DynamipsError(f"WIC slot {wic_slot_number} is already occupied by another WIC")
|
|
1279
|
+
|
|
1280
|
+
if await self.is_running():
|
|
1281
|
+
raise DynamipsError(
|
|
1282
|
+
'WIC "{wic}" cannot be added while router "{name}" is running'.format(wic=wic, name=self._name)
|
|
1283
|
+
)
|
|
1284
|
+
|
|
1285
|
+
# Dynamips WICs slot IDs start on a multiple of 16
|
|
1286
|
+
# WIC1 = 16, WIC2 = 32 and WIC3 = 48
|
|
1287
|
+
internal_wic_slot_number = 16 * (wic_slot_number + 1)
|
|
1288
|
+
await self._hypervisor.send(
|
|
1289
|
+
'vm slot_add_binding "{name}" {slot_number} {wic_slot_number} {wic}'.format(
|
|
1290
|
+
name=self._name, slot_number=slot_number, wic_slot_number=internal_wic_slot_number, wic=wic
|
|
1291
|
+
)
|
|
1292
|
+
)
|
|
1293
|
+
|
|
1294
|
+
log.info(
|
|
1295
|
+
'Router "{name}" [{id}]: {wic} inserted into WIC slot {wic_slot_number}'.format(
|
|
1296
|
+
name=self._name, id=self._id, wic=wic, wic_slot_number=wic_slot_number
|
|
1297
|
+
)
|
|
1298
|
+
)
|
|
1299
|
+
|
|
1300
|
+
adapter.install_wic(wic_slot_number, wic)
|
|
1301
|
+
|
|
1302
|
+
async def uninstall_wic(self, wic_slot_number):
|
|
1303
|
+
"""
|
|
1304
|
+
Uninstalls a WIC adapter from this router.
|
|
1305
|
+
|
|
1306
|
+
:param wic_slot_number: WIC slot number
|
|
1307
|
+
"""
|
|
1308
|
+
|
|
1309
|
+
# WICs are always installed on adapters in slot 0
|
|
1310
|
+
slot_number = 0
|
|
1311
|
+
|
|
1312
|
+
# Do not check if slot has an adapter because adapters with WICs interfaces
|
|
1313
|
+
# must be inserted by default in the router and cannot be removed.
|
|
1314
|
+
adapter = self._slots[slot_number]
|
|
1315
|
+
|
|
1316
|
+
if wic_slot_number > len(adapter.wics) - 1:
|
|
1317
|
+
raise DynamipsError(f"WIC slot {wic_slot_number} doesn't exist")
|
|
1318
|
+
|
|
1319
|
+
if adapter.wic_slot_available(wic_slot_number):
|
|
1320
|
+
raise DynamipsError(f"No WIC is installed in WIC slot {wic_slot_number}")
|
|
1321
|
+
|
|
1322
|
+
if await self.is_running():
|
|
1323
|
+
raise DynamipsError(
|
|
1324
|
+
'WIC cannot be removed from slot {wic_slot_number} while router "{name}" is running'.format(
|
|
1325
|
+
wic_slot_number=wic_slot_number, name=self._name
|
|
1326
|
+
)
|
|
1327
|
+
)
|
|
1328
|
+
|
|
1329
|
+
# Dynamips WICs slot IDs start on a multiple of 16
|
|
1330
|
+
# WIC1 = 16, WIC2 = 32 and WIC3 = 48
|
|
1331
|
+
internal_wic_slot_number = 16 * (wic_slot_number + 1)
|
|
1332
|
+
await self._hypervisor.send(
|
|
1333
|
+
'vm slot_remove_binding "{name}" {slot_number} {wic_slot_number}'.format(
|
|
1334
|
+
name=self._name, slot_number=slot_number, wic_slot_number=internal_wic_slot_number
|
|
1335
|
+
)
|
|
1336
|
+
)
|
|
1337
|
+
|
|
1338
|
+
log.info(
|
|
1339
|
+
'Router "{name}" [{id}]: {wic} removed from WIC slot {wic_slot_number}'.format(
|
|
1340
|
+
name=self._name, id=self._id, wic=adapter.wics[wic_slot_number], wic_slot_number=wic_slot_number
|
|
1341
|
+
)
|
|
1342
|
+
)
|
|
1343
|
+
adapter.uninstall_wic(wic_slot_number)
|
|
1344
|
+
|
|
1345
|
+
async def get_slot_nio_bindings(self, slot_number):
|
|
1346
|
+
"""
|
|
1347
|
+
Returns slot NIO bindings.
|
|
1348
|
+
|
|
1349
|
+
:param slot_number: slot number
|
|
1350
|
+
|
|
1351
|
+
:returns: list of NIO bindings
|
|
1352
|
+
"""
|
|
1353
|
+
|
|
1354
|
+
nio_bindings = await self._hypervisor.send(
|
|
1355
|
+
'vm slot_nio_bindings "{name}" {slot_number}'.format(name=self._name, slot_number=slot_number)
|
|
1356
|
+
)
|
|
1357
|
+
return nio_bindings
|
|
1358
|
+
|
|
1359
|
+
async def slot_add_nio_binding(self, slot_number, port_number, nio):
|
|
1360
|
+
"""
|
|
1361
|
+
Adds a slot NIO binding.
|
|
1362
|
+
|
|
1363
|
+
:param slot_number: slot number
|
|
1364
|
+
:param port_number: port number
|
|
1365
|
+
:param nio: NIO instance to add to the slot/port
|
|
1366
|
+
"""
|
|
1367
|
+
|
|
1368
|
+
try:
|
|
1369
|
+
adapter = self._slots[slot_number]
|
|
1370
|
+
except IndexError:
|
|
1371
|
+
raise DynamipsError(
|
|
1372
|
+
'Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, slot_number=slot_number)
|
|
1373
|
+
)
|
|
1374
|
+
|
|
1375
|
+
if adapter is None:
|
|
1376
|
+
raise DynamipsError(f"Adapter is missing in slot {slot_number}")
|
|
1377
|
+
|
|
1378
|
+
if not adapter.port_exists(port_number):
|
|
1379
|
+
raise DynamipsError(
|
|
1380
|
+
"Port {port_number} does not exist on adapter {adapter}".format(
|
|
1381
|
+
adapter=adapter, port_number=port_number
|
|
1382
|
+
)
|
|
1383
|
+
)
|
|
1384
|
+
|
|
1385
|
+
try:
|
|
1386
|
+
await self._hypervisor.send(
|
|
1387
|
+
'vm slot_add_nio_binding "{name}" {slot_number} {port_number} {nio}'.format(
|
|
1388
|
+
name=self._name, slot_number=slot_number, port_number=port_number, nio=nio
|
|
1389
|
+
)
|
|
1390
|
+
)
|
|
1391
|
+
except DynamipsError:
|
|
1392
|
+
# in case of error try to remove and add the nio binding
|
|
1393
|
+
await self._hypervisor.send(
|
|
1394
|
+
'vm slot_remove_nio_binding "{name}" {slot_number} {port_number}'.format(
|
|
1395
|
+
name=self._name, slot_number=slot_number, port_number=port_number
|
|
1396
|
+
)
|
|
1397
|
+
)
|
|
1398
|
+
await self._hypervisor.send(
|
|
1399
|
+
'vm slot_add_nio_binding "{name}" {slot_number} {port_number} {nio}'.format(
|
|
1400
|
+
name=self._name, slot_number=slot_number, port_number=port_number, nio=nio
|
|
1401
|
+
)
|
|
1402
|
+
)
|
|
1403
|
+
|
|
1404
|
+
log.info(
|
|
1405
|
+
'Router "{name}" [{id}]: NIO {nio_name} bound to port {slot_number}/{port_number}'.format(
|
|
1406
|
+
name=self._name, id=self._id, nio_name=nio.name, slot_number=slot_number, port_number=port_number
|
|
1407
|
+
)
|
|
1408
|
+
)
|
|
1409
|
+
|
|
1410
|
+
await self.slot_enable_nio(slot_number, port_number)
|
|
1411
|
+
adapter.add_nio(port_number, nio)
|
|
1412
|
+
|
|
1413
|
+
async def slot_update_nio_binding(self, slot_number, port_number, nio):
|
|
1414
|
+
"""
|
|
1415
|
+
Update a slot NIO binding.
|
|
1416
|
+
|
|
1417
|
+
:param slot_number: slot number
|
|
1418
|
+
:param port_number: port number
|
|
1419
|
+
:param nio: NIO instance to add to the slot/port
|
|
1420
|
+
"""
|
|
1421
|
+
|
|
1422
|
+
await nio.update()
|
|
1423
|
+
|
|
1424
|
+
async def slot_remove_nio_binding(self, slot_number, port_number):
|
|
1425
|
+
"""
|
|
1426
|
+
Removes a slot NIO binding.
|
|
1427
|
+
|
|
1428
|
+
:param slot_number: slot number
|
|
1429
|
+
:param port_number: port number
|
|
1430
|
+
|
|
1431
|
+
:returns: removed NIO instance
|
|
1432
|
+
"""
|
|
1433
|
+
|
|
1434
|
+
try:
|
|
1435
|
+
adapter = self._slots[slot_number]
|
|
1436
|
+
except IndexError:
|
|
1437
|
+
raise DynamipsError(
|
|
1438
|
+
'Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, slot_number=slot_number)
|
|
1439
|
+
)
|
|
1440
|
+
|
|
1441
|
+
if adapter is None:
|
|
1442
|
+
raise DynamipsError(f"Adapter is missing in slot {slot_number}")
|
|
1443
|
+
|
|
1444
|
+
if not adapter.port_exists(port_number):
|
|
1445
|
+
raise DynamipsError(
|
|
1446
|
+
"Port {port_number} does not exist on adapter {adapter}".format(
|
|
1447
|
+
adapter=adapter, port_number=port_number
|
|
1448
|
+
)
|
|
1449
|
+
)
|
|
1450
|
+
|
|
1451
|
+
await self.stop_capture(slot_number, port_number)
|
|
1452
|
+
await self.slot_disable_nio(slot_number, port_number)
|
|
1453
|
+
await self._hypervisor.send(
|
|
1454
|
+
'vm slot_remove_nio_binding "{name}" {slot_number} {port_number}'.format(
|
|
1455
|
+
name=self._name, slot_number=slot_number, port_number=port_number
|
|
1456
|
+
)
|
|
1457
|
+
)
|
|
1458
|
+
|
|
1459
|
+
nio = adapter.get_nio(port_number)
|
|
1460
|
+
if nio is None:
|
|
1461
|
+
return
|
|
1462
|
+
await nio.close()
|
|
1463
|
+
adapter.remove_nio(port_number)
|
|
1464
|
+
|
|
1465
|
+
log.info(
|
|
1466
|
+
'Router "{name}" [{id}]: NIO {nio_name} removed from port {slot_number}/{port_number}'.format(
|
|
1467
|
+
name=self._name, id=self._id, nio_name=nio.name, slot_number=slot_number, port_number=port_number
|
|
1468
|
+
)
|
|
1469
|
+
)
|
|
1470
|
+
|
|
1471
|
+
return nio
|
|
1472
|
+
|
|
1473
|
+
async def slot_enable_nio(self, slot_number, port_number):
|
|
1474
|
+
"""
|
|
1475
|
+
Enables a slot NIO binding.
|
|
1476
|
+
|
|
1477
|
+
:param slot_number: slot number
|
|
1478
|
+
:param port_number: port number
|
|
1479
|
+
"""
|
|
1480
|
+
|
|
1481
|
+
is_running = await self.is_running()
|
|
1482
|
+
if is_running: # running router
|
|
1483
|
+
await self._hypervisor.send(
|
|
1484
|
+
'vm slot_enable_nio "{name}" {slot_number} {port_number}'.format(
|
|
1485
|
+
name=self._name, slot_number=slot_number, port_number=port_number
|
|
1486
|
+
)
|
|
1487
|
+
)
|
|
1488
|
+
|
|
1489
|
+
log.info(
|
|
1490
|
+
'Router "{name}" [{id}]: NIO enabled on port {slot_number}/{port_number}'.format(
|
|
1491
|
+
name=self._name, id=self._id, slot_number=slot_number, port_number=port_number
|
|
1492
|
+
)
|
|
1493
|
+
)
|
|
1494
|
+
|
|
1495
|
+
def get_nio(self, slot_number, port_number):
|
|
1496
|
+
"""
|
|
1497
|
+
Gets an slot NIO binding.
|
|
1498
|
+
|
|
1499
|
+
:param slot_number: slot number
|
|
1500
|
+
:param port_number: port number
|
|
1501
|
+
|
|
1502
|
+
:returns: NIO instance
|
|
1503
|
+
"""
|
|
1504
|
+
|
|
1505
|
+
try:
|
|
1506
|
+
adapter = self._slots[slot_number]
|
|
1507
|
+
except IndexError:
|
|
1508
|
+
raise DynamipsError(
|
|
1509
|
+
'Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, slot_number=slot_number)
|
|
1510
|
+
)
|
|
1511
|
+
if not adapter.port_exists(port_number):
|
|
1512
|
+
raise DynamipsError(
|
|
1513
|
+
"Port {port_number} does not exist on adapter {adapter}".format(
|
|
1514
|
+
adapter=adapter, port_number=port_number
|
|
1515
|
+
)
|
|
1516
|
+
)
|
|
1517
|
+
|
|
1518
|
+
nio = adapter.get_nio(port_number)
|
|
1519
|
+
|
|
1520
|
+
if not nio:
|
|
1521
|
+
raise DynamipsError(
|
|
1522
|
+
"Port {slot_number}/{port_number} is not connected".format(
|
|
1523
|
+
slot_number=slot_number, port_number=port_number
|
|
1524
|
+
)
|
|
1525
|
+
)
|
|
1526
|
+
return nio
|
|
1527
|
+
|
|
1528
|
+
async def slot_disable_nio(self, slot_number, port_number):
|
|
1529
|
+
"""
|
|
1530
|
+
Disables a slot NIO binding.
|
|
1531
|
+
|
|
1532
|
+
:param slot_number: slot number
|
|
1533
|
+
:param port_number: port number
|
|
1534
|
+
"""
|
|
1535
|
+
|
|
1536
|
+
is_running = await self.is_running()
|
|
1537
|
+
if is_running: # running router
|
|
1538
|
+
await self._hypervisor.send(
|
|
1539
|
+
'vm slot_disable_nio "{name}" {slot_number} {port_number}'.format(
|
|
1540
|
+
name=self._name, slot_number=slot_number, port_number=port_number
|
|
1541
|
+
)
|
|
1542
|
+
)
|
|
1543
|
+
|
|
1544
|
+
log.info(
|
|
1545
|
+
'Router "{name}" [{id}]: NIO disabled on port {slot_number}/{port_number}'.format(
|
|
1546
|
+
name=self._name, id=self._id, slot_number=slot_number, port_number=port_number
|
|
1547
|
+
)
|
|
1548
|
+
)
|
|
1549
|
+
|
|
1550
|
+
async def start_capture(self, slot_number, port_number, output_file, data_link_type="DLT_EN10MB"):
|
|
1551
|
+
"""
|
|
1552
|
+
Starts a packet capture.
|
|
1553
|
+
|
|
1554
|
+
:param slot_number: slot number
|
|
1555
|
+
:param port_number: port number
|
|
1556
|
+
:param output_file: PCAP destination file for the capture
|
|
1557
|
+
:param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
|
|
1558
|
+
"""
|
|
1559
|
+
|
|
1560
|
+
try:
|
|
1561
|
+
open(output_file, "w+").close()
|
|
1562
|
+
except OSError as e:
|
|
1563
|
+
raise DynamipsError(f'Can not write capture to "{output_file}": {str(e)}')
|
|
1564
|
+
|
|
1565
|
+
try:
|
|
1566
|
+
adapter = self._slots[slot_number]
|
|
1567
|
+
except IndexError:
|
|
1568
|
+
raise DynamipsError(
|
|
1569
|
+
'Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, slot_number=slot_number)
|
|
1570
|
+
)
|
|
1571
|
+
if not adapter.port_exists(port_number):
|
|
1572
|
+
raise DynamipsError(
|
|
1573
|
+
"Port {port_number} does not exist on adapter {adapter}".format(
|
|
1574
|
+
adapter=adapter, port_number=port_number
|
|
1575
|
+
)
|
|
1576
|
+
)
|
|
1577
|
+
|
|
1578
|
+
data_link_type = data_link_type.lower()
|
|
1579
|
+
if data_link_type.startswith("dlt_"):
|
|
1580
|
+
data_link_type = data_link_type[4:]
|
|
1581
|
+
|
|
1582
|
+
nio = adapter.get_nio(port_number)
|
|
1583
|
+
|
|
1584
|
+
if not nio:
|
|
1585
|
+
raise DynamipsError(
|
|
1586
|
+
"Port {slot_number}/{port_number} is not connected".format(
|
|
1587
|
+
slot_number=slot_number, port_number=port_number
|
|
1588
|
+
)
|
|
1589
|
+
)
|
|
1590
|
+
|
|
1591
|
+
if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
|
|
1592
|
+
raise DynamipsError(
|
|
1593
|
+
"Port {port_number} has already a filter applied on {adapter}".format(
|
|
1594
|
+
adapter=adapter, port_number=port_number
|
|
1595
|
+
)
|
|
1596
|
+
)
|
|
1597
|
+
await nio.start_packet_capture(output_file, data_link_type)
|
|
1598
|
+
log.info(
|
|
1599
|
+
'Router "{name}" [{id}]: starting packet capture on port {slot_number}/{port_number}'.format(
|
|
1600
|
+
name=self._name, id=self._id, nio_name=nio.name, slot_number=slot_number, port_number=port_number
|
|
1601
|
+
)
|
|
1602
|
+
)
|
|
1603
|
+
|
|
1604
|
+
async def stop_capture(self, slot_number, port_number):
|
|
1605
|
+
"""
|
|
1606
|
+
Stops a packet capture.
|
|
1607
|
+
|
|
1608
|
+
:param slot_number: slot number
|
|
1609
|
+
:param port_number: port number
|
|
1610
|
+
"""
|
|
1611
|
+
|
|
1612
|
+
try:
|
|
1613
|
+
adapter = self._slots[slot_number]
|
|
1614
|
+
except IndexError:
|
|
1615
|
+
raise DynamipsError(
|
|
1616
|
+
'Slot {slot_number} does not exist on router "{name}"'.format(name=self._name, slot_number=slot_number)
|
|
1617
|
+
)
|
|
1618
|
+
if not adapter.port_exists(port_number):
|
|
1619
|
+
raise DynamipsError(
|
|
1620
|
+
"Port {port_number} does not exist on adapter {adapter}".format(
|
|
1621
|
+
adapter=adapter, port_number=port_number
|
|
1622
|
+
)
|
|
1623
|
+
)
|
|
1624
|
+
|
|
1625
|
+
nio = adapter.get_nio(port_number)
|
|
1626
|
+
|
|
1627
|
+
if not nio:
|
|
1628
|
+
raise DynamipsError(
|
|
1629
|
+
"Port {slot_number}/{port_number} is not connected".format(
|
|
1630
|
+
slot_number=slot_number, port_number=port_number
|
|
1631
|
+
)
|
|
1632
|
+
)
|
|
1633
|
+
|
|
1634
|
+
if not nio.capturing:
|
|
1635
|
+
return
|
|
1636
|
+
await nio.stop_packet_capture()
|
|
1637
|
+
|
|
1638
|
+
log.info(
|
|
1639
|
+
'Router "{name}" [{id}]: stopping packet capture on port {slot_number}/{port_number}'.format(
|
|
1640
|
+
name=self._name, id=self._id, nio_name=nio.name, slot_number=slot_number, port_number=port_number
|
|
1641
|
+
)
|
|
1642
|
+
)
|
|
1643
|
+
|
|
1644
|
+
def _create_slots(self, numslots):
|
|
1645
|
+
"""
|
|
1646
|
+
Creates the appropriate number of slots for this router.
|
|
1647
|
+
|
|
1648
|
+
:param numslots: number of slots to create
|
|
1649
|
+
"""
|
|
1650
|
+
|
|
1651
|
+
self._slots = numslots * [None]
|
|
1652
|
+
|
|
1653
|
+
@property
|
|
1654
|
+
def slots(self):
|
|
1655
|
+
"""
|
|
1656
|
+
Returns the slots for this router.
|
|
1657
|
+
|
|
1658
|
+
:return: slot list
|
|
1659
|
+
"""
|
|
1660
|
+
|
|
1661
|
+
return self._slots
|
|
1662
|
+
|
|
1663
|
+
@property
|
|
1664
|
+
def startup_config_path(self):
|
|
1665
|
+
"""
|
|
1666
|
+
:returns: Path of the startup config
|
|
1667
|
+
"""
|
|
1668
|
+
return os.path.join(self._working_directory, "configs", f"i{self._dynamips_id}_startup-config.cfg")
|
|
1669
|
+
|
|
1670
|
+
@property
|
|
1671
|
+
def private_config_path(self):
|
|
1672
|
+
"""
|
|
1673
|
+
:returns: Path of the private config
|
|
1674
|
+
"""
|
|
1675
|
+
return os.path.join(self._working_directory, "configs", f"i{self._dynamips_id}_private-config.cfg")
|
|
1676
|
+
|
|
1677
|
+
async def set_name(self, new_name):
|
|
1678
|
+
"""
|
|
1679
|
+
Renames this router.
|
|
1680
|
+
|
|
1681
|
+
:param new_name: new name string
|
|
1682
|
+
"""
|
|
1683
|
+
|
|
1684
|
+
if not is_ios_hostname_valid(new_name):
|
|
1685
|
+
raise DynamipsError(f"{new_name} is an invalid name to rename router '{self._name}'")
|
|
1686
|
+
|
|
1687
|
+
await self._hypervisor.send(f'vm rename "{self._name}" "{new_name}"')
|
|
1688
|
+
|
|
1689
|
+
# change the hostname in the startup-config
|
|
1690
|
+
if os.path.isfile(self.startup_config_path):
|
|
1691
|
+
try:
|
|
1692
|
+
with open(self.startup_config_path, "r+", encoding="utf-8", errors="replace") as f:
|
|
1693
|
+
old_config = f.read()
|
|
1694
|
+
new_config = re.sub(r"hostname .+$", "hostname " + new_name, old_config, flags=re.MULTILINE)
|
|
1695
|
+
f.seek(0)
|
|
1696
|
+
f.write(new_config)
|
|
1697
|
+
except OSError as e:
|
|
1698
|
+
raise DynamipsError(f"Could not amend the configuration {self.startup_config_path}: {e}")
|
|
1699
|
+
|
|
1700
|
+
# change the hostname in the private-config
|
|
1701
|
+
if os.path.isfile(self.private_config_path):
|
|
1702
|
+
try:
|
|
1703
|
+
with open(self.private_config_path, "r+", encoding="utf-8", errors="replace") as f:
|
|
1704
|
+
old_config = f.read()
|
|
1705
|
+
new_config = old_config.replace(self.name, new_name)
|
|
1706
|
+
f.seek(0)
|
|
1707
|
+
f.write(new_config)
|
|
1708
|
+
except OSError as e:
|
|
1709
|
+
raise DynamipsError(f"Could not amend the configuration {self.private_config_path}: {e}")
|
|
1710
|
+
|
|
1711
|
+
log.info(f'Router "{self._name}" [{self._id}]: renamed to "{new_name}"')
|
|
1712
|
+
self._name = new_name
|
|
1713
|
+
|
|
1714
|
+
async def extract_config(self):
|
|
1715
|
+
"""
|
|
1716
|
+
Gets the contents of the config files
|
|
1717
|
+
startup-config and private-config from NVRAM.
|
|
1718
|
+
|
|
1719
|
+
:returns: tuple (startup-config, private-config) base64 encoded
|
|
1720
|
+
"""
|
|
1721
|
+
|
|
1722
|
+
try:
|
|
1723
|
+
reply = await self._hypervisor.send(f'vm extract_config "{self._name}"')
|
|
1724
|
+
except DynamipsError:
|
|
1725
|
+
# for some reason Dynamips gets frozen when it does not find the magic number in the NVRAM file.
|
|
1726
|
+
return None, None
|
|
1727
|
+
reply = reply[0].rsplit(" ", 2)[-2:]
|
|
1728
|
+
startup_config = reply[0][1:-1] # get statup-config and remove single quotes
|
|
1729
|
+
private_config = reply[1][1:-1] # get private-config and remove single quotes
|
|
1730
|
+
return startup_config, private_config
|
|
1731
|
+
|
|
1732
|
+
async def save_configs(self):
|
|
1733
|
+
"""
|
|
1734
|
+
Saves the startup-config and private-config to files.
|
|
1735
|
+
"""
|
|
1736
|
+
|
|
1737
|
+
try:
|
|
1738
|
+
config_path = os.path.join(self._working_directory, "configs")
|
|
1739
|
+
os.makedirs(config_path, exist_ok=True)
|
|
1740
|
+
except OSError as e:
|
|
1741
|
+
raise DynamipsError(f"Could could not create configuration directory {config_path}: {e}")
|
|
1742
|
+
|
|
1743
|
+
startup_config_base64, private_config_base64 = await self.extract_config()
|
|
1744
|
+
if startup_config_base64:
|
|
1745
|
+
startup_config = self.startup_config_path
|
|
1746
|
+
try:
|
|
1747
|
+
config = base64.b64decode(startup_config_base64).decode("utf-8", errors="replace")
|
|
1748
|
+
config = "!\n" + config.replace("\r", "")
|
|
1749
|
+
config_path = os.path.join(self._working_directory, startup_config)
|
|
1750
|
+
with open(config_path, "wb") as f:
|
|
1751
|
+
log.info(f"saving startup-config to {startup_config}")
|
|
1752
|
+
f.write(config.encode("utf-8"))
|
|
1753
|
+
except (binascii.Error, OSError) as e:
|
|
1754
|
+
raise DynamipsError(f"Could not save the startup configuration {config_path}: {e}")
|
|
1755
|
+
|
|
1756
|
+
if private_config_base64 and base64.b64decode(private_config_base64) != b"\nkerberos password \nend\n":
|
|
1757
|
+
private_config = self.private_config_path
|
|
1758
|
+
try:
|
|
1759
|
+
config = base64.b64decode(private_config_base64).decode("utf-8", errors="replace")
|
|
1760
|
+
config_path = os.path.join(self._working_directory, private_config)
|
|
1761
|
+
with open(config_path, "wb") as f:
|
|
1762
|
+
log.info(f"saving private-config to {private_config}")
|
|
1763
|
+
f.write(config.encode("utf-8"))
|
|
1764
|
+
except (binascii.Error, OSError) as e:
|
|
1765
|
+
raise DynamipsError(f"Could not save the private configuration {config_path}: {e}")
|
|
1766
|
+
|
|
1767
|
+
async def delete(self):
|
|
1768
|
+
"""
|
|
1769
|
+
Deletes this VM (including all its files).
|
|
1770
|
+
"""
|
|
1771
|
+
|
|
1772
|
+
try:
|
|
1773
|
+
await wait_run_in_executor(shutil.rmtree, self._working_directory)
|
|
1774
|
+
except OSError as e:
|
|
1775
|
+
log.warning(f"Could not delete file {e}")
|
|
1776
|
+
|
|
1777
|
+
self.manager.release_dynamips_id(self._project.id, self._dynamips_id)
|
|
1778
|
+
|
|
1779
|
+
async def clean_delete(self):
|
|
1780
|
+
"""
|
|
1781
|
+
Deletes this router & associated files (nvram, disks etc.)
|
|
1782
|
+
"""
|
|
1783
|
+
|
|
1784
|
+
await self._hypervisor.send(f'vm clean_delete "{self._name}"')
|
|
1785
|
+
self._hypervisor.devices.remove(self)
|
|
1786
|
+
try:
|
|
1787
|
+
await wait_run_in_executor(shutil.rmtree, self._working_directory)
|
|
1788
|
+
except OSError as e:
|
|
1789
|
+
log.warning(f"Could not delete file {e}")
|
|
1790
|
+
log.info(f'Router "{self._name}" [{self._id}] has been deleted (including associated files)')
|
|
1791
|
+
|
|
1792
|
+
def _memory_files(self):
|
|
1793
|
+
|
|
1794
|
+
return [
|
|
1795
|
+
os.path.join(self._working_directory, f"{self.platform}_i{self.dynamips_id}_rom"),
|
|
1796
|
+
os.path.join(self._working_directory, f"{self.platform}_i{self.dynamips_id}_nvram"),
|
|
1797
|
+
]
|