diff --git a/gns3server/handlers/__init__.py b/gns3server/handlers/__init__.py
index de1a5c0b..727b4053 100644
--- a/gns3server/handlers/__init__.py
+++ b/gns3server/handlers/__init__.py
@@ -1 +1,6 @@
-__all__ = ['version_handler', 'network_handler', 'vpcs_handler', 'project_handler', 'virtualbox_handler']
+__all__ = ["version_handler",
+ "network_handler",
+ "vpcs_handler",
+ "project_handler",
+ "virtualbox_handler",
+ "dynamips_handler"]
diff --git a/gns3server/handlers/dynamips_handler.py b/gns3server/handlers/dynamips_handler.py
new file mode 100644
index 00000000..f7929708
--- /dev/null
+++ b/gns3server/handlers/dynamips_handler.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2015 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import os
+from ..web.route import Route
+from ..schemas.dynamips import ROUTER_CREATE_SCHEMA
+from ..schemas.dynamips import ROUTER_OBJECT_SCHEMA
+from ..modules.dynamips import Dynamips
+from ..modules.project_manager import ProjectManager
+
+
+class DynamipsHandler:
+
+ """
+ API entry points for Dynamips.
+ """
+
+ @classmethod
+ @Route.post(
+ r"/projects/{project_id}/dynamips/routers",
+ parameters={
+ "project_id": "UUID for the project"
+ },
+ status_codes={
+ 201: "Instance created",
+ 400: "Invalid request",
+ 409: "Conflict"
+ },
+ description="Create a new Dynamips router instance",
+ input=ROUTER_CREATE_SCHEMA)
+ #output=ROUTER_OBJECT_SCHEMA)
+ def create(request, response):
+
+ dynamips_manager = Dynamips.instance()
+ vm = yield from dynamips_manager.create_vm(request.json.pop("name"),
+ request.match_info["project_id"],
+ request.json.get("vm_id"))
+
+ #for name, value in request.json.items():
+ # if hasattr(vm, name) and getattr(vm, name) != value:
+ # setattr(vm, name, value)
+
+ response.set_status(201)
+ response.json(vm)
diff --git a/gns3server/modules/__init__.py b/gns3server/modules/__init__.py
index 5127dd83..4e2f51bb 100644
--- a/gns3server/modules/__init__.py
+++ b/gns3server/modules/__init__.py
@@ -15,8 +15,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import sys
from .vpcs import VPCS
from .virtualbox import VirtualBox
+from .dynamips import Dynamips
-MODULES = [VPCS, VirtualBox]
+MODULES = [VPCS, VirtualBox, Dynamips]
diff --git a/gns3server/modules/dynamips/__init__.py b/gns3server/modules/dynamips/__init__.py
new file mode 100644
index 00000000..9e9246bd
--- /dev/null
+++ b/gns3server/modules/dynamips/__init__.py
@@ -0,0 +1,611 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2015 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""
+Dynamips server module.
+"""
+
+import sys
+import os
+import base64
+import tempfile
+import shutil
+import glob
+import socket
+from gns3server.config import Config
+
+# from .hypervisor import Hypervisor
+# from .hypervisor_manager import HypervisorManager
+# from .dynamips_error import DynamipsError
+#
+# # Nodes
+# from .nodes.router import Router
+# from .nodes.c1700 import C1700
+# from .nodes.c2600 import C2600
+# from .nodes.c2691 import C2691
+# from .nodes.c3600 import C3600
+# from .nodes.c3725 import C3725
+# from .nodes.c3745 import C3745
+# from .nodes.c7200 import C7200
+# from .nodes.bridge import Bridge
+# from .nodes.ethernet_switch import EthernetSwitch
+# from .nodes.atm_switch import ATMSwitch
+# from .nodes.atm_bridge import ATMBridge
+# from .nodes.frame_relay_switch import FrameRelaySwitch
+# from .nodes.hub import Hub
+#
+# # Adapters
+# from .adapters.c7200_io_2fe import C7200_IO_2FE
+# from .adapters.c7200_io_fe import C7200_IO_FE
+# from .adapters.c7200_io_ge_e import C7200_IO_GE_E
+# from .adapters.nm_16esw import NM_16ESW
+# from .adapters.nm_1e import NM_1E
+# from .adapters.nm_1fe_tx import NM_1FE_TX
+# from .adapters.nm_4e import NM_4E
+# from .adapters.nm_4t import NM_4T
+# from .adapters.pa_2fe_tx import PA_2FE_TX
+# from .adapters.pa_4e import PA_4E
+# from .adapters.pa_4t import PA_4T
+# from .adapters.pa_8e import PA_8E
+# from .adapters.pa_8t import PA_8T
+# from .adapters.pa_a1 import PA_A1
+# from .adapters.pa_fe_tx import PA_FE_TX
+# from .adapters.pa_ge import PA_GE
+# from .adapters.pa_pos_oc3 import PA_POS_OC3
+# from .adapters.wic_1t import WIC_1T
+# from .adapters.wic_2t import WIC_2T
+# from .adapters.wic_1enet import WIC_1ENET
+#
+# # NIOs
+# from .nios.nio_udp import NIO_UDP
+# from .nios.nio_udp_auto import NIO_UDP_auto
+# from .nios.nio_unix import NIO_UNIX
+# from .nios.nio_vde import NIO_VDE
+# from .nios.nio_tap import NIO_TAP
+# from .nios.nio_generic_ethernet import NIO_GenericEthernet
+# from .nios.nio_linux_ethernet import NIO_LinuxEthernet
+# from .nios.nio_fifo import NIO_FIFO
+# from .nios.nio_mcast import NIO_Mcast
+# from .nios.nio_null import NIO_Null
+#
+# from .backends import vm
+# from .backends import ethsw
+# from .backends import ethhub
+# from .backends import frsw
+# from .backends import atmsw
+
+import time
+import asyncio
+import logging
+
+log = logging.getLogger(__name__)
+
+from pkg_resources import parse_version
+from ..base_manager import BaseManager
+from .dynamips_error import DynamipsError
+from .hypervisor import Hypervisor
+from .nodes.router import Router
+
+
+class Dynamips(BaseManager):
+
+ _VM_CLASS = Router
+
+ def __init__(self):
+
+ super().__init__()
+ self._dynamips_path = None
+
+ # FIXME: temporary
+ self._working_dir = "/tmp"
+ self._dynamips_path = "/usr/local/bin/dynamips"
+
+ def find_dynamips(self):
+
+ # look for Dynamips
+ dynamips_path = self.config.get_section_config("Dynamips").get("dynamips_path")
+ if not dynamips_path:
+ dynamips_path = shutil.which("dynamips")
+
+ if not dynamips_path:
+ raise DynamipsError("Could not find Dynamips")
+ if not os.path.isfile(dynamips_path):
+ raise DynamipsError("Dynamips {} is not accessible".format(dynamips_path))
+ if not os.access(dynamips_path, os.X_OK):
+ raise DynamipsError("Dynamips is not executable")
+
+ self._dynamips_path = dynamips_path
+ return dynamips_path
+
+ @asyncio.coroutine
+ def _wait_for_hypervisor(self, host, port, timeout=10.0):
+ """
+ Waits for an hypervisor to be started (accepting a socket connection)
+
+ :param host: host/address to connect to the hypervisor
+ :param port: port to connect to the hypervisor
+ """
+
+ begin = time.time()
+ connection_success = False
+ last_exception = None
+ while time.time() - begin < timeout:
+ yield from asyncio.sleep(0.01)
+ try:
+ _, writer = yield from asyncio.open_connection(host, port)
+ writer.close()
+ except OSError as e:
+ last_exception = e
+ continue
+ connection_success = True
+ break
+
+ if not connection_success:
+ raise DynamipsError("Couldn't connect to hypervisor on {}:{} :{}".format(host, port, last_exception))
+ else:
+ log.info("Dynamips server ready after {:.4f} seconds".format(time.time() - begin))
+
+ @asyncio.coroutine
+ def start_new_hypervisor(self):
+ """
+ Creates a new Dynamips process and start it.
+
+ :returns: the new hypervisor instance
+ """
+
+ try:
+ # let the OS find an unused port for the Dynamips hypervisor
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.bind(("127.0.0.1", 0))
+ port = sock.getsockname()[1]
+ except OSError as e:
+ raise DynamipsError("Could not find free port for the Dynamips hypervisor: {}".format(e))
+
+ hypervisor = Hypervisor(self._dynamips_path, self._working_dir, "127.0.0.1", port)
+
+ log.info("Ceating new hypervisor {}:{} with working directory {}".format(hypervisor.host, hypervisor.port, self._working_dir))
+ yield from hypervisor.start()
+
+ yield from self._wait_for_hypervisor("127.0.0.1", port)
+ log.info("Hypervisor {}:{} has successfully started".format(hypervisor.host, hypervisor.port))
+
+ yield from hypervisor.connect()
+ if parse_version(hypervisor.version) < parse_version('0.2.11'):
+ raise DynamipsError("Dynamips version must be >= 0.2.11, detected version is {}".format(hypervisor.version))
+
+ return hypervisor
+
+
+# class Dynamips(IModule):
+# """
+# Dynamips module.
+#
+# :param name: module name
+# :param args: arguments for the module
+# :param kwargs: named arguments for the module
+# """
+#
+# def stop(self, signum=None):
+# """
+# Properly stops the module.
+#
+# :param signum: signal number (if called by the signal handler)
+# """
+#
+# if not sys.platform.startswith("win32"):
+# self._callback.stop()
+#
+# # automatically save configs for all router instances
+# for router_id in self._routers:
+# router = self._routers[router_id]
+# try:
+# router.save_configs()
+# except DynamipsError:
+# continue
+#
+# # stop all Dynamips hypervisors
+# if self._hypervisor_manager:
+# self._hypervisor_manager.stop_all_hypervisors()
+#
+# self.delete_dynamips_files()
+# IModule.stop(self, signum) # this will stop the I/O loop
+#
+# def get_device_instance(self, device_id, instance_dict):
+# """
+# Returns a device instance.
+#
+# :param device_id: device identifier
+# :param instance_dict: dictionary containing the instances
+#
+# :returns: device instance
+# """
+#
+# if device_id not in instance_dict:
+# log.debug("device ID {} doesn't exist".format(device_id), exc_info=1)
+# self.send_custom_error("Device ID {} doesn't exist".format(device_id))
+# return None
+# return instance_dict[device_id]
+#
+# def delete_dynamips_files(self):
+# """
+# Deletes useless Dynamips files from the working directory
+# """
+#
+# files = glob.glob(os.path.join(self._working_dir, "dynamips", "*.ghost"))
+# files += glob.glob(os.path.join(self._working_dir, "dynamips", "*_lock"))
+# files += glob.glob(os.path.join(self._working_dir, "dynamips", "ilt_*"))
+# files += glob.glob(os.path.join(self._working_dir, "dynamips", "c[0-9][0-9][0-9][0-9]_*_rommon_vars"))
+# files += glob.glob(os.path.join(self._working_dir, "dynamips", "c[0-9][0-9][0-9][0-9]_*_ssa"))
+# for file in files:
+# try:
+# log.debug("deleting file {}".format(file))
+# os.remove(file)
+# except OSError as e:
+# log.warn("could not delete file {}: {}".format(file, e))
+# continue
+#
+# @IModule.route("dynamips.reset")
+# def reset(self, request=None):
+# """
+# Resets the module (JSON-RPC notification).
+#
+# :param request: JSON request (not used)
+# """
+#
+# # automatically save configs for all router instances
+# for router_id in self._routers:
+# router = self._routers[router_id]
+# try:
+# router.save_configs()
+# except DynamipsError:
+# continue
+#
+# # stop all Dynamips hypervisors
+# if self._hypervisor_manager:
+# self._hypervisor_manager.stop_all_hypervisors()
+#
+# # resets the instance counters
+# Router.reset()
+# EthernetSwitch.reset()
+# Hub.reset()
+# FrameRelaySwitch.reset()
+# ATMSwitch.reset()
+# NIO_UDP.reset()
+# NIO_UDP_auto.reset()
+# NIO_UNIX.reset()
+# NIO_VDE.reset()
+# NIO_TAP.reset()
+# NIO_GenericEthernet.reset()
+# NIO_LinuxEthernet.reset()
+# NIO_FIFO.reset()
+# NIO_Mcast.reset()
+# NIO_Null.reset()
+#
+# self._routers.clear()
+# self._ethernet_switches.clear()
+# self._frame_relay_switches.clear()
+# self._atm_switches.clear()
+#
+# self.delete_dynamips_files()
+#
+# self._hypervisor_manager = None
+# self._working_dir = self._projects_dir
+# log.info("dynamips module has been reset")
+#
+# def start_hypervisor_manager(self):
+# """
+# Starts the hypervisor manager.
+# """
+#
+# # check if Dynamips path exists
+# if not os.path.isfile(self._dynamips):
+# raise DynamipsError("Dynamips executable {} doesn't exist".format(self._dynamips))
+#
+# # check if Dynamips is executable
+# if not os.access(self._dynamips, os.X_OK):
+# raise DynamipsError("Dynamips {} is not executable".format(self._dynamips))
+#
+# workdir = os.path.join(self._working_dir, "dynamips")
+# try:
+# os.makedirs(workdir)
+# except FileExistsError:
+# pass
+# except OSError as e:
+# raise DynamipsError("Could not create working directory {}".format(e))
+#
+# # check if the working directory is writable
+# if not os.access(workdir, os.W_OK):
+# raise DynamipsError("Cannot write to working directory {}".format(workdir))
+#
+# log.info("starting the hypervisor manager with Dynamips working directory set to '{}'".format(workdir))
+# self._hypervisor_manager = HypervisorManager(self._dynamips, workdir, self._host, self._console_host)
+#
+# for name, value in self._hypervisor_manager_settings.items():
+# if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value:
+# setattr(self._hypervisor_manager, name, value)
+#
+# @IModule.route("dynamips.settings")
+# def settings(self, request):
+# """
+# Set or update settings.
+#
+# Optional request parameters:
+# - path (path to the Dynamips executable)
+# - working_dir (path to a working directory)
+# - project_name
+#
+# :param request: JSON request
+# """
+#
+# if request is None:
+# self.send_param_error()
+# return
+#
+# log.debug("received request {}".format(request))
+#
+# #TODO: JSON schema validation
+# if not self._hypervisor_manager:
+#
+# if "path" in request:
+# self._dynamips = request.pop("path")
+#
+# if "working_dir" in request:
+# self._working_dir = request.pop("working_dir")
+# log.info("this server is local")
+# else:
+# self._working_dir = os.path.join(self._projects_dir, request["project_name"])
+# log.info("this server is remote with working directory path to {}".format(self._working_dir))
+#
+# self._hypervisor_manager_settings = request
+#
+# else:
+# if "project_name" in request:
+# # for remote server
+# new_working_dir = os.path.join(self._projects_dir, request["project_name"])
+#
+# if self._projects_dir != self._working_dir != new_working_dir:
+#
+# # trick to avoid file locks by Dynamips on Windows
+# if sys.platform.startswith("win"):
+# self._hypervisor_manager.working_dir = tempfile.gettempdir()
+#
+# if not os.path.isdir(new_working_dir):
+# try:
+# self.delete_dynamips_files()
+# shutil.move(self._working_dir, new_working_dir)
+# except OSError as e:
+# log.error("could not move working directory from {} to {}: {}".format(self._working_dir,
+# new_working_dir,
+# e))
+# return
+#
+# elif "working_dir" in request:
+# # for local server
+# new_working_dir = request.pop("working_dir")
+#
+# try:
+# self._hypervisor_manager.working_dir = new_working_dir
+# except DynamipsError as e:
+# log.error("could not change working directory: {}".format(e))
+# return
+#
+# self._working_dir = new_working_dir
+#
+# # apply settings to the hypervisor manager
+# for name, value in request.items():
+# if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value:
+# setattr(self._hypervisor_manager, name, value)
+#
+# @IModule.route("dynamips.echo")
+# def echo(self, request):
+# """
+# Echo end point for testing purposes.
+#
+# :param request: JSON request
+# """
+#
+# if request is None:
+# self.send_param_error()
+# else:
+# log.debug("received request {}".format(request))
+# self.send_response(request)
+#
+# def create_nio(self, node, request):
+# """
+# Creates a new NIO.
+#
+# :param node: node requesting the NIO
+# :param request: the original request with the
+# necessary information to create the NIO
+#
+# :returns: a NIO object
+# """
+#
+# nio = None
+# if request["nio"]["type"] == "nio_udp":
+# lport = request["nio"]["lport"]
+# rhost = request["nio"]["rhost"]
+# rport = request["nio"]["rport"]
+# try:
+# #TODO: handle IPv6
+# with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
+# sock.connect((rhost, rport))
+# except OSError as e:
+# raise DynamipsError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
+# # check if we have an allocated NIO UDP auto
+# nio = node.hypervisor.get_nio_udp_auto(lport)
+# if not nio:
+# # otherwise create an NIO UDP
+# nio = NIO_UDP(node.hypervisor, lport, rhost, rport)
+# else:
+# nio.connect(rhost, rport)
+# elif request["nio"]["type"] == "nio_generic_ethernet":
+# ethernet_device = request["nio"]["ethernet_device"]
+# if sys.platform.startswith("win"):
+# # replace the interface name by the GUID on Windows
+# interfaces = get_windows_interfaces()
+# npf_interface = None
+# for interface in interfaces:
+# if interface["name"] == ethernet_device:
+# npf_interface = interface["id"]
+# if not npf_interface:
+# raise DynamipsError("Could not find interface {} on this host".format(ethernet_device))
+# else:
+# ethernet_device = npf_interface
+# nio = NIO_GenericEthernet(node.hypervisor, ethernet_device)
+# elif request["nio"]["type"] == "nio_linux_ethernet":
+# if sys.platform.startswith("win"):
+# raise DynamipsError("This NIO type is not supported on Windows")
+# ethernet_device = request["nio"]["ethernet_device"]
+# nio = NIO_LinuxEthernet(node.hypervisor, ethernet_device)
+# elif request["nio"]["type"] == "nio_tap":
+# tap_device = request["nio"]["tap_device"]
+# nio = NIO_TAP(node.hypervisor, tap_device)
+# elif request["nio"]["type"] == "nio_unix":
+# local_file = request["nio"]["local_file"]
+# remote_file = request["nio"]["remote_file"]
+# nio = NIO_UNIX(node.hypervisor, local_file, remote_file)
+# elif request["nio"]["type"] == "nio_vde":
+# control_file = request["nio"]["control_file"]
+# local_file = request["nio"]["local_file"]
+# nio = NIO_VDE(node.hypervisor, control_file, local_file)
+# elif request["nio"]["type"] == "nio_null":
+# nio = NIO_Null(node.hypervisor)
+# return nio
+#
+# def allocate_udp_port(self, node):
+# """
+# Allocates a UDP port in order to create an UDP NIO.
+#
+# :param node: the node that needs to allocate an UDP port
+#
+# :returns: dictionary with the allocated host/port info
+# """
+#
+# port = node.hypervisor.allocate_udp_port()
+# host = node.hypervisor.host
+#
+# log.info("{} [id={}] has allocated UDP port {} with host {}".format(node.name,
+# node.id,
+# port,
+# host))
+# response = {"lport": port}
+# return response
+#
+# def set_ghost_ios(self, router):
+# """
+# Manages Ghost IOS support.
+#
+# :param router: Router instance
+# """
+#
+# if not router.mmap:
+# raise DynamipsError("mmap support is required to enable ghost IOS support")
+#
+# ghost_instance = router.formatted_ghost_file()
+# all_ghosts = []
+#
+# # search of an existing ghost instance across all hypervisors
+# for hypervisor in self._hypervisor_manager.hypervisors:
+# all_ghosts.extend(hypervisor.ghosts)
+#
+# if ghost_instance not in all_ghosts:
+# # create a new ghost IOS instance
+# ghost = Router(router.hypervisor, "ghost-" + ghost_instance, router.platform, ghost_flag=True)
+# ghost.image = router.image
+# # for 7200s, the NPE must be set when using an NPE-G2.
+# if router.platform == "c7200":
+# ghost.npe = router.npe
+# ghost.ghost_status = 1
+# ghost.ghost_file = ghost_instance
+# ghost.ram = router.ram
+# try:
+# ghost.start()
+# ghost.stop()
+# except DynamipsError:
+# raise
+# finally:
+# ghost.clean_delete()
+#
+# if router.ghost_file != ghost_instance:
+# # set the ghost file to the router
+# router.ghost_status = 2
+# router.ghost_file = ghost_instance
+#
+# def create_config_from_file(self, local_base_config, router, destination_config_path):
+# """
+# Creates a config file from a local base config
+#
+# :param local_base_config: path the a local base config
+# :param router: router instance
+# :param destination_config_path: path to the destination config file
+#
+# :returns: relative path to the created config file
+# """
+#
+# log.info("creating config file {} from {}".format(destination_config_path, local_base_config))
+# config_path = destination_config_path
+# config_dir = os.path.dirname(destination_config_path)
+# try:
+# os.makedirs(config_dir)
+# except FileExistsError:
+# pass
+# except OSError as e:
+# raise DynamipsError("Could not create configs directory: {}".format(e))
+#
+# try:
+# with open(local_base_config, "r", errors="replace") as f:
+# config = f.read()
+# with open(config_path, "w") as f:
+# config = "!\n" + config.replace("\r", "")
+# config = config.replace('%h', router.name)
+# f.write(config)
+# except OSError as e:
+# raise DynamipsError("Could not save the configuration from {} to {}: {}".format(local_base_config, config_path, e))
+# return "configs" + os.sep + os.path.basename(config_path)
+#
+# def create_config_from_base64(self, config_base64, router, destination_config_path):
+# """
+# Creates a config file from a base64 encoded config.
+#
+# :param config_base64: base64 encoded config
+# :param router: router instance
+# :param destination_config_path: path to the destination config file
+#
+# :returns: relative path to the created config file
+# """
+#
+# log.info("creating config file {} from base64".format(destination_config_path))
+# config = base64.decodebytes(config_base64.encode("utf-8")).decode("utf-8")
+# config = "!\n" + config.replace("\r", "")
+# config = config.replace('%h', router.name)
+# config_dir = os.path.dirname(destination_config_path)
+# try:
+# os.makedirs(config_dir)
+# except FileExistsError:
+# pass
+# except OSError as e:
+# raise DynamipsError("Could not create configs directory: {}".format(e))
+#
+# config_path = destination_config_path
+# try:
+# with open(config_path, "w") as f:
+# log.info("saving startup-config to {}".format(config_path))
+# f.write(config)
+# except OSError as e:
+# raise DynamipsError("Could not save the configuration {}: {}".format(config_path, e))
+# return "configs" + os.sep + os.path.basename(config_path)
diff --git a/gns3server/old_modules/dynamips/adapters/__init__.py b/gns3server/modules/dynamips/adapters/__init__.py
similarity index 100%
rename from gns3server/old_modules/dynamips/adapters/__init__.py
rename to gns3server/modules/dynamips/adapters/__init__.py
diff --git a/gns3server/old_modules/dynamips/adapters/adapter.py b/gns3server/modules/dynamips/adapters/adapter.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/adapter.py
rename to gns3server/modules/dynamips/adapters/adapter.py
index 40d82c7e..d963933e 100644
--- a/gns3server/old_modules/dynamips/adapters/adapter.py
+++ b/gns3server/modules/dynamips/adapters/adapter.py
@@ -17,7 +17,6 @@
class Adapter(object):
-
"""
Base class for adapters.
diff --git a/gns3server/old_modules/dynamips/adapters/c1700_mb_1fe.py b/gns3server/modules/dynamips/adapters/c1700_mb_1fe.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/c1700_mb_1fe.py
rename to gns3server/modules/dynamips/adapters/c1700_mb_1fe.py
index c94f551d..3c67f3df 100644
--- a/gns3server/old_modules/dynamips/adapters/c1700_mb_1fe.py
+++ b/gns3server/modules/dynamips/adapters/c1700_mb_1fe.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class C1700_MB_1FE(Adapter):
-
"""
Integrated 1 port FastEthernet adapter for c1700 platform.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/c1700_mb_wic1.py b/gns3server/modules/dynamips/adapters/c1700_mb_wic1.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/c1700_mb_wic1.py
rename to gns3server/modules/dynamips/adapters/c1700_mb_wic1.py
index 9c6d2190..eca72358 100644
--- a/gns3server/old_modules/dynamips/adapters/c1700_mb_wic1.py
+++ b/gns3server/modules/dynamips/adapters/c1700_mb_wic1.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class C1700_MB_WIC1(Adapter):
-
"""
Fake module to provide a placeholder for slot 1 interfaces when WICs
are inserted into WIC slot 1.
diff --git a/gns3server/old_modules/dynamips/adapters/c2600_mb_1e.py b/gns3server/modules/dynamips/adapters/c2600_mb_1e.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/c2600_mb_1e.py
rename to gns3server/modules/dynamips/adapters/c2600_mb_1e.py
index bebe7fa9..26fe5497 100644
--- a/gns3server/old_modules/dynamips/adapters/c2600_mb_1e.py
+++ b/gns3server/modules/dynamips/adapters/c2600_mb_1e.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class C2600_MB_1E(Adapter):
-
"""
Integrated 1 port Ethernet adapter for the c2600 platform.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/c2600_mb_1fe.py b/gns3server/modules/dynamips/adapters/c2600_mb_1fe.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/c2600_mb_1fe.py
rename to gns3server/modules/dynamips/adapters/c2600_mb_1fe.py
index 1ad294f2..768d9c95 100644
--- a/gns3server/old_modules/dynamips/adapters/c2600_mb_1fe.py
+++ b/gns3server/modules/dynamips/adapters/c2600_mb_1fe.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class C2600_MB_1FE(Adapter):
-
"""
Integrated 1 port FastEthernet adapter for the c2600 platform.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/c2600_mb_2e.py b/gns3server/modules/dynamips/adapters/c2600_mb_2e.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/c2600_mb_2e.py
rename to gns3server/modules/dynamips/adapters/c2600_mb_2e.py
index 1e42d5dd..c2ca7442 100644
--- a/gns3server/old_modules/dynamips/adapters/c2600_mb_2e.py
+++ b/gns3server/modules/dynamips/adapters/c2600_mb_2e.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class C2600_MB_2E(Adapter):
-
"""
Integrated 2 port Ethernet adapter for the c2600 platform.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/c2600_mb_2fe.py b/gns3server/modules/dynamips/adapters/c2600_mb_2fe.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/c2600_mb_2fe.py
rename to gns3server/modules/dynamips/adapters/c2600_mb_2fe.py
index dcd96581..a7e6df14 100644
--- a/gns3server/old_modules/dynamips/adapters/c2600_mb_2fe.py
+++ b/gns3server/modules/dynamips/adapters/c2600_mb_2fe.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class C2600_MB_2FE(Adapter):
-
"""
Integrated 2 port FastEthernet adapter for the c2600 platform.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/c7200_io_2fe.py b/gns3server/modules/dynamips/adapters/c7200_io_2fe.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/c7200_io_2fe.py
rename to gns3server/modules/dynamips/adapters/c7200_io_2fe.py
index 8b545e99..0b8ae8a4 100644
--- a/gns3server/old_modules/dynamips/adapters/c7200_io_2fe.py
+++ b/gns3server/modules/dynamips/adapters/c7200_io_2fe.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class C7200_IO_2FE(Adapter):
-
"""
C7200-IO-2FE FastEthernet Input/Ouput controller.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/c7200_io_fe.py b/gns3server/modules/dynamips/adapters/c7200_io_fe.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/c7200_io_fe.py
rename to gns3server/modules/dynamips/adapters/c7200_io_fe.py
index 784b154d..56e86cf1 100644
--- a/gns3server/old_modules/dynamips/adapters/c7200_io_fe.py
+++ b/gns3server/modules/dynamips/adapters/c7200_io_fe.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class C7200_IO_FE(Adapter):
-
"""
C7200-IO-FE FastEthernet Input/Ouput controller.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/c7200_io_ge_e.py b/gns3server/modules/dynamips/adapters/c7200_io_ge_e.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/c7200_io_ge_e.py
rename to gns3server/modules/dynamips/adapters/c7200_io_ge_e.py
index f233dffd..12ebaed6 100644
--- a/gns3server/old_modules/dynamips/adapters/c7200_io_ge_e.py
+++ b/gns3server/modules/dynamips/adapters/c7200_io_ge_e.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class C7200_IO_GE_E(Adapter):
-
"""
C7200-IO-GE-E GigabitEthernet Input/Ouput controller.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/gt96100_fe.py b/gns3server/modules/dynamips/adapters/gt96100_fe.py
similarity index 100%
rename from gns3server/old_modules/dynamips/adapters/gt96100_fe.py
rename to gns3server/modules/dynamips/adapters/gt96100_fe.py
diff --git a/gns3server/old_modules/dynamips/adapters/leopard_2fe.py b/gns3server/modules/dynamips/adapters/leopard_2fe.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/leopard_2fe.py
rename to gns3server/modules/dynamips/adapters/leopard_2fe.py
index db6ad9c2..0afa95c0 100644
--- a/gns3server/old_modules/dynamips/adapters/leopard_2fe.py
+++ b/gns3server/modules/dynamips/adapters/leopard_2fe.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class Leopard_2FE(Adapter):
-
"""
Integrated 2 port FastEthernet adapter for c3660 router.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/nm_16esw.py b/gns3server/modules/dynamips/adapters/nm_16esw.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/nm_16esw.py
rename to gns3server/modules/dynamips/adapters/nm_16esw.py
index 31e74565..fc3755cd 100644
--- a/gns3server/old_modules/dynamips/adapters/nm_16esw.py
+++ b/gns3server/modules/dynamips/adapters/nm_16esw.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class NM_16ESW(Adapter):
-
"""
NM-16ESW FastEthernet network module.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/nm_1e.py b/gns3server/modules/dynamips/adapters/nm_1e.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/nm_1e.py
rename to gns3server/modules/dynamips/adapters/nm_1e.py
index 59ac5569..ac200247 100644
--- a/gns3server/old_modules/dynamips/adapters/nm_1e.py
+++ b/gns3server/modules/dynamips/adapters/nm_1e.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class NM_1E(Adapter):
-
"""
NM-1E Ethernet network module.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/nm_1fe_tx.py b/gns3server/modules/dynamips/adapters/nm_1fe_tx.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/nm_1fe_tx.py
rename to gns3server/modules/dynamips/adapters/nm_1fe_tx.py
index 26568306..9723f703 100644
--- a/gns3server/old_modules/dynamips/adapters/nm_1fe_tx.py
+++ b/gns3server/modules/dynamips/adapters/nm_1fe_tx.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class NM_1FE_TX(Adapter):
-
"""
NM-1FE-TX FastEthernet network module.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/nm_4e.py b/gns3server/modules/dynamips/adapters/nm_4e.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/nm_4e.py
rename to gns3server/modules/dynamips/adapters/nm_4e.py
index 086b04ee..ae6a51ed 100644
--- a/gns3server/old_modules/dynamips/adapters/nm_4e.py
+++ b/gns3server/modules/dynamips/adapters/nm_4e.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class NM_4E(Adapter):
-
"""
NM-4E Ethernet network module.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/nm_4t.py b/gns3server/modules/dynamips/adapters/nm_4t.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/nm_4t.py
rename to gns3server/modules/dynamips/adapters/nm_4t.py
index 77c3ecc8..df6db299 100644
--- a/gns3server/old_modules/dynamips/adapters/nm_4t.py
+++ b/gns3server/modules/dynamips/adapters/nm_4t.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class NM_4T(Adapter):
-
"""
NM-4T Serial network module.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/pa_2fe_tx.py b/gns3server/modules/dynamips/adapters/pa_2fe_tx.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/pa_2fe_tx.py
rename to gns3server/modules/dynamips/adapters/pa_2fe_tx.py
index 09b677f3..8589ff2e 100644
--- a/gns3server/old_modules/dynamips/adapters/pa_2fe_tx.py
+++ b/gns3server/modules/dynamips/adapters/pa_2fe_tx.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class PA_2FE_TX(Adapter):
-
"""
PA-2FE-TX FastEthernet port adapter.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/pa_4e.py b/gns3server/modules/dynamips/adapters/pa_4e.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/pa_4e.py
rename to gns3server/modules/dynamips/adapters/pa_4e.py
index d5981860..32564992 100644
--- a/gns3server/old_modules/dynamips/adapters/pa_4e.py
+++ b/gns3server/modules/dynamips/adapters/pa_4e.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class PA_4E(Adapter):
-
"""
PA-4E Ethernet port adapter.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/pa_4t.py b/gns3server/modules/dynamips/adapters/pa_4t.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/pa_4t.py
rename to gns3server/modules/dynamips/adapters/pa_4t.py
index 5a1393bc..6a098a24 100644
--- a/gns3server/old_modules/dynamips/adapters/pa_4t.py
+++ b/gns3server/modules/dynamips/adapters/pa_4t.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class PA_4T(Adapter):
-
"""
PA-4T+ Serial port adapter.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/pa_8e.py b/gns3server/modules/dynamips/adapters/pa_8e.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/pa_8e.py
rename to gns3server/modules/dynamips/adapters/pa_8e.py
index 96684055..a6b5075f 100644
--- a/gns3server/old_modules/dynamips/adapters/pa_8e.py
+++ b/gns3server/modules/dynamips/adapters/pa_8e.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class PA_8E(Adapter):
-
"""
PA-8E Ethernet port adapter.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/pa_8t.py b/gns3server/modules/dynamips/adapters/pa_8t.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/pa_8t.py
rename to gns3server/modules/dynamips/adapters/pa_8t.py
index 723e026f..600a5c29 100644
--- a/gns3server/old_modules/dynamips/adapters/pa_8t.py
+++ b/gns3server/modules/dynamips/adapters/pa_8t.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class PA_8T(Adapter):
-
"""
PA-8T Serial port adapter.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/pa_a1.py b/gns3server/modules/dynamips/adapters/pa_a1.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/pa_a1.py
rename to gns3server/modules/dynamips/adapters/pa_a1.py
index 469d9ce4..21d51f15 100644
--- a/gns3server/old_modules/dynamips/adapters/pa_a1.py
+++ b/gns3server/modules/dynamips/adapters/pa_a1.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class PA_A1(Adapter):
-
"""
PA-A1 ATM port adapter.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/pa_fe_tx.py b/gns3server/modules/dynamips/adapters/pa_fe_tx.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/pa_fe_tx.py
rename to gns3server/modules/dynamips/adapters/pa_fe_tx.py
index 6434d2b4..70ce8489 100644
--- a/gns3server/old_modules/dynamips/adapters/pa_fe_tx.py
+++ b/gns3server/modules/dynamips/adapters/pa_fe_tx.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class PA_FE_TX(Adapter):
-
"""
PA-FE-TX FastEthernet port adapter.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/pa_ge.py b/gns3server/modules/dynamips/adapters/pa_ge.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/pa_ge.py
rename to gns3server/modules/dynamips/adapters/pa_ge.py
index e466d905..f0287408 100644
--- a/gns3server/old_modules/dynamips/adapters/pa_ge.py
+++ b/gns3server/modules/dynamips/adapters/pa_ge.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class PA_GE(Adapter):
-
"""
PA-GE GigabitEthernet port adapter.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/pa_pos_oc3.py b/gns3server/modules/dynamips/adapters/pa_pos_oc3.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/pa_pos_oc3.py
rename to gns3server/modules/dynamips/adapters/pa_pos_oc3.py
index de0bc5d1..b120de97 100644
--- a/gns3server/old_modules/dynamips/adapters/pa_pos_oc3.py
+++ b/gns3server/modules/dynamips/adapters/pa_pos_oc3.py
@@ -19,7 +19,6 @@ from .adapter import Adapter
class PA_POS_OC3(Adapter):
-
"""
PA-POS-OC3 port adapter.
"""
diff --git a/gns3server/old_modules/dynamips/adapters/wic_1enet.py b/gns3server/modules/dynamips/adapters/wic_1enet.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/wic_1enet.py
rename to gns3server/modules/dynamips/adapters/wic_1enet.py
index 2d5e62b7..dac79b6b 100644
--- a/gns3server/old_modules/dynamips/adapters/wic_1enet.py
+++ b/gns3server/modules/dynamips/adapters/wic_1enet.py
@@ -17,7 +17,6 @@
class WIC_1ENET(object):
-
"""
WIC-1ENET Ethernet
"""
diff --git a/gns3server/old_modules/dynamips/adapters/wic_1t.py b/gns3server/modules/dynamips/adapters/wic_1t.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/wic_1t.py
rename to gns3server/modules/dynamips/adapters/wic_1t.py
index 2067246d..0f7cb3ad 100644
--- a/gns3server/old_modules/dynamips/adapters/wic_1t.py
+++ b/gns3server/modules/dynamips/adapters/wic_1t.py
@@ -17,7 +17,6 @@
class WIC_1T(object):
-
"""
WIC-1T Serial
"""
diff --git a/gns3server/old_modules/dynamips/adapters/wic_2t.py b/gns3server/modules/dynamips/adapters/wic_2t.py
similarity index 99%
rename from gns3server/old_modules/dynamips/adapters/wic_2t.py
rename to gns3server/modules/dynamips/adapters/wic_2t.py
index b5af954e..2bf2d565 100644
--- a/gns3server/old_modules/dynamips/adapters/wic_2t.py
+++ b/gns3server/modules/dynamips/adapters/wic_2t.py
@@ -17,7 +17,6 @@
class WIC_2T(object):
-
"""
WIC-2T Serial
"""
diff --git a/gns3server/old_modules/dynamips/dynamips_error.py b/gns3server/modules/dynamips/dynamips_error.py
similarity index 96%
rename from gns3server/old_modules/dynamips/dynamips_error.py
rename to gns3server/modules/dynamips/dynamips_error.py
index 332c6bbb..58c306ee 100644
--- a/gns3server/old_modules/dynamips/dynamips_error.py
+++ b/gns3server/modules/dynamips/dynamips_error.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2013 GNS3 Technologies Inc.
+# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/gns3server/old_modules/dynamips/dynamips_hypervisor.py b/gns3server/modules/dynamips/dynamips_hypervisor.py
similarity index 58%
rename from gns3server/old_modules/dynamips/dynamips_hypervisor.py
rename to gns3server/modules/dynamips/dynamips_hypervisor.py
index 1ac01ee1..954d6d4b 100644
--- a/gns3server/old_modules/dynamips/dynamips_hypervisor.py
+++ b/gns3server/modules/dynamips/dynamips_hypervisor.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2013 GNS3 Technologies Inc.
+# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,14 +23,15 @@ http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L46
import socket
import re
import logging
+import asyncio
+
from .dynamips_error import DynamipsError
from .nios.nio_udp_auto import NIO_UDP_auto
log = logging.getLogger(__name__)
-class DynamipsHypervisor(object):
-
+class DynamipsHypervisor:
"""
Creates a new connection to a Dynamips server (also called hypervisor)
@@ -54,18 +55,20 @@ class DynamipsHypervisor(object):
self._ghosts = {}
self._jitsharing_groups = {}
self._working_dir = working_dir
- self._console_start_port_range = 2001
- self._console_end_port_range = 2500
- self._aux_start_port_range = 2501
- self._aux_end_port_range = 3000
- self._udp_start_port_range = 10001
- self._udp_end_port_range = 20000
+ # self._console_start_port_range = 2001
+ # self._console_end_port_range = 2500
+ # self._aux_start_port_range = 2501
+ # self._aux_end_port_range = 3000
+ # self._udp_start_port_range = 10001
+ # self._udp_end_port_range = 20000
self._nio_udp_auto_instances = {}
self._version = "N/A"
self._timeout = timeout
- self._socket = None
self._uuid = None
+ self._reader = None
+ self._writer = None
+ @asyncio.coroutine
def connect(self):
"""
Connects to the hypervisor.
@@ -81,19 +84,22 @@ class DynamipsHypervisor(object):
host = self._host
try:
- self._socket = socket.create_connection((host, self._port), self._timeout)
+ self._reader, self._writer = yield from asyncio.wait_for(asyncio.open_connection(host, self._port), timeout=self._timeout)
except OSError as e:
- raise DynamipsError("Could not connect to server: {}".format(e))
+ raise DynamipsError("Could not connect to hypervisor {}:{} {}".format(host, self._port, e))
+ except asyncio.TimeoutError:
+ raise DynamipsError("Timeout error while connecting to hypervisor {}:{}".format(host, self._port))
try:
- self._version = self.send("hypervisor version")[0].split("-", 1)[0]
+ version = yield from self.send("hypervisor version")
+ self._version = version[0].split("-", 1)[0]
except IndexError:
self._version = "Unknown"
- self._uuid = self.send("hypervisor uuid")
+ self._uuid = yield from self.send("hypervisor uuid")
# this forces to send the working dir to Dynamips
- self.working_dir = self._working_dir
+ yield from self.set_working_dir(self._working_dir)
@property
def version(self):
@@ -105,54 +111,49 @@ class DynamipsHypervisor(object):
return self._version
- def module_list(self):
- """
- Returns the modules supported by this hypervisor.
-
- :returns: module list
- """
-
- return self.send("hypervisor module_list")
-
- def cmd_list(self, module):
- """
- Returns commands recognized by the specified module.
-
- :param module: the module name
- :returns: command list
- """
-
- return self.send("hypervisor cmd_list {}".format(module))
-
+ @asyncio.coroutine
def close(self):
"""
Closes the connection to this hypervisor (but leave it running).
"""
- self.send("hypervisor close")
- self._socket.shutdown(socket.SHUT_RDWR)
- self._socket.close()
- self._socket = None
+ yield from self.send("hypervisor close")
+ self._writer.close()
+ self._reader, self._writer = None
+ @asyncio.coroutine
def stop(self):
"""
Stops this hypervisor (will no longer run).
"""
- self.send("hypervisor stop")
- self._socket.shutdown(socket.SHUT_RDWR)
- self._socket.close()
- self._socket = None
+ yield from self.send("hypervisor stop")
+ self._writer.close()
+ self._reader, self._writer = None
self._nio_udp_auto_instances.clear()
+ @asyncio.coroutine
def reset(self):
"""
Resets this hypervisor (used to get an empty configuration).
"""
- self.send('hypervisor reset')
+ yield from self.send("hypervisor reset")
self._nio_udp_auto_instances.clear()
+ @asyncio.coroutine
+ def set_working_dir(self, working_dir):
+ """
+ Sets the working directory for this hypervisor.
+
+ :param working_dir: path to the working directory
+ """
+
+ # encase working_dir in quotes to protect spaces in the path
+ yield from self.send("hypervisor working_dir {}".format('"' + working_dir + '"'))
+ self._working_dir = working_dir
+ log.debug("Working directory set to {}".format(self._working_dir))
+
@property
def working_dir(self):
"""
@@ -163,29 +164,6 @@ class DynamipsHypervisor(object):
return self._working_dir
- @working_dir.setter
- def working_dir(self, working_dir):
- """
- Sets the working directory for this hypervisor.
-
- :param working_dir: path to the working directory
- """
-
- # encase working_dir in quotes to protect spaces in the path
- self.send("hypervisor working_dir {}".format('"' + working_dir + '"'))
- self._working_dir = working_dir
- log.debug("working directory set to {}".format(self._working_dir))
-
- def save_config(self, filename):
- """
- Saves the configuration of all Dynamips instances into the specified file.
-
- :param filename: path string
- """
-
- # encase working_dir in quotes to protect spaces in the path
- self.send("hypervisor save_config {}".format('"' + filename + '"'))
-
@property
def uuid(self):
"""
@@ -196,17 +174,6 @@ class DynamipsHypervisor(object):
return self._uuid
- @property
- def socket(self):
- """
- Returns the current socket used to communicate with this hypervisor.
-
- :returns: socket instance
- """
-
- assert self._socket
- return self._socket
-
@property
def devices(self):
"""
@@ -217,136 +184,136 @@ class DynamipsHypervisor(object):
return self._devices
- @devices.setter
- def devices(self, devices):
- """
- Sets the list of devices managed by this hypervisor instance.
- This method is for internal use.
+ # @devices.setter
+ # def devices(self, devices):
+ # """
+ # Sets the list of devices managed by this hypervisor instance.
+ # This method is for internal use.
+ #
+ # :param devices: a list of device objects
+ # """
+ #
+ # self._devices = devices
- :param devices: a list of device objects
- """
+ # @property
+ # def console_start_port_range(self):
+ # """
+ # Returns the console start port range value
+ #
+ # :returns: console start port range value (integer)
+ # """
+ #
+ # return self._console_start_port_range
- self._devices = devices
+ # @console_start_port_range.setter
+ # def console_start_port_range(self, console_start_port_range):
+ # """
+ # Set a new console start port range value
+ #
+ # :param console_start_port_range: console start port range value (integer)
+ # """
+ #
+ # self._console_start_port_range = console_start_port_range
+ #
+ # @property
+ # def console_end_port_range(self):
+ # """
+ # Returns the console end port range value
+ #
+ # :returns: console end port range value (integer)
+ # """
+ #
+ # return self._console_end_port_range
+ #
+ # @console_end_port_range.setter
+ # def console_end_port_range(self, console_end_port_range):
+ # """
+ # Set a new console end port range value
+ #
+ # :param console_end_port_range: console end port range value (integer)
+ # """
+ #
+ # self._console_end_port_range = console_end_port_range
- @property
- def console_start_port_range(self):
- """
- Returns the console start port range value
+ # @property
+ # def aux_start_port_range(self):
+ # """
+ # Returns the auxiliary console start port range value
+ #
+ # :returns: auxiliary console start port range value (integer)
+ # """
+ #
+ # return self._aux_start_port_range
+ #
+ # @aux_start_port_range.setter
+ # def aux_start_port_range(self, aux_start_port_range):
+ # """
+ # Sets a new auxiliary console start port range value
+ #
+ # :param aux_start_port_range: auxiliary console start port range value (integer)
+ # """
+ #
+ # self._aux_start_port_range = aux_start_port_range
+ #
+ # @property
+ # def aux_end_port_range(self):
+ # """
+ # Returns the auxiliary console end port range value
+ #
+ # :returns: auxiliary console end port range value (integer)
+ # """
+ #
+ # return self._aux_end_port_range
+ #
+ # @aux_end_port_range.setter
+ # def aux_end_port_range(self, aux_end_port_range):
+ # """
+ # Sets a new auxiliary console end port range value
+ #
+ # :param aux_end_port_range: auxiliary console end port range value (integer)
+ # """
+ #
+ # self._aux_end_port_range = aux_end_port_range
- :returns: console start port range value (integer)
- """
-
- return self._console_start_port_range
-
- @console_start_port_range.setter
- def console_start_port_range(self, console_start_port_range):
- """
- Set a new console start port range value
-
- :param console_start_port_range: console start port range value (integer)
- """
-
- self._console_start_port_range = console_start_port_range
-
- @property
- def console_end_port_range(self):
- """
- Returns the console end port range value
-
- :returns: console end port range value (integer)
- """
-
- return self._console_end_port_range
-
- @console_end_port_range.setter
- def console_end_port_range(self, console_end_port_range):
- """
- Set a new console end port range value
-
- :param console_end_port_range: console end port range value (integer)
- """
-
- self._console_end_port_range = console_end_port_range
-
- @property
- def aux_start_port_range(self):
- """
- Returns the auxiliary console start port range value
-
- :returns: auxiliary console start port range value (integer)
- """
-
- return self._aux_start_port_range
-
- @aux_start_port_range.setter
- def aux_start_port_range(self, aux_start_port_range):
- """
- Sets a new auxiliary console start port range value
-
- :param aux_start_port_range: auxiliary console start port range value (integer)
- """
-
- self._aux_start_port_range = aux_start_port_range
-
- @property
- def aux_end_port_range(self):
- """
- Returns the auxiliary console end port range value
-
- :returns: auxiliary console end port range value (integer)
- """
-
- return self._aux_end_port_range
-
- @aux_end_port_range.setter
- def aux_end_port_range(self, aux_end_port_range):
- """
- Sets a new auxiliary console end port range value
-
- :param aux_end_port_range: auxiliary console end port range value (integer)
- """
-
- self._aux_end_port_range = aux_end_port_range
-
- @property
- def udp_start_port_range(self):
- """
- Returns the UDP start port range value
-
- :returns: UDP start port range value (integer)
- """
-
- return self._udp_start_port_range
-
- @udp_start_port_range.setter
- def udp_start_port_range(self, udp_start_port_range):
- """
- Sets a new UDP start port range value
-
- :param udp_start_port_range: UDP start port range value (integer)
- """
-
- self._udp_start_port_range = udp_start_port_range
-
- @property
- def udp_end_port_range(self):
- """
- Returns the UDP end port range value
-
- :returns: UDP end port range value (integer)
- """
-
- return self._udp_end_port_range
-
- @udp_end_port_range.setter
- def udp_end_port_range(self, udp_end_port_range):
- """
- Sets an new UDP end port range value
-
- :param udp_end_port_range: UDP end port range value (integer)
- """
-
- self._udp_end_port_range = udp_end_port_range
+ # @property
+ # def udp_start_port_range(self):
+ # """
+ # Returns the UDP start port range value
+ #
+ # :returns: UDP start port range value (integer)
+ # """
+ #
+ # return self._udp_start_port_range
+ #
+ # @udp_start_port_range.setter
+ # def udp_start_port_range(self, udp_start_port_range):
+ # """
+ # Sets a new UDP start port range value
+ #
+ # :param udp_start_port_range: UDP start port range value (integer)
+ # """
+ #
+ # self._udp_start_port_range = udp_start_port_range
+ #
+ # @property
+ # def udp_end_port_range(self):
+ # """
+ # Returns the UDP end port range value
+ #
+ # :returns: UDP end port range value (integer)
+ # """
+ #
+ # return self._udp_end_port_range
+ #
+ # @udp_end_port_range.setter
+ # def udp_end_port_range(self, udp_end_port_range):
+ # """
+ # Sets an new UDP end port range value
+ #
+ # :param udp_end_port_range: UDP end port range value (integer)
+ # """
+ #
+ # self._udp_end_port_range = udp_end_port_range
@property
def ghosts(self):
@@ -388,25 +355,45 @@ class DynamipsHypervisor(object):
self._jitsharing_groups[image_name] = group_number
+ @property
+ def port(self):
+ """
+ Returns the port used to start the hypervisor.
+
+ :returns: port number (integer)
+ """
+
+ return self._port
+
+ @port.setter
+ def port(self, port):
+ """
+ Sets the port used to start the hypervisor.
+
+ :param port: port number (integer)
+ """
+
+ self._port = port
+
@property
def host(self):
"""
- Returns this hypervisor host.
+ Returns the host (binding) used to start the hypervisor.
- :returns: host (string)
+ :returns: host/address (string)
"""
return self._host
- @property
- def port(self):
+ @host.setter
+ def host(self, host):
"""
- Returns this hypervisor port.
+ Sets the host (binding) used to start the hypervisor.
- :returns: port (integer)
+ :param host: host/address (string)
"""
- return self._port
+ self._host = host
def get_nio_udp_auto(self, port):
"""
@@ -433,18 +420,7 @@ class DynamipsHypervisor(object):
allocated_port = nio.lport
return allocated_port
- def send_raw(self, string):
- """
- Sends a raw command to this hypervisor. Use sparingly.
-
- :param string: command string.
-
- :returns: command result (string)
- """
-
- result = self.send(string)
- return result
-
+ @asyncio.coroutine
def send(self, command):
"""
Sends commands to this hypervisor.
@@ -467,13 +443,13 @@ class DynamipsHypervisor(object):
# but still have more data. The only thing we know for sure is the last line
# will begin with '100-' or a '2xx-' and end with '\r\n'
- if not self._socket:
+ if self._writer is None or self._reader is None:
raise DynamipsError("Not connected")
try:
command = command.strip() + '\n'
log.debug("sending {}".format(command))
- self.socket.sendall(command.encode('utf-8'))
+ self._writer.write(command.encode())
except OSError as e:
raise DynamipsError("Lost communication with {host}:{port} :{error}, Dynamips process running: {run}"
.format(host=self._host, port=self._port, error=e, run=self.is_running()))
@@ -483,8 +459,8 @@ class DynamipsHypervisor(object):
buf = ''
while True:
try:
- chunk = self.socket.recv(1024) # match to Dynamips' buffer size
- buf += chunk.decode("utf-8")
+ chunk = yield from self._reader.read(1024) # match to Dynamips' buffer size
+ buf += chunk.decode()
except OSError as e:
raise DynamipsError("Communication timed out with {host}:{port} :{error}, Dynamips process running: {run}"
.format(host=self._host, port=self._port, error=e, run=self.is_running()))
diff --git a/gns3server/old_modules/dynamips/hypervisor.py b/gns3server/modules/dynamips/hypervisor.py
similarity index 57%
rename from gns3server/old_modules/dynamips/hypervisor.py
rename to gns3server/modules/dynamips/hypervisor.py
index ffce2935..87e05f75 100644
--- a/gns3server/old_modules/dynamips/hypervisor.py
+++ b/gns3server/modules/dynamips/hypervisor.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright (C) 2013 GNS3 Technologies Inc.
+# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -20,9 +20,9 @@ Represents a Dynamips hypervisor and starts/stops the associated Dynamips proces
"""
import os
-import time
import subprocess
import tempfile
+import asyncio
from .dynamips_hypervisor import DynamipsHypervisor
from .dynamips_error import DynamipsError
@@ -32,7 +32,6 @@ log = logging.getLogger(__name__)
class Hypervisor(DynamipsHypervisor):
-
"""
Hypervisor.
@@ -58,11 +57,6 @@ class Hypervisor(DynamipsHypervisor):
self._stdout_file = ""
self._started = False
- # settings used the load-balance hypervisors
- # (for the hypervisor manager)
- self._memory_load = 0
- self._ios_image_ref = ""
-
@property
def id(self):
"""
@@ -103,99 +97,7 @@ class Hypervisor(DynamipsHypervisor):
self._path = path
- @property
- def port(self):
- """
- Returns the port used to start the Dynamips hypervisor.
-
- :returns: port number (integer)
- """
-
- return self._port
-
- @port.setter
- def port(self, port):
- """
- Sets the port used to start the Dynamips hypervisor.
-
- :param port: port number (integer)
- """
-
- self._port = port
-
- @property
- def host(self):
- """
- Returns the host (binding) used to start the Dynamips hypervisor.
-
- :returns: host/address (string)
- """
-
- return self._host
-
- @host.setter
- def host(self, host):
- """
- Sets the host (binding) used to start the Dynamips hypervisor.
-
- :param host: host/address (string)
- """
-
- self._host = host
-
- @property
- def image_ref(self):
- """
- Returns the reference IOS image name
- (used by the hypervisor manager for load-balancing purposes).
-
- :returns: image reference name
- """
-
- return self._ios_image_ref
-
- @image_ref.setter
- def image_ref(self, ios_image_name):
- """
- Sets the reference IOS image name
- (used by the hypervisor manager for load-balancing purposes).
-
- :param ios_image_name: image reference name
- """
-
- self._ios_image_ref = ios_image_name
-
- def increase_memory_load(self, memory):
- """
- Increases the memory load of this hypervisor.
- (used by the hypervisor manager for load-balancing purposes).
-
- :param memory: amount of RAM (integer)
- """
-
- self._memory_load += memory
-
- def decrease_memory_load(self, memory):
- """
- Decreases the memory load of this hypervisor.
- (used by the hypervisor manager for load-balancing purposes).
-
- :param memory: amount of RAM (integer)
- """
-
- self._memory_load -= memory
-
- @property
- def memory_load(self):
- """
- Returns the memory load of this hypervisor.
- (used by the hypervisor manager for load-balancing purposes).
-
- :returns: amount of RAM (integer)
- """
-
- return self._memory_load
-
+ @asyncio.coroutine
def start(self):
"""
Starts the Dynamips hypervisor process.
@@ -203,37 +105,38 @@ class Hypervisor(DynamipsHypervisor):
self._command = self._build_command()
try:
- log.info("starting Dynamips: {}".format(self._command))
+ log.info("Starting Dynamips: {}".format(self._command))
+
with tempfile.NamedTemporaryFile(delete=False) as fd:
self._stdout_file = fd.name
log.info("Dynamips process logging to {}".format(fd.name))
- self._process = subprocess.Popen(self._command,
- stdout=fd,
- stderr=subprocess.STDOUT,
- cwd=self._working_dir)
- log.info("Dynamips started PID={}".format(self._process.pid))
+ self._process = yield from asyncio.create_subprocess_exec(*self._command,
+ stdout=fd,
+ stderr=subprocess.STDOUT,
+ cwd=self._working_dir)
+ log.info("Dynamips process started PID={}".format(self._process.pid))
self._started = True
except (OSError, subprocess.SubprocessError) as e:
- log.error("could not start Dynamips: {}".format(e))
- raise DynamipsError("could not start Dynamips: {}".format(e))
+ log.error("Could not start Dynamips: {}".format(e))
+ raise DynamipsError("Could not start Dynamips: {}".format(e))
+ @asyncio.coroutine
def stop(self):
"""
Stops the Dynamips hypervisor process.
"""
if self.is_running():
+ log.info("Stopping Dynamips process PID={}".format(self._process.pid))
DynamipsHypervisor.stop(self)
- log.info("stopping Dynamips PID={}".format(self._process.pid))
+ # give some time for the hypervisor to properly stop.
+ # time to delete UNIX NIOs for instance.
+ yield from asyncio.sleep(0.01)
try:
- # give some time for the hypervisor to properly stop.
- # time to delete UNIX NIOs for instance.
- time.sleep(0.01)
- self._process.terminate()
- self._process.wait(1)
- except subprocess.TimeoutExpired:
+ yield from asyncio.wait_for(self._process.wait(), timeout=3)
+ except asyncio.TimeoutError:
self._process.kill()
- if self._process.poll() is None:
+ if self._process.returncode is None:
log.warn("Dynamips process {} is still running".format(self._process.pid))
if self._stdout_file and os.access(self._stdout_file, os.W_OK):
@@ -265,7 +168,7 @@ class Hypervisor(DynamipsHypervisor):
:returns: True or False
"""
- if self._process and self._process.poll() is None:
+ if self._process and self._process.returncode is None:
return True
return False
diff --git a/gns3server/old_modules/dynamips/backends/__init__.py b/gns3server/modules/dynamips/nios/__init__.py
similarity index 100%
rename from gns3server/old_modules/dynamips/backends/__init__.py
rename to gns3server/modules/dynamips/nios/__init__.py
diff --git a/gns3server/old_modules/dynamips/nios/nio.py b/gns3server/modules/dynamips/nios/nio.py
similarity index 79%
rename from gns3server/old_modules/dynamips/nios/nio.py
rename to gns3server/modules/dynamips/nios/nio.py
index 3b66d54f..256ddc1b 100644
--- a/gns3server/old_modules/dynamips/nios/nio.py
+++ b/gns3server/modules/dynamips/nios/nio.py
@@ -20,23 +20,24 @@ Base interface for Dynamips Network Input/Output (NIO) module ("nio").
http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L451
"""
+import asyncio
from ..dynamips_error import DynamipsError
import logging
log = logging.getLogger(__name__)
-class NIO(object):
-
+class NIO:
"""
Base NIO class
:param hypervisor: Dynamips hypervisor instance
"""
- def __init__(self, hypervisor):
+ def __init__(self, name, hypervisor):
self._hypervisor = hypervisor
+ self._name = None
self._bandwidth = None # no bandwidth constraint by default
self._input_filter = None # no input filter applied by default
self._output_filter = None # no output filter applied by default
@@ -44,6 +45,7 @@ class NIO(object):
self._output_filter_options = None # no output filter options by default
self._dynamips_direction = {"in": 0, "out": 1, "both": 2}
+ @asyncio.coroutine
def list(self):
"""
Returns all NIOs.
@@ -51,18 +53,21 @@ class NIO(object):
:returns: NIO list
"""
- return self._hypervisor.send("nio list")
+ nio_list = yield from self._hypervisor.send("nio list")
+ return nio_list
+ @asyncio.coroutine
def delete(self):
"""
Deletes this NIO.
"""
if self._input_filter or self._output_filter:
- self.unbind_filter("both")
- self._hypervisor.send("nio delete {}".format(self._name))
+ yield from self.unbind_filter("both")
+ yield from self._hypervisor.send("nio delete {}".format(self._name))
log.info("NIO {name} has been deleted".format(name=self._name))
+ @asyncio.coroutine
def rename(self, new_name):
"""
Renames this NIO
@@ -70,13 +75,12 @@ class NIO(object):
:param new_name: new NIO name
"""
- self._hypervisor.send("nio rename {name} {new_name}".format(name=self._name,
- new_name=new_name))
+ yield from self._hypervisor.send("nio rename {name} {new_name}".format(name=self._name, new_name=new_name))
- log.info("NIO {name} renamed to {new_name}".format(name=self._name,
- new_name=new_name))
+ log.info("NIO {name} renamed to {new_name}".format(name=self._name, new_name=new_name))
self._name = new_name
+ @asyncio.coroutine
def debug(self, debug):
"""
Enables/Disables debugging for this NIO.
@@ -84,9 +88,9 @@ class NIO(object):
:param debug: debug value (0 = disable, enable = 1)
"""
- self._hypervisor.send("nio set_debug {name} {debug}".format(name=self._name,
- debug=debug))
+ yield from self._hypervisor.send("nio set_debug {name} {debug}".format(name=self._name, debug=debug))
+ @asyncio.coroutine
def bind_filter(self, direction, filter_name):
"""
Adds a packet filter to this NIO.
@@ -101,9 +105,9 @@ class NIO(object):
raise DynamipsError("Unknown direction {} to bind filter {}:".format(direction, filter_name))
dynamips_direction = self._dynamips_direction[direction]
- self._hypervisor.send("nio bind_filter {name} {direction} {filter}".format(name=self._name,
- direction=dynamips_direction,
- filter=filter_name))
+ yield from self._hypervisor.send("nio bind_filter {name} {direction} {filter}".format(name=self._name,
+ direction=dynamips_direction,
+ filter=filter_name))
if direction == "in":
self._input_filter = filter_name
@@ -113,6 +117,7 @@ class NIO(object):
self._input_filter = filter_name
self._output_filter = filter_name
+ @asyncio.coroutine
def unbind_filter(self, direction):
"""
Removes packet filter for this NIO.
@@ -124,8 +129,8 @@ class NIO(object):
raise DynamipsError("Unknown direction {} to unbind filter:".format(direction))
dynamips_direction = self._dynamips_direction[direction]
- self._hypervisor.send("nio unbind_filter {name} {direction}".format(name=self._name,
- direction=dynamips_direction))
+ yield from self._hypervisor.send("nio unbind_filter {name} {direction}".format(name=self._name,
+ direction=dynamips_direction))
if direction == "in":
self._input_filter = None
@@ -135,6 +140,7 @@ class NIO(object):
self._input_filter = None
self._output_filter = None
+ @asyncio.coroutine
def setup_filter(self, direction, options):
"""
Setups a packet filter bound with this NIO.
@@ -157,9 +163,9 @@ class NIO(object):
raise DynamipsError("Unknown direction {} to setup filter:".format(direction))
dynamips_direction = self._dynamips_direction[direction]
- self._hypervisor.send("nio setup_filter {name} {direction} {options}".format(name=self._name,
- direction=dynamips_direction,
- options=options))
+ yield from self._hypervisor.send("nio setup_filter {name} {direction} {options}".format(name=self._name,
+ direction=dynamips_direction,
+ options=options))
if direction == "in":
self._input_filter_options = options
@@ -189,6 +195,7 @@ class NIO(object):
return self._output_filter, self._output_filter_options
+ @asyncio.coroutine
def get_stats(self):
"""
Gets statistics for this NIO.
@@ -196,25 +203,16 @@ class NIO(object):
:returns: NIO statistics (string with packets in, packets out, bytes in, bytes out)
"""
- return self._hypervisor.send("nio get_stats {}".format(self._name))[0]
+ stats = yield from self._hypervisor.send("nio get_stats {}".format(self._name))
+ return stats[0]
+ @asyncio.coroutine
def reset_stats(self):
"""
Resets statistics for this NIO.
"""
- self._hypervisor.send("nio reset_stats {}".format(self._name))
-
- def set_bandwidth(self, bandwidth):
- """
- Sets bandwidth constraint.
-
- :param bandwidth: bandwidth integer value (in Kb/s)
- """
-
- self._hypervisor.send("nio set_bandwidth {name} {bandwidth}".format(name=self._name,
- bandwidth=bandwidth))
- self._bandwidth = bandwidth
+ yield from self._hypervisor.send("nio reset_stats {}".format(self._name))
@property
def bandwidth(self):
@@ -226,6 +224,17 @@ class NIO(object):
return self._bandwidth
+ @asyncio.coroutine
+ def set_bandwidth(self, bandwidth):
+ """
+ Sets bandwidth constraint.
+
+ :param bandwidth: bandwidth integer value (in Kb/s)
+ """
+
+ yield from self._hypervisor.send("nio set_bandwidth {name} {bandwidth}".format(name=self._name, bandwidth=bandwidth))
+ self._bandwidth = bandwidth
+
def __str__(self):
"""
NIO string representation.
diff --git a/gns3server/old_modules/dynamips/nios/nio_fifo.py b/gns3server/modules/dynamips/nios/nio_fifo.py
similarity index 85%
rename from gns3server/old_modules/dynamips/nios/nio_fifo.py
rename to gns3server/modules/dynamips/nios/nio_fifo.py
index c85b679d..768d87af 100644
--- a/gns3server/old_modules/dynamips/nios/nio_fifo.py
+++ b/gns3server/modules/dynamips/nios/nio_fifo.py
@@ -19,6 +19,7 @@
Interface for FIFO NIOs.
"""
+import asyncio
from .nio import NIO
import logging
@@ -26,7 +27,6 @@ log = logging.getLogger(__name__)
class NIO_FIFO(NIO):
-
"""
Dynamips FIFO NIO.
@@ -44,10 +44,6 @@ class NIO_FIFO(NIO):
NIO_FIFO._instance_count += 1
self._name = 'nio_fifo' + str(self._id)
- self._hypervisor.send("nio create_fifo {}".format(self._name))
-
- log.info("NIO FIFO {name} created.".format(name=self._name))
-
@classmethod
def reset(cls):
"""
@@ -56,6 +52,13 @@ class NIO_FIFO(NIO):
cls._instance_count = 0
+ @asyncio.coroutine
+ def create(self):
+
+ yield from self._hypervisor.send("nio create_fifo {}".format(self._name))
+ log.info("NIO FIFO {name} created.".format(name=self._name))
+
+ @asyncio.coroutine
def crossconnect(self, nio):
"""
Establishes a cross-connect between this FIFO NIO and another one.
@@ -63,7 +66,7 @@ class NIO_FIFO(NIO):
:param nio: FIFO NIO instance
"""
- self._hypervisor.send("nio crossconnect_fifo {name} {nio}".format(name=self._name,
- nio=nio))
+ yield from self._hypervisor.send("nio crossconnect_fifo {name} {nio}".format(name=self._name,
+ nio=nio))
log.info("NIO FIFO {name} crossconnected with {nio_name}.".format(name=self._name, nio_name=nio.name))
diff --git a/gns3server/old_modules/dynamips/nios/nio_generic_ethernet.py b/gns3server/modules/dynamips/nios/nio_generic_ethernet.py
similarity index 87%
rename from gns3server/old_modules/dynamips/nios/nio_generic_ethernet.py
rename to gns3server/modules/dynamips/nios/nio_generic_ethernet.py
index 2a8b1443..4428e2bf 100644
--- a/gns3server/old_modules/dynamips/nios/nio_generic_ethernet.py
+++ b/gns3server/modules/dynamips/nios/nio_generic_ethernet.py
@@ -19,6 +19,7 @@
Interface for generic Ethernet NIOs (PCAP library).
"""
+import asyncio
from .nio import NIO
import logging
@@ -26,7 +27,6 @@ log = logging.getLogger(__name__)
class NIO_GenericEthernet(NIO):
-
"""
Dynamips generic Ethernet NIO.
@@ -46,11 +46,7 @@ class NIO_GenericEthernet(NIO):
self._name = 'nio_gen_eth' + str(self._id)
self._ethernet_device = ethernet_device
- self._hypervisor.send("nio create_gen_eth {name} {eth_device}".format(name=self._name,
- eth_device=ethernet_device))
- log.info("NIO Generic Ethernet {name} created with device {device}".format(name=self._name,
- device=ethernet_device))
@classmethod
def reset(cls):
@@ -60,6 +56,15 @@ class NIO_GenericEthernet(NIO):
cls._instance_count = 0
+ @asyncio.coroutine
+ def create(self):
+
+ yield from self._hypervisor.send("nio create_gen_eth {name} {eth_device}".format(name=self._name,
+ eth_device=self._ethernet_device))
+
+ log.info("NIO Generic Ethernet {name} created with device {device}".format(name=self._name,
+ device=self._ethernet_device))
+
@property
def ethernet_device(self):
"""
diff --git a/gns3server/old_modules/dynamips/nios/nio_linux_ethernet.py b/gns3server/modules/dynamips/nios/nio_linux_ethernet.py
similarity index 87%
rename from gns3server/old_modules/dynamips/nios/nio_linux_ethernet.py
rename to gns3server/modules/dynamips/nios/nio_linux_ethernet.py
index 25988aa8..28bfbe89 100644
--- a/gns3server/old_modules/dynamips/nios/nio_linux_ethernet.py
+++ b/gns3server/modules/dynamips/nios/nio_linux_ethernet.py
@@ -19,6 +19,7 @@
Interface for Linux Ethernet NIOs (Linux only).
"""
+import asyncio
from .nio import NIO
import logging
@@ -26,7 +27,6 @@ log = logging.getLogger(__name__)
class NIO_LinuxEthernet(NIO):
-
"""
Dynamips Linux Ethernet NIO.
@@ -46,12 +46,6 @@ class NIO_LinuxEthernet(NIO):
self._name = 'nio_linux_eth' + str(self._id)
self._ethernet_device = ethernet_device
- self._hypervisor.send("nio create_linux_eth {name} {eth_device}".format(name=self._name,
- eth_device=ethernet_device))
-
- log.info("NIO Linux Ethernet {name} created with device {device}".format(name=self._name,
- device=ethernet_device))
-
@classmethod
def reset(cls):
"""
@@ -60,6 +54,15 @@ class NIO_LinuxEthernet(NIO):
cls._instance_count = 0
+ @asyncio.coroutine
+ def create(self):
+
+ yield from self._hypervisor.send("nio create_linux_eth {name} {eth_device}".format(name=self._name,
+ eth_device=self._ethernet_device))
+
+ log.info("NIO Linux Ethernet {name} created with device {device}".format(name=self._name,
+ device=self._ethernet_device))
+
@property
def ethernet_device(self):
"""
diff --git a/gns3server/old_modules/dynamips/nios/nio_mcast.py b/gns3server/modules/dynamips/nios/nio_mcast.py
similarity index 83%
rename from gns3server/old_modules/dynamips/nios/nio_mcast.py
rename to gns3server/modules/dynamips/nios/nio_mcast.py
index bcd42670..fe32135b 100644
--- a/gns3server/old_modules/dynamips/nios/nio_mcast.py
+++ b/gns3server/modules/dynamips/nios/nio_mcast.py
@@ -19,6 +19,7 @@
Interface for multicast NIOs.
"""
+import asyncio
from .nio import NIO
import logging
@@ -26,7 +27,6 @@ log = logging.getLogger(__name__)
class NIO_Mcast(NIO):
-
"""
Dynamips Linux Ethernet NIO.
@@ -49,14 +49,6 @@ class NIO_Mcast(NIO):
self._port = port
self._ttl = 1 # default TTL
- self._hypervisor.send("nio create_mcast {name} {mgroup} {mport}".format(name=self._name,
- mgroup=group,
- mport=port))
-
- log.info("NIO Multicast {name} created with mgroup={group}, mport={port}".format(name=self._name,
- group=group,
- port=port))
-
@classmethod
def reset(cls):
"""
@@ -65,6 +57,17 @@ class NIO_Mcast(NIO):
cls._instance_count = 0
+ @asyncio.coroutine
+ def create(self):
+
+ yield from self._hypervisor.send("nio create_mcast {name} {mgroup} {mport}".format(name=self._name,
+ mgroup=self._group,
+ mport=self._port))
+
+ log.info("NIO Multicast {name} created with mgroup={group}, mport={port}".format(name=self._name,
+ group=self._group,
+ port=self._port))
+
@property
def group(self):
"""
@@ -95,14 +98,13 @@ class NIO_Mcast(NIO):
return self._ttl
- @ttl.setter
- def ttl(self, ttl):
+ def set_ttl(self, ttl):
"""
Sets the TTL for the multicast address
:param ttl: TTL value
"""
- self._hypervisor.send("nio set_mcast_ttl {name} {ttl}".format(name=self._name,
- ttl=ttl))
+ yield from self._hypervisor.send("nio set_mcast_ttl {name} {ttl}".format(name=self._name,
+ ttl=ttl))
self._ttl = ttl
diff --git a/gns3server/old_modules/dynamips/nios/nio_null.py b/gns3server/modules/dynamips/nios/nio_null.py
similarity index 90%
rename from gns3server/old_modules/dynamips/nios/nio_null.py
rename to gns3server/modules/dynamips/nios/nio_null.py
index 1cde2a52..b8113e59 100644
--- a/gns3server/old_modules/dynamips/nios/nio_null.py
+++ b/gns3server/modules/dynamips/nios/nio_null.py
@@ -19,6 +19,7 @@
Interface for dummy NIOs (mostly for tests).
"""
+import asyncio
from .nio import NIO
import logging
@@ -26,7 +27,6 @@ log = logging.getLogger(__name__)
class NIO_Null(NIO):
-
"""
Dynamips NULL NIO.
@@ -44,9 +44,6 @@ class NIO_Null(NIO):
NIO_Null._instance_count += 1
self._name = 'nio_null' + str(self._id)
- self._hypervisor.send("nio create_null {}".format(self._name))
- log.info("NIO NULL {name} created.".format(name=self._name))
-
@classmethod
def reset(cls):
"""
@@ -54,3 +51,9 @@ class NIO_Null(NIO):
"""
cls._instance_count = 0
+
+ @asyncio.coroutine
+ def create(self):
+
+ yield from self._hypervisor.send("nio create_null {}".format(self._name))
+ log.info("NIO NULL {name} created.".format(name=self._name))
diff --git a/gns3server/old_modules/dynamips/nios/nio_tap.py b/gns3server/modules/dynamips/nios/nio_tap.py
similarity index 85%
rename from gns3server/old_modules/dynamips/nios/nio_tap.py
rename to gns3server/modules/dynamips/nios/nio_tap.py
index d24e9109..efe47a9e 100644
--- a/gns3server/old_modules/dynamips/nios/nio_tap.py
+++ b/gns3server/modules/dynamips/nios/nio_tap.py
@@ -19,6 +19,7 @@
Interface for TAP NIOs (UNIX based OSes only).
"""
+import asyncio
from .nio import NIO
import logging
@@ -26,7 +27,6 @@ log = logging.getLogger(__name__)
class NIO_TAP(NIO):
-
"""
Dynamips TAP NIO.
@@ -46,12 +46,6 @@ class NIO_TAP(NIO):
self._name = 'nio_tap' + str(self._id)
self._tap_device = tap_device
- self._hypervisor.send("nio create_tap {name} {tap}".format(name=self._name,
- tap=tap_device))
-
- log.info("NIO TAP {name} created with device {device}".format(name=self._name,
- device=tap_device))
-
@classmethod
def reset(cls):
"""
@@ -60,6 +54,12 @@ class NIO_TAP(NIO):
cls._instance_count = 0
+ @asyncio.coroutine
+ def create(self):
+
+ yield from self._hypervisor.send("nio create_tap {name} {tap}".format(name=self._name, tap=self._tap_device))
+ log.info("NIO TAP {name} created with device {device}".format(name=self._name, device=self._tap_device))
+
@property
def tap_device(self):
"""
diff --git a/gns3server/old_modules/dynamips/nios/nio_udp.py b/gns3server/modules/dynamips/nios/nio_udp.py
similarity index 83%
rename from gns3server/old_modules/dynamips/nios/nio_udp.py
rename to gns3server/modules/dynamips/nios/nio_udp.py
index d9e2d294..0bae8bbf 100644
--- a/gns3server/old_modules/dynamips/nios/nio_udp.py
+++ b/gns3server/modules/dynamips/nios/nio_udp.py
@@ -19,6 +19,7 @@
Interface for UDP NIOs.
"""
+import asyncio
from .nio import NIO
import logging
@@ -26,7 +27,6 @@ log = logging.getLogger(__name__)
class NIO_UDP(NIO):
-
"""
Dynamips UDP NIO.
@@ -50,16 +50,6 @@ class NIO_UDP(NIO):
self._rhost = rhost
self._rport = rport
- self._hypervisor.send("nio create_udp {name} {lport} {rhost} {rport}".format(name=self._name,
- lport=lport,
- rhost=rhost,
- rport=rport))
-
- log.info("NIO UDP {name} created with lport={lport}, rhost={rhost}, rport={rport}".format(name=self._name,
- lport=lport,
- rhost=rhost,
- rport=rport))
-
@classmethod
def reset(cls):
"""
@@ -68,6 +58,19 @@ class NIO_UDP(NIO):
cls._instance_count = 0
+ @asyncio.coroutine
+ def create(self):
+
+ yield from self._hypervisor.send("nio create_udp {name} {lport} {rhost} {rport}".format(name=self._name,
+ lport=self._lport,
+ rhost=self._rhost,
+ rport=self._rport))
+
+ log.info("NIO UDP {name} created with lport={lport}, rhost={rhost}, rport={rport}".format(name=self._name,
+ lport=self._lport,
+ rhost=self._rhost,
+ rport=self._rport))
+
@property
def lport(self):
"""
diff --git a/gns3server/old_modules/dynamips/nios/nio_udp_auto.py b/gns3server/modules/dynamips/nios/nio_udp_auto.py
similarity index 83%
rename from gns3server/old_modules/dynamips/nios/nio_udp_auto.py
rename to gns3server/modules/dynamips/nios/nio_udp_auto.py
index 03d290d6..eb42e580 100644
--- a/gns3server/old_modules/dynamips/nios/nio_udp_auto.py
+++ b/gns3server/modules/dynamips/nios/nio_udp_auto.py
@@ -19,6 +19,7 @@
Interface for automatic UDP NIOs.
"""
+import asyncio
from .nio import NIO
import logging
@@ -26,7 +27,6 @@ log = logging.getLogger(__name__)
class NIO_UDP_auto(NIO):
-
"""
Dynamips auto UDP NIO.
@@ -48,15 +48,7 @@ class NIO_UDP_auto(NIO):
self._name = 'nio_udp_auto' + str(self._id)
self._laddr = laddr
- self._lport = int(self._hypervisor.send("nio create_udp_auto {name} {laddr} {lport_start} {lport_end}".format(name=self._name,
- laddr=laddr,
- lport_start=lport_start,
- lport_end=lport_end))[0])
-
- log.info("NIO UDP AUTO {name} created with laddr={laddr}, lport_start={start}, lport_end={end}".format(name=self._name,
- laddr=laddr,
- start=lport_start,
- end=lport_end))
+ self._lport = None
self._raddr = None
self._rport = None
@@ -68,6 +60,20 @@ class NIO_UDP_auto(NIO):
cls._instance_count = 0
+ @asyncio.coroutine
+ def create(self):
+
+ port = yield from self._hypervisor.send("nio create_udp_auto {name} {laddr} {lport_start} {lport_end}".format(name=self._name,
+ laddr=self._laddr,
+ lport_start=self._lport_start,
+ lport_end=self._lport_end))
+ self._lport = int(port[0])
+
+ log.info("NIO UDP AUTO {name} created with laddr={laddr}, lport_start={start}, lport_end={end}".format(name=self._name,
+ laddr=self._laddr,
+ start=self._lport_start,
+ end=self._lport_end))
+
@property
def laddr(self):
"""
@@ -108,6 +114,7 @@ class NIO_UDP_auto(NIO):
return self._rport
+ @asyncio.coroutine
def connect(self, raddr, rport):
"""
Connects this NIO to a remote socket
@@ -116,9 +123,9 @@ class NIO_UDP_auto(NIO):
:param rport: remote port number
"""
- self._hypervisor.send("nio connect_udp_auto {name} {raddr} {rport}".format(name=self._name,
- raddr=raddr,
- rport=rport))
+ yield from self._hypervisor.send("nio connect_udp_auto {name} {raddr} {rport}".format(name=self._name,
+ raddr=raddr,
+ rport=rport))
self._raddr = raddr
self._rport = rport
diff --git a/gns3server/old_modules/dynamips/nios/nio_unix.py b/gns3server/modules/dynamips/nios/nio_unix.py
similarity index 85%
rename from gns3server/old_modules/dynamips/nios/nio_unix.py
rename to gns3server/modules/dynamips/nios/nio_unix.py
index af100d2e..af913f88 100644
--- a/gns3server/old_modules/dynamips/nios/nio_unix.py
+++ b/gns3server/modules/dynamips/nios/nio_unix.py
@@ -19,6 +19,7 @@
Interface for UNIX NIOs (Unix based OSes only).
"""
+import asyncio
from .nio import NIO
import logging
@@ -26,7 +27,6 @@ log = logging.getLogger(__name__)
class NIO_UNIX(NIO):
-
"""
Dynamips UNIX NIO.
@@ -48,14 +48,6 @@ class NIO_UNIX(NIO):
self._local_file = local_file
self._remote_file = remote_file
- self._hypervisor.send("nio create_unix {name} {local} {remote}".format(name=self._name,
- local=local_file,
- remote=remote_file))
-
- log.info("NIO UNIX {name} created with local file {local} and remote file {remote}".format(name=self._name,
- local=local_file,
- remote=remote_file))
-
@classmethod
def reset(cls):
"""
@@ -64,6 +56,17 @@ class NIO_UNIX(NIO):
cls._instance_count = 0
+ @asyncio.coroutine
+ def create(self):
+
+ yield from self._hypervisor.send("nio create_unix {name} {local} {remote}".format(name=self._name,
+ local=self._local_file,
+ remote=self._remote_file))
+
+ log.info("NIO UNIX {name} created with local file {local} and remote file {remote}".format(name=self._name,
+ local=self._local_file,
+ remote=self._remote_file))
+
@property
def local_file(self):
"""
diff --git a/gns3server/old_modules/dynamips/nios/nio_vde.py b/gns3server/modules/dynamips/nios/nio_vde.py
similarity index 99%
rename from gns3server/old_modules/dynamips/nios/nio_vde.py
rename to gns3server/modules/dynamips/nios/nio_vde.py
index 7157834f..79af96d7 100644
--- a/gns3server/old_modules/dynamips/nios/nio_vde.py
+++ b/gns3server/modules/dynamips/nios/nio_vde.py
@@ -26,7 +26,6 @@ log = logging.getLogger(__name__)
class NIO_VDE(NIO):
-
"""
Dynamips VDE NIO.
diff --git a/gns3server/old_modules/dynamips/nios/__init__.py b/gns3server/modules/dynamips/nodes/__init__.py
similarity index 100%
rename from gns3server/old_modules/dynamips/nios/__init__.py
rename to gns3server/modules/dynamips/nodes/__init__.py
diff --git a/gns3server/old_modules/dynamips/nodes/c1700.py b/gns3server/modules/dynamips/nodes/c1700.py
similarity index 99%
rename from gns3server/old_modules/dynamips/nodes/c1700.py
rename to gns3server/modules/dynamips/nodes/c1700.py
index 249ab508..906abe3e 100644
--- a/gns3server/old_modules/dynamips/nodes/c1700.py
+++ b/gns3server/modules/dynamips/nodes/c1700.py
@@ -29,7 +29,6 @@ log = logging.getLogger(__name__)
class C1700(Router):
-
"""
Dynamips c1700 router.
diff --git a/gns3server/old_modules/dynamips/nodes/c2600.py b/gns3server/modules/dynamips/nodes/c2600.py
similarity index 99%
rename from gns3server/old_modules/dynamips/nodes/c2600.py
rename to gns3server/modules/dynamips/nodes/c2600.py
index 083bbce6..b5e46e89 100644
--- a/gns3server/old_modules/dynamips/nodes/c2600.py
+++ b/gns3server/modules/dynamips/nodes/c2600.py
@@ -31,7 +31,6 @@ log = logging.getLogger(__name__)
class C2600(Router):
-
"""
Dynamips c2600 router.
diff --git a/gns3server/old_modules/dynamips/nodes/c2691.py b/gns3server/modules/dynamips/nodes/c2691.py
similarity index 99%
rename from gns3server/old_modules/dynamips/nodes/c2691.py
rename to gns3server/modules/dynamips/nodes/c2691.py
index fca62624..0dc0ef28 100644
--- a/gns3server/old_modules/dynamips/nodes/c2691.py
+++ b/gns3server/modules/dynamips/nodes/c2691.py
@@ -28,7 +28,6 @@ log = logging.getLogger(__name__)
class C2691(Router):
-
"""
Dynamips c2691 router.
diff --git a/gns3server/old_modules/dynamips/nodes/c3600.py b/gns3server/modules/dynamips/nodes/c3600.py
similarity index 99%
rename from gns3server/old_modules/dynamips/nodes/c3600.py
rename to gns3server/modules/dynamips/nodes/c3600.py
index 8b9e8966..32e2bbe7 100644
--- a/gns3server/old_modules/dynamips/nodes/c3600.py
+++ b/gns3server/modules/dynamips/nodes/c3600.py
@@ -28,7 +28,6 @@ log = logging.getLogger(__name__)
class C3600(Router):
-
"""
Dynamips c3600 router.
diff --git a/gns3server/old_modules/dynamips/nodes/c3725.py b/gns3server/modules/dynamips/nodes/c3725.py
similarity index 99%
rename from gns3server/old_modules/dynamips/nodes/c3725.py
rename to gns3server/modules/dynamips/nodes/c3725.py
index 76ba4d9f..9317a393 100644
--- a/gns3server/old_modules/dynamips/nodes/c3725.py
+++ b/gns3server/modules/dynamips/nodes/c3725.py
@@ -28,7 +28,6 @@ log = logging.getLogger(__name__)
class C3725(Router):
-
"""
Dynamips c3725 router.
diff --git a/gns3server/old_modules/dynamips/nodes/c3745.py b/gns3server/modules/dynamips/nodes/c3745.py
similarity index 99%
rename from gns3server/old_modules/dynamips/nodes/c3745.py
rename to gns3server/modules/dynamips/nodes/c3745.py
index 0903b789..8002909a 100644
--- a/gns3server/old_modules/dynamips/nodes/c3745.py
+++ b/gns3server/modules/dynamips/nodes/c3745.py
@@ -28,7 +28,6 @@ log = logging.getLogger(__name__)
class C3745(Router):
-
"""
Dynamips c3745 router.
diff --git a/gns3server/old_modules/dynamips/nodes/c7200.py b/gns3server/modules/dynamips/nodes/c7200.py
similarity index 97%
rename from gns3server/old_modules/dynamips/nodes/c7200.py
rename to gns3server/modules/dynamips/nodes/c7200.py
index 8ba10f8e..21ab4aa6 100644
--- a/gns3server/old_modules/dynamips/nodes/c7200.py
+++ b/gns3server/modules/dynamips/nodes/c7200.py
@@ -30,7 +30,6 @@ log = logging.getLogger(__name__)
class C7200(Router):
-
"""
Dynamips c7200 router (model is 7206).
@@ -228,9 +227,9 @@ class C7200(Router):
powered_on=power_supply))
log.info("router {name} [id={id}]: power supply {power_supply_id} state updated to {powered_on}".format(name=self._name,
- id=self._id,
- power_supply_id=power_supply_id,
- powered_on=power_supply))
+ id=self._id,
+ power_supply_id=power_supply_id,
+ powered_on=power_supply))
power_supply_id += 1
self._power_supplies = power_supplies
diff --git a/gns3server/modules/dynamips/nodes/router.py b/gns3server/modules/dynamips/nodes/router.py
new file mode 100644
index 00000000..722100f4
--- /dev/null
+++ b/gns3server/modules/dynamips/nodes/router.py
@@ -0,0 +1,1514 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2015 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""
+Interface for Dynamips virtual Machine module ("vm")
+http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L77
+"""
+
+from ...base_vm import BaseVM
+from ..dynamips_error import DynamipsError
+
+import asyncio
+import time
+import sys
+import os
+import base64
+
+import logging
+log = logging.getLogger(__name__)
+
+
+class Router(BaseVM):
+
+ """
+ Dynamips router implementation.
+ """
+
+ _status = {0: "inactive",
+ 1: "shutting down",
+ 2: "running",
+ 3: "suspended"}
+
+ def __init__(self, name, vm_id, project, manager, platform="c7200", ghost_flag=False):
+
+ super().__init__(name, vm_id, project, manager)
+
+ self._hypervisor = None
+ self._closed = False
+ self._name = name
+ self._platform = platform
+ self._image = ""
+ self._startup_config = ""
+ self._private_config = ""
+ self._ram = 128 # Megabytes
+ self._nvram = 128 # Kilobytes
+ self._mmap = True
+ self._sparsemem = True
+ self._clock_divisor = 8
+ self._idlepc = ""
+ self._idlemax = 500
+ self._idlesleep = 30
+ self._ghost_file = ""
+ self._ghost_status = 0
+ if sys.platform.startswith("win"):
+ self._exec_area = 16 # 16 MB by default on Windows (Cygwin)
+ else:
+ self._exec_area = 64 # 64 MB on other systems
+ self._disk0 = 0 # Megabytes
+ self._disk1 = 0 # Megabytes
+ self._confreg = "0x2102"
+ self._console = None
+ self._aux = None
+ self._mac_addr = None
+ self._system_id = "FTX0945W0MY" # processor board ID in IOS
+ self._slots = []
+ self._ghost_flag = ghost_flag
+
+ if not ghost_flag:
+
+ if self._console is not None:
+ self._console = self._manager.port_manager.reserve_console_port(self._console)
+ else:
+ self._console = self._manager.port_manager.get_free_console_port()
+
+ if self._aux is not None:
+ self._aux = self._manager.port_manager.reserve_console_port(self._aux)
+ else:
+ self._aux = self._manager.port_manager.get_free_console_port()
+
+ def __json__(self):
+
+ router_info = {"name": self.name,
+ "vm_id": self.id,
+ "project_id": self.project.id,
+ "platform": self._platform,
+ "image": self._image,
+ "startup_config": self._startup_config,
+ "private_config": self._private_config,
+ "ram": self._ram,
+ "nvram": self._nvram,
+ "mmap": self._mmap,
+ "sparsemem": self._sparsemem,
+ "clock_divisor": self._clock_divisor,
+ "idlepc": self._idlepc,
+ "idlemax": self._idlemax,
+ "idlesleep": self._idlesleep,
+ "exec_area": self._exec_area,
+ "disk0": self._disk0,
+ "disk1": self._disk1,
+ "confreg": self._confreg,
+ "console": self._console,
+ "aux": self._aux,
+ "mac_addr": self._mac_addr,
+ "system_id": self._system_id}
+
+ # FIXME: add default slots/wics
+ #slot_id = 0
+ #for slot in self._slots:
+ # if slot:
+ # slot = str(slot)
+ # router_defaults["slot" + str(slot_id)] = slot
+ # slot_id += 1
+
+ #if self._slots[0] and self._slots[0].wics:
+ # for wic_slot_id in range(0, len(self._slots[0].wics)):
+ # router_defaults["wic" + str(wic_slot_id)] = None
+
+ return router_info
+
+ @asyncio.coroutine
+ def create(self):
+
+ self._hypervisor = yield from self.manager.start_new_hypervisor()
+
+ yield from self._hypervisor.send("vm create '{name}' {id} {platform}".format(name=self._name,
+ id=self._id,
+ platform=self._platform))
+
+ if not self._ghost_flag:
+
+ log.info("Router {platform} '{name}' [{id}] has been created".format(name=self._name,
+ platform=self._platform,
+ id=self._id))
+
+ yield from self._hypervisor.send("vm set_con_tcp_port '{name}' {console}".format(name=self._name, console=self._console))
+ yield from self._hypervisor.send("vm set_aux_tcp_port '{name}' {aux}".format(name=self._name, aux=self._aux))
+
+ # get the default base MAC address
+ mac_addr = yield from self._hypervisor.send("{platform} get_mac_addr '{name}'".format(platform=self._platform,
+ name=self._name))
+ self._mac_addr = mac_addr[0]
+
+ self._hypervisor.devices.append(self)
+
+ @asyncio.coroutine
+ def get_status(self):
+ """
+ Returns the status of this router
+
+ :returns: inactive, shutting down, running or suspended.
+ """
+
+ status = yield from self._hypervisor.send("vm get_status '{name}'".format(name=self._name))
+ return self._status[int(status[0])]
+
+ @asyncio.coroutine
+ def start(self):
+ """
+ Starts this router.
+ At least the IOS image must be set before it can start.
+ """
+
+ status = yield from self.get_status()
+ if status == "suspended":
+ yield from self.resume()
+ elif status == "inactive":
+
+ if not os.path.isfile(self._image) or not os.path.exists(self._image):
+ if os.path.islink(self._image):
+ raise DynamipsError("IOS image '{}' linked to '{}' is not accessible".format(self._image, os.path.realpath(self._image)))
+ else:
+ raise DynamipsError("IOS image '{}' is not accessible".format(self._image))
+
+ try:
+ with open(self._image, "rb") as f:
+ # read the first 7 bytes of the file.
+ elf_header_start = f.read(7)
+ except OSError as e:
+ raise DynamipsError("Cannot read ELF header for IOS image {}: {}".format(self._image, e))
+
+ # IOS images must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
+ if elf_header_start != b'\x7fELF\x01\x02\x01':
+ raise DynamipsError("'{}' is not a valid IOS image".format(self._image))
+
+ yield from self._hypervisor.send("vm start '{}'".format(self._name))
+ log.info("router '{name}' [{id}] has been started".format(name=self._name, id=self._id))
+
+ @asyncio.coroutine
+ def stop(self):
+ """
+ Stops this router.
+ """
+
+ status = yield from self.get_status()
+ if status != "inactive":
+ yield from self._hypervisor.send("vm stop '{name}'".format(self._name))
+ log.info("Router '{name}' [{id}] has been stopped".format(name=self._name, id=self._id))
+
+ @asyncio.coroutine
+ def suspend(self):
+ """
+ Suspends this router.
+ """
+
+ status = yield from self.get_status()
+ if status == "running":
+ yield from self._hypervisor.send("vm suspend '{}'".format(self._name))
+ log.info("Router '{name}' [{id}] has been suspended".format(name=self._name, id=self._id))
+
+ @asyncio.coroutine
+ def resume(self):
+ """
+ Resumes this suspended router
+ """
+
+ yield from self._hypervisor.send("vm resume '{}'".format(self._name))
+ log.info("Router '{name}' [{id}] has been resumed".format(name=self._name, id=self._id))
+
+ @asyncio.coroutine
+ def is_running(self):
+ """
+ Checks if this router is running.
+
+ :returns: True if running, False otherwise
+ """
+
+ status = yield from self.get_status()
+ if status == "running":
+ return True
+ return False
+
+ @asyncio.coroutine
+ def close(self):
+
+ if self._closed:
+ # router is already closed
+ return
+
+ if self._hypervisor:
+ yield from self.stop()
+ yield from self.hypervisor.stop()
+
+ if self._console:
+ self._manager.port_manager.release_console_port(self._console)
+ self._console = None
+
+ if self._aux:
+ self._manager.port_manager.release_console_port(self._aux)
+ self._aux = None
+
+ self._closed = True
+
+ @asyncio.coroutine
+ def delete(self):
+ """
+ Deletes this router.
+ """
+
+ yield from self.close()
+ yield from self._hypervisor.send("vm delete '{}'".format(self._name))
+ self._hypervisor.devices.remove(self)
+ log.info("router '{name}' [{id}] has been deleted".format(name=self._name, id=self._id))
+
+ @property
+ def platform(self):
+ """
+ Returns the platform of this router.
+
+ :returns: platform name (string):
+ c7200, c3745, c3725, c3600, c2691, c2600 or c1700
+ """
+
+ return self._platform
+
+ @property
+ def hypervisor(self):
+ """
+ Returns the current hypervisor.
+
+ :returns: hypervisor instance
+ """
+
+ return self._hypervisor
+
+ @asyncio.coroutine
+ def list(self):
+ """
+ Returns all VM instances
+
+ :returns: list of all VM instances
+ """
+
+ vm_list = yield from self._hypervisor.send("vm list")
+ return vm_list
+
+ @asyncio.coroutine
+ def list_con_ports(self):
+ """
+ Returns all VM console TCP ports
+
+ :returns: list of port numbers
+ """
+
+ port_list = yield from self._hypervisor.send("vm list_con_ports")
+ return port_list
+
+ @asyncio.coroutine
+ def set_debug_level(self, level):
+ """
+ Sets the debug level for this router (default is 0).
+
+ :param level: level number
+ """
+
+ yield from self._hypervisor.send("vm set_debug_level '{name}' {level}".format(name=self._name, level=level))
+
+ @property
+ def image(self):
+ """
+ Returns this IOS image for this router.
+
+ :returns: path to IOS image file
+ """
+
+ return self._image
+
+ @asyncio.coroutine
+ def set_image(self, image):
+ """
+ Sets the IOS image for this router.
+ There is no default.
+
+ :param image: path to IOS image file
+ """
+
+ # encase image in quotes to protect spaces in the path
+ yield from self._hypervisor.send("vm set_ios {name} {image}".format(name=self._name, image='"' + image + '"'))
+
+ log.info("Router '{name}' [{id}]: has a new IOS image set: {image}".format(name=self._name,
+ id=self._id,
+ image='"' + image + '"'))
+
+ self._image = image
+
+ @property
+ def ram(self):
+ """
+ Returns the amount of RAM allocated to this router.
+
+ :returns: amount of RAM in Mbytes (integer)
+ """
+
+ return self._ram
+
+ @asyncio.coroutine
+ def set_ram(self, ram):
+ """
+ Sets amount of RAM allocated to this router
+
+ :param ram: amount of RAM in Mbytes (integer)
+ """
+
+ if self._ram == ram:
+ return
+
+ yield from self._hypervisor.send("vm set_ram '{name}' {ram}".format(name=self._name, ram=ram))
+ log.info("Router '{name}' [{id}]: RAM updated from {old_ram}MB to {new_ram}MB".format(name=self._name,
+ id=self._id,
+ old_ram=self._ram,
+ new_ram=ram))
+ self._ram = ram
+
+ @property
+ def nvram(self):
+ """
+ Returns the mount of NVRAM allocated to this router.
+
+ :returns: amount of NVRAM in Kbytes (integer)
+ """
+
+ return self._nvram
+
+ @asyncio.coroutine
+ def set_nvram(self, nvram):
+ """
+ Sets amount of NVRAM allocated to this router
+
+ :param nvram: amount of NVRAM in Kbytes (integer)
+ """
+
+ if self._nvram == nvram:
+ return
+
+ yield from self._hypervisor.send("vm set_nvram '{name}' {nvram}".format(name=self._name, nvram=nvram))
+ log.info("Router '{name}' [{id}]: NVRAM updated from {old_nvram}KB to {new_nvram}KB".format(name=self._name,
+ id=self._id,
+ old_nvram=self._nvram,
+ new_nvram=nvram))
+ self._nvram = nvram
+
+ @property
+ def mmap(self):
+ """
+ Returns True if a mapped file is used to simulate this router memory.
+
+ :returns: boolean either mmap is activated or not
+ """
+
+ return self._mmap
+
+ @asyncio.coroutine
+ def set_mmap(self, mmap):
+ """
+ Enable/Disable use of a mapped file to simulate router memory.
+ By default, a mapped file is used. This is a bit slower, but requires less memory.
+
+ :param mmap: activate/deactivate mmap (boolean)
+ """
+
+ if mmap:
+ flag = 1
+ else:
+ flag = 0
+
+ yield from self._hypervisor.send("vm set_ram_mmap '{name}' {mmap}".format(name=self._name, mmap=flag))
+
+ if mmap:
+ log.info("Router '{name}' [{id}]: mmap enabled".format(name=self._name, id=self._id))
+ else:
+ log.info("Router '{name}' [{id}]: mmap disabled".format(name=self._name, id=self._id))
+ self._mmap = mmap
+
+ @property
+ def sparsemem(self):
+ """
+ Returns True if sparse memory is used on this router.
+
+ :returns: boolean either mmap is activated or not
+ """
+
+ return self._sparsemem
+
+ @asyncio.coroutine
+ def set_sparsemem(self, sparsemem):
+ """
+ Enable/disable use of sparse memory
+
+ :param sparsemem: activate/deactivate sparsemem (boolean)
+ """
+
+ if sparsemem:
+ flag = 1
+ else:
+ flag = 0
+ yield from self._hypervisor.send("vm set_sparse_mem '{name}' {sparsemem}".format(name=self._name, sparsemem=flag))
+
+ if sparsemem:
+ log.info("Router '{name}' [{id}]: sparse memory enabled".format(name=self._name, id=self._id))
+ else:
+ log.info("Router '{name}' [{id}]: sparse memory disabled".format(name=self._name, id=self._id))
+ self._sparsemem = sparsemem
+
+ @property
+ def clock_divisor(self):
+ """
+ Returns the clock divisor value for this router.
+
+ :returns: clock divisor value (integer)
+ """
+
+ return self._clock_divisor
+
+ @asyncio.coroutine
+ def set_clock_divisor(self, clock_divisor):
+ """
+ Sets the clock divisor value. The higher is the value, the faster is the clock in the
+ virtual machine. The default is 4, but it is often required to adjust it.
+
+ :param clock_divisor: clock divisor value (integer)
+ """
+
+ yield from self._hypervisor.send("vm set_clock_divisor '{name}' {clock}".format(name=self._name, clock=clock_divisor))
+ log.info("Router '{name}' [{id}]: clock divisor updated from {old_clock} to {new_clock}".format(name=self._name,
+ id=self._id,
+ old_clock=self._clock_divisor,
+ new_clock=clock_divisor))
+ self._clock_divisor = clock_divisor
+
+ @property
+ def idlepc(self):
+ """
+ Returns the idle Pointer Counter (PC).
+
+ :returns: idlepc value (string)
+ """
+
+ return self._idlepc
+
+ @asyncio.coroutine
+ def set_idlepc(self, idlepc):
+ """
+ Sets the idle Pointer Counter (PC)
+
+ :param idlepc: idlepc value (string)
+ """
+
+ if not idlepc:
+ idlepc = "0x0"
+
+ is_running = yield from self.is_running()
+ if not is_running:
+ # router is not running
+ yield from self._hypervisor.send("vm set_idle_pc '{name}' {idlepc}".format(name=self._name, idlepc=idlepc))
+ else:
+ yield from self._hypervisor.send("vm set_idle_pc_online '{name}' 0 {idlepc}".format(name=self._name, idlepc=idlepc))
+
+ log.info("Router '{name}' [{id}]: idle-PC set to {idlepc}".format(name=self._name, id=self._id, idlepc=idlepc))
+ self._idlepc = idlepc
+
+ @asyncio.coroutine
+ def get_idle_pc_prop(self):
+ """
+ Gets the idle PC proposals.
+ Takes 1000 measurements and records up to 10 idle PC proposals.
+ There is a 10ms wait between each measurement.
+
+ :returns: list of idle PC proposal
+ """
+
+ is_running = yield from self.is_running()
+ if not is_running:
+ # router is not running
+ raise DynamipsError("Router '{name}' is not running".format(name=self._name))
+
+ log.info("Router '{name}' [{id}] has started calculating Idle-PC values".format(name=self._name, id=self._id))
+ begin = time.time()
+ idlepcs = yield from self._hypervisor.send("vm get_idle_pc_prop '{}' 0".format(self._name))
+ log.info("Router '{name}' [{id}] has finished calculating Idle-PC values after {time:.4f} seconds".format(name=self._name,
+ id=self._id,
+ time=time.time() - begin))
+ return idlepcs
+
+ @asyncio.coroutine
+ def show_idle_pc_prop(self):
+ """
+ Dumps the idle PC proposals (previously generated).
+
+ :returns: list of idle PC proposal
+ """
+
+ is_running = yield from self.is_running()
+ if not is_running:
+ # router is not running
+ raise DynamipsError("Router '{name}' is not running".format(name=self._name))
+
+ proposals = yield from self._hypervisor.send("vm show_idle_pc_prop '{}' 0".format(self._name))
+ return proposals
+
+ @property
+ def idlemax(self):
+ """
+ Returns CPU idle max value.
+
+ :returns: idle max (integer)
+ """
+
+ return self._idlemax
+
+ @asyncio.coroutine
+ def set_idlemax(self, idlemax):
+ """
+ Sets CPU idle max value
+
+ :param idlemax: idle max value (integer)
+ """
+
+ is_running = yield from self.is_running()
+ if is_running: # router is running
+ yield from self._hypervisor.send("vm set_idle_max '{name}' 0 {idlemax}".format(name=self._name, idlemax=idlemax))
+
+ log.info("Router '{name}' [{id}]: idlemax updated from {old_idlemax} to {new_idlemax}".format(name=self._name,
+ id=self._id,
+ old_idlemax=self._idlemax,
+ new_idlemax=idlemax))
+
+ self._idlemax = idlemax
+
+ @property
+ def idlesleep(self):
+ """
+ Returns CPU idle sleep time value.
+
+ :returns: idle sleep (integer)
+ """
+
+ return self._idlesleep
+
+ @asyncio.coroutine
+ def set_idlesleep(self, idlesleep):
+ """
+ Sets CPU idle sleep time value.
+
+ :param idlesleep: idle sleep value (integer)
+ """
+
+ is_running = yield from self.is_running()
+ if is_running: # router is running
+ yield from self._hypervisor.send("vm set_idle_sleep_time '{name}' 0 {idlesleep}".format(name=self._name,
+ idlesleep=idlesleep))
+
+ log.info("Router '{name}' [{id}]: idlesleep updated from {old_idlesleep} to {new_idlesleep}".format(name=self._name,
+ id=self._id,
+ old_idlesleep=self._idlesleep,
+ new_idlesleep=idlesleep))
+
+ self._idlesleep = idlesleep
+
+ @property
+ def ghost_file(self):
+ """
+ Returns ghost RAM file.
+
+ :returns: path to ghost file
+ """
+
+ return self._ghost_file
+
+ @asyncio.coroutine
+ def set_ghost_file(self, ghost_file):
+ """
+ Sets ghost RAM file
+
+ :ghost_file: path to ghost file
+ """
+
+ yield from self._hypervisor.send("vm set_ghost_file '{name}' {ghost_file}".format(name=self._name,
+ ghost_file=ghost_file))
+
+ log.info("Router '{name}' [{id}]: ghost file set to {ghost_file}".format(name=self._name,
+ id=self._id,
+ ghost_file=ghost_file))
+
+ self._ghost_file = ghost_file
+
+ # this is a ghost instance, track this as a hosted ghost instance by this hypervisor
+ if self.ghost_status == 1:
+ self._hypervisor.add_ghost(ghost_file, self)
+
+ def formatted_ghost_file(self):
+ """
+ Returns a properly formatted ghost file name.
+
+ :returns: formatted ghost_file name (string)
+ """
+
+ # replace specials characters in 'drive:\filename' in Linux and Dynamips in MS Windows or viceversa.
+ ghost_file = "{}-{}.ghost".format(os.path.basename(self._image), self._ram)
+ ghost_file = ghost_file.replace('\\', '-').replace('/', '-').replace(':', '-')
+ return ghost_file
+
+ @property
+ def ghost_status(self):
+ """Returns ghost RAM status
+
+ :returns: ghost status (integer)
+ """
+
+ return self._ghost_status
+
+ @asyncio.coroutine
+ def set_ghost_status(self, ghost_status):
+ """
+ Sets ghost RAM status
+
+ :param ghost_status: state flag indicating status
+ 0 => Do not use IOS ghosting
+ 1 => This is a ghost instance
+ 2 => Use an existing ghost instance
+ """
+
+ yield from self._hypervisor.send("vm set_ghost_status '{name}' {ghost_status}".format(name=self._name,
+ ghost_status=ghost_status))
+
+ log.info("Router '{name}' [{id}]: ghost status set to {ghost_status}".format(name=self._name,
+ id=self._id,
+ ghost_status=ghost_status))
+ self._ghost_status = ghost_status
+
+ @property
+ def exec_area(self):
+ """
+ Returns the exec area value.
+
+ :returns: exec area value (integer)
+ """
+
+ return self._exec_area
+
+ @asyncio.coroutine
+ def set_exec_area(self, exec_area):
+ """
+ Sets the exec area value.
+ The exec area is a pool of host memory used to store pages
+ translated by the JIT (they contain the native code
+ corresponding to MIPS code pages).
+
+ :param exec_area: exec area value (integer)
+ """
+
+ yield from self._hypervisor.send("vm set_exec_area '{name}' {exec_area}".format(name=self._name,
+ exec_area=exec_area))
+
+ log.info("Router '{name}' [{id}]: exec area updated from {old_exec}MB to {new_exec}MB".format(name=self._name,
+ id=self._id,
+ old_exec=self._exec_area,
+ new_exec=exec_area))
+ self._exec_area = exec_area
+
+ @property
+ def disk0(self):
+ """
+ Returns the size (MB) for PCMCIA disk0.
+
+ :returns: disk0 size (integer)
+ """
+
+ return self._disk0
+
+ @asyncio.coroutine
+ def set_disk0(self, disk0):
+ """
+ Sets the size (MB) for PCMCIA disk0.
+
+ :param disk0: disk0 size (integer)
+ """
+
+ yield from self._hypervisor.send("vm set_disk0 '{name}' {disk0}".format(name=self._name, disk0=disk0))
+
+ log.info("Router {name} [{id}]: disk0 updated from {old_disk0}MB to {new_disk0}MB".format(name=self._name,
+ id=self._id,
+ old_disk0=self._disk0,
+ new_disk0=disk0))
+ self._disk0 = disk0
+
+ @property
+ def disk1(self):
+ """
+ Returns the size (MB) for PCMCIA disk1.
+
+ :returns: disk1 size (integer)
+ """
+
+ return self._disk1
+
+ @asyncio.coroutine
+ def disk1(self, disk1):
+ """
+ Sets the size (MB) for PCMCIA disk1.
+
+ :param disk1: disk1 size (integer)
+ """
+
+ yield from self._hypervisor.send("vm set_disk1 '{name}' {disk1}".format(name=self._name, disk1=disk1))
+
+ log.info("Router '{name}' [{id}]: disk1 updated from {old_disk1}MB to {new_disk1}MB".format(name=self._name,
+ id=self._id,
+ old_disk1=self._disk1,
+ new_disk1=disk1))
+ self._disk1 = disk1
+
+ @property
+ def confreg(self):
+ """
+ Returns the configuration register.
+ The default is 0x2102.
+
+ :returns: configuration register value (string)
+ """
+
+ return self._confreg
+
+ @asyncio.coroutine
+ def set_confreg(self, confreg):
+ """
+ Sets the configuration register.
+
+ :param confreg: configuration register value (string)
+ """
+
+ yield from self._hypervisor.send("vm set_conf_reg '{name}' {confreg}".format(name=self._name, confreg=confreg))
+
+ log.info("Router '{name}' [{id}]: confreg updated from {old_confreg} to {new_confreg}".format(name=self._name,
+ id=self._id,
+ old_confreg=self._confreg,
+ new_confreg=confreg))
+ self._confreg = confreg
+
+ @property
+ def console(self):
+ """
+ Returns the TCP console port.
+
+ :returns: console port (integer)
+ """
+
+ return self._console
+
+ @asyncio.coroutine
+ def set_console(self, console):
+ """
+ Sets the TCP console port.
+
+ :param console: console port (integer)
+ """
+
+ yield from self._hypervisor.send("vm set_con_tcp_port '{name}' {console}".format(name=self._name, console=console))
+
+ log.info("Router '{name}' [{id}]: console port updated from {old_console} to {new_console}".format(name=self._name,
+ id=self._id,
+ old_console=self._console,
+ new_console=console))
+
+ self._manager.port_manager.release_console_port(self._console)
+ self._console = self._manager.port_manager.reserve_console_port(console)
+
+ @property
+ def aux(self):
+ """
+ Returns the TCP auxiliary port.
+
+ :returns: console auxiliary port (integer)
+ """
+
+ return self._aux
+
+ @asyncio.coroutine
+ def set_aux(self, aux):
+ """
+ Sets the TCP auxiliary port.
+
+ :param aux: console auxiliary port (integer)
+ """
+
+ yield from self._hypervisor.send("vm set_aux_tcp_port '{name}' {aux}".format(name=self._name, aux=aux))
+
+ log.info("Router '{name}' [{id}]: aux port updated from {old_aux} to {new_aux}".format(name=self._name,
+ id=self._id,
+ old_aux=self._aux,
+ new_aux=aux))
+
+ self._manager.port_manager.release_console_port(self._aux)
+ self._aux = self._manager.port_manager.reserve_console_port(aux)
+
+ @asyncio.coroutine
+ def get_cpu_usage(self, cpu_id=0):
+ """
+ Shows cpu usage in seconds, "cpu_id" is ignored.
+
+ :returns: cpu usage in seconds
+ """
+
+ cpu_usage = yield from self._hypervisor.send("vm cpu_usage '{name}' {cpu_id}".format(name=self._name, cpu_id=cpu_id))
+ return int(cpu_usage[0])
+
+ @property
+ def mac_addr(self):
+ """
+ Returns the MAC address.
+
+ :returns: the MAC address (hexadecimal format: hh:hh:hh:hh:hh:hh)
+ """
+
+ return self._mac_addr
+
+ @asyncio.coroutine
+ def set_mac_addr(self, mac_addr):
+ """
+ Sets the MAC address.
+
+ :param mac_addr: a MAC address (hexadecimal format: hh:hh:hh:hh:hh:hh)
+ """
+
+ yield from self._hypervisor.send("{platform} set_mac_addr '{name}' {mac_addr}".format(platform=self._platform,
+ name=self._name,
+ mac_addr=mac_addr))
+
+ log.info("Router '{name}' [{id}]: MAC address updated from {old_mac} to {new_mac}".format(name=self._name,
+ id=self._id,
+ old_mac=self._mac_addr,
+ new_mac=mac_addr))
+ self._mac_addr = mac_addr
+
+ @property
+ def system_id(self):
+ """
+ Returns the system ID.
+
+ :returns: the system ID (also called board processor ID)
+ """
+
+ return self._system_id
+
+ @asyncio.coroutine
+ def set_system_id(self, system_id):
+ """
+ Sets the system ID.
+
+ :param system_id: a system ID (also called board processor ID)
+ """
+
+ yield from self._hypervisor.send("{platform} set_system_id '{name}' {system_id}".format(platform=self._platform,
+ name=self._name,
+ system_id=system_id))
+
+ log.info("Router '{name'} [{id}]: system ID updated from {old_id} to {new_id}".format(name=self._name,
+ id=self._id,
+ old_id=self._system_id,
+ new_id=system_id))
+ self._system_id = system_id
+
+ @asyncio.coroutine
+ def get_slot_bindings(self):
+ """
+ Returns slot bindings.
+
+ :returns: slot bindings (adapter names) list
+ """
+
+ slot_bindings = yield from self._hypervisor.send("vm slot_bindings '{}'".format(self._name))
+ return slot_bindings
+
+ @asyncio.coroutine
+ def slot_add_binding(self, slot_id, adapter):
+ """
+ Adds a slot binding (a module into a slot).
+
+ :param slot_id: slot ID
+ :param adapter: device to add in the corresponding slot
+ """
+
+ try:
+ slot = self._slots[slot_id]
+ except IndexError:
+ raise DynamipsError("Slot {slot_id} doesn't exist on router '{name}'".format(name=self._name, slot_id=slot_id))
+
+ if slot is not None:
+ current_adapter = slot
+ raise DynamipsError("Slot {slot_id} is already occupied by adapter {adapter} on router '{name}'".format(name=self._name,
+ slot_id=slot_id,
+ adapter=current_adapter))
+
+ is_running = yield from self.is_running()
+
+ # Only c7200, c3600 and c3745 (NM-4T only) support new adapter while running
+ if is_running and not ((self._platform == 'c7200' and not str(adapter).startswith('C7200'))
+ and not (self._platform == 'c3600' and self.chassis == '3660')
+ and not (self._platform == 'c3745' and adapter == 'NM-4T')):
+ raise DynamipsError("Adapter {adapter} cannot be added while router '{name} 'is running".format(adapter=adapter,
+ name=self._name))
+
+ yield from self._hypervisor.send("vm slot_add_binding '{name}' {slot_id} 0 {adapter}".format(name=self._name,
+ slot_id=slot_id,
+ adapter=adapter))
+
+ log.info("Router '{name}' [{id}]: adapter {adapter} inserted into slot {slot_id}".format(name=self._name,
+ id=self._id,
+ adapter=adapter,
+ slot_id=slot_id))
+
+ self._slots[slot_id] = adapter
+
+ # Generate an OIR event if the router is running
+ if is_running:
+
+ yield from self._hypervisor.send("vm slot_oir_start '{name}' {slot_id} 0".format(name=self._name, slot_id=slot_id))
+
+ log.info("Router '{name}' [{id}]: OIR start event sent to slot {slot_id}".format(name=self._name,
+ id=self._id,
+ slot_id=slot_id))
+
+ @asyncio.coroutine
+ def slot_remove_binding(self, slot_id):
+ """
+ Removes a slot binding (a module from a slot).
+
+ :param slot_id: slot ID
+ """
+
+ try:
+ adapter = self._slots[slot_id]
+ except IndexError:
+ raise DynamipsError("Slot {slot_id} doesn't exist on router '{name}'".format(name=self._name, slot_id=slot_id))
+
+ if adapter is None:
+ raise DynamipsError("No adapter in slot {slot_id} on router '{name}'".format(name=self._name,
+ slot_id=slot_id))
+
+ is_running = yield from self.is_running()
+
+ # Only c7200, c3600 and c3745 (NM-4T only) support to remove adapter while running
+ if is_running and not ((self._platform == 'c7200' and not str(adapter).startswith('C7200'))
+ and not (self._platform == 'c3600' and self.chassis == '3660')
+ and not (self._platform == 'c3745' and adapter == 'NM-4T')):
+ raise DynamipsError("Adapter {adapter} cannot be removed while router '{name}' is running".format(adapter=adapter,
+ name=self._name))
+
+ # Generate an OIR event if the router is running
+ if is_running:
+
+ yield from self._hypervisor.send("vm slot_oir_stop '{name}' {slot_id} 0".format(name=self._name, slot_id=slot_id))
+
+ log.info("router '{name}' [{id}]: OIR stop event sent to slot {slot_id}".format(name=self._name,
+ id=self._id,
+ slot_id=slot_id))
+
+ yield from self._hypervisor.send("vm slot_remove_binding '{name}' {slot_id} 0".format(name=self._name, slot_id=slot_id))
+
+ log.info("Router '{name}' [{id}]: adapter {adapter} removed from slot {slot_id}".format(name=self._name,
+ id=self._id,
+ adapter=adapter,
+ slot_id=slot_id))
+ self._slots[slot_id] = None
+
+ @asyncio.coroutine
+ def install_wic(self, wic_slot_id, wic):
+ """
+ Installs a WIC adapter into this router.
+
+ :param wic_slot_id: WIC slot ID
+ :param wic: WIC to be installed
+ """
+
+ # WICs are always installed on adapters in slot 0
+ slot_id = 0
+
+ # Do not check if slot has an adapter because adapters with WICs interfaces
+ # must be inserted by default in the router and cannot be removed.
+ adapter = self._slots[slot_id]
+
+ if wic_slot_id > len(adapter.wics) - 1:
+ raise DynamipsError("WIC slot {wic_slot_id} doesn't exist".format(wic_slot_id=wic_slot_id))
+
+ if not adapter.wic_slot_available(wic_slot_id):
+ raise DynamipsError("WIC slot {wic_slot_id} is already occupied by another WIC".format(wic_slot_id=wic_slot_id))
+
+ # Dynamips WICs slot IDs start on a multiple of 16
+ # WIC1 = 16, WIC2 = 32 and WIC3 = 48
+ internal_wic_slot_id = 16 * (wic_slot_id + 1)
+ yield from self._hypervisor.send("vm slot_add_binding '{name}' {slot_id} {wic_slot_id} {wic}".format(name=self._name,
+ slot_id=slot_id,
+ wic_slot_id=internal_wic_slot_id,
+ wic=wic))
+
+ log.info("Router '{name}' [{id}]: {wic} inserted into WIC slot {wic_slot_id}".format(name=self._name,
+ id=self._id,
+ wic=wic,
+ wic_slot_id=wic_slot_id))
+
+ adapter.install_wic(wic_slot_id, wic)
+
+ @asyncio.coroutine
+ def uninstall_wic(self, wic_slot_id):
+ """
+ Uninstalls a WIC adapter from this router.
+
+ :param wic_slot_id: WIC slot ID
+ """
+
+ # WICs are always installed on adapters in slot 0
+ slot_id = 0
+
+ # Do not check if slot has an adapter because adapters with WICs interfaces
+ # must be inserted by default in the router and cannot be removed.
+ adapter = self._slots[slot_id]
+
+ if wic_slot_id > len(adapter.wics) - 1:
+ raise DynamipsError("WIC slot {wic_slot_id} doesn't exist".format(wic_slot_id=wic_slot_id))
+
+ if adapter.wic_slot_available(wic_slot_id):
+ raise DynamipsError("No WIC is installed in WIC slot {wic_slot_id}".format(wic_slot_id=wic_slot_id))
+
+ # Dynamips WICs slot IDs start on a multiple of 16
+ # WIC1 = 16, WIC2 = 32 and WIC3 = 48
+ internal_wic_slot_id = 16 * (wic_slot_id + 1)
+ yield from self._hypervisor.send("vm slot_remove_binding '{name}' {slot_id} {wic_slot_id}".format(name=self._name,
+ slot_id=slot_id,
+ wic_slot_id=internal_wic_slot_id))
+
+ log.info("Router '{name}' [{id}]: {wic} removed from WIC slot {wic_slot_id}".format(name=self._name,
+ id=self._id,
+ wic=adapter.wics[wic_slot_id],
+ wic_slot_id=wic_slot_id))
+ adapter.uninstall_wic(wic_slot_id)
+
+ @asyncio.coroutine
+ def get_slot_nio_bindings(self, slot_id):
+ """
+ Returns slot NIO bindings.
+
+ :param slot_id: slot ID
+
+ :returns: list of NIO bindings
+ """
+
+ nio_bindings = yield from self._hypervisor.send("vm slot_nio_bindings '{name}' {slot_id}".format(name=self._name,
+ slot_id=slot_id))
+ return nio_bindings
+
+ @asyncio.coroutine
+ def slot_add_nio_binding(self, slot_id, port_id, nio):
+ """
+ Adds a slot NIO binding.
+
+ :param slot_id: slot ID
+ :param port_id: port ID
+ :param nio: NIO instance to add to the slot/port
+ """
+
+ try:
+ adapter = self._slots[slot_id]
+ except IndexError:
+ raise DynamipsError("Slot {slot_id} doesn't exist on router '{name}'".format(name=self._name,
+ slot_id=slot_id))
+ if not adapter.port_exists(port_id):
+ raise DynamipsError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=adapter,
+ port_id=port_id))
+
+ yield from self._hypervisor.send("vm slot_add_nio_binding '{name}' {slot_id} {port_id} {nio}".format(name=self._name,
+ slot_id=slot_id,
+ port_id=port_id,
+ nio=nio))
+
+ log.info("Router '{name}' [{id}]: NIO {nio_name} bound to port {slot_id}/{port_id}".format(name=self._name,
+ id=self._id,
+ nio_name=nio.name,
+ slot_id=slot_id,
+ port_id=port_id))
+
+ yield from self.slot_enable_nio(slot_id, port_id)
+ adapter.add_nio(port_id, nio)
+
+ @asyncio.coroutine
+ def slot_remove_nio_binding(self, slot_id, port_id):
+ """
+ Removes a slot NIO binding.
+
+ :param slot_id: slot ID
+ :param port_id: port ID
+
+ :returns: removed NIO instance
+ """
+
+ try:
+ adapter = self._slots[slot_id]
+ except IndexError:
+ raise DynamipsError("Slot {slot_id} doesn't exist on router '{name}'".format(name=self._name, slot_id=slot_id))
+ if not adapter.port_exists(port_id):
+ raise DynamipsError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=adapter, port_id=port_id))
+
+ yield from self.slot_disable_nio(slot_id, port_id)
+ yield from self._hypervisor.send("vm slot_remove_nio_binding '{name}' {slot_id} {port_id}".format(name=self._name,
+ slot_id=slot_id,
+ port_id=port_id))
+
+ nio = adapter.get_nio(port_id)
+ adapter.remove_nio(port_id)
+
+ log.info("Router '{name}' [{id}]: NIO {nio_name} removed from port {slot_id}/{port_id}".format(name=self._name,
+ id=self._id,
+ nio_name=nio.name,
+ slot_id=slot_id,
+ port_id=port_id))
+
+ return nio
+
+ @asyncio.coroutine
+ def slot_enable_nio(self, slot_id, port_id):
+ """
+ Enables a slot NIO binding.
+
+ :param slot_id: slot ID
+ :param port_id: port ID
+ """
+
+ is_running = yield from self.is_running()
+ if is_running: # running router
+ yield from self._hypervisor.send("vm slot_enable_nio '{name}' {slot_id} {port_id}".format(name=self._name,
+ slot_id=slot_id,
+ port_id=port_id))
+
+ log.info("Router '{name}' [{id}]: NIO enabled on port {slot_id}/{port_id}".format(name=self._name,
+ id=self._id,
+ slot_id=slot_id,
+ port_id=port_id))
+ @asyncio.coroutine
+ def slot_disable_nio(self, slot_id, port_id):
+ """
+ Disables a slot NIO binding.
+
+ :param slot_id: slot ID
+ :param port_id: port ID
+ """
+
+ is_running = yield from self.is_running()
+ if is_running: # running router
+ yield from self._hypervisor.send("vm slot_disable_nio '{name}' {slot_id} {port_id}".format(name=self._name,
+ slot_id=slot_id,
+ port_id=port_id))
+
+ log.info("Router '{name}' [{id}]: NIO disabled on port {slot_id}/{port_id}".format(name=self._name,
+ id=self._id,
+ slot_id=slot_id,
+ port_id=port_id))
+
+ @asyncio.coroutine
+ def start_capture(self, slot_id, port_id, output_file, data_link_type="DLT_EN10MB"):
+ """
+ Starts a packet capture.
+
+ :param slot_id: slot ID
+ :param port_id: port ID
+ :param output_file: PCAP destination file for the capture
+ :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
+ """
+
+ try:
+ adapter = self._slots[slot_id]
+ except IndexError:
+ raise DynamipsError("Slot {slot_id} doesn't exist on router '{name}'".format(name=self._name, slot_id=slot_id))
+ if not adapter.port_exists(port_id):
+ raise DynamipsError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=adapter, port_id=port_id))
+
+ data_link_type = data_link_type.lower()
+ if data_link_type.startswith("dlt_"):
+ data_link_type = data_link_type[4:]
+
+ nio = adapter.get_nio(port_id)
+
+ if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
+ raise DynamipsError("Port {port_id} has already a filter applied on {adapter}".format(adapter=adapter,
+ port_id=port_id))
+
+
+ # FIXME: capture
+ #try:
+ # os.makedirs(os.path.dirname(output_file), exist_ok=True)
+ #except OSError as e:
+ # raise DynamipsError("Could not create captures directory {}".format(e))
+
+ yield from nio.bind_filter("both", "capture")
+ yield from nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file))
+
+ log.info("Router '{name}' [{id}]: starting packet capture on port {slot_id}/{port_id}".format(name=self._name,
+ id=self._id,
+ nio_name=nio.name,
+ slot_id=slot_id,
+ port_id=port_id))
+ @asyncio.coroutine
+ def stop_capture(self, slot_id, port_id):
+ """
+ Stops a packet capture.
+
+ :param slot_id: slot ID
+ :param port_id: port ID
+ """
+
+ try:
+ adapter = self._slots[slot_id]
+ except IndexError:
+ raise DynamipsError("Slot {slot_id} doesn't exist on router '{name}'".format(name=self._name, slot_id=slot_id))
+ if not adapter.port_exists(port_id):
+ raise DynamipsError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=adapter, port_id=port_id))
+
+ nio = adapter.get_nio(port_id)
+ yield from nio.unbind_filter("both")
+
+ log.info("Router '{name}' [{id}]: stopping packet capture on port {slot_id}/{port_id}".format(name=self._name,
+ id=self._id,
+ nio_name=nio.name,
+ slot_id=slot_id,
+ port_id=port_id))
+
+ def _create_slots(self, numslots):
+ """
+ Creates the appropriate number of slots for this router.
+
+ :param numslots: number of slots to create
+ """
+
+ self._slots = numslots * [None]
+
+ @property
+ def slots(self):
+ """
+ Returns the slots for this router.
+
+ :return: slot list
+ """
+
+ return self._slots
+
+ @property
+ def startup_config(self):
+ """
+ Returns the startup-config for this router.
+
+ :returns: path to startup-config file
+ """
+
+ return self._startup_config
+
+ @startup_config.setter
+ def startup_config(self, startup_config):
+ """
+ Sets the startup-config for this router.
+
+ :param startup_config: path to startup-config file
+ """
+
+ self._startup_config = startup_config
+
+ @property
+ def private_config(self):
+ """
+ Returns the private-config for this router.
+
+ :returns: path to private-config file
+ """
+
+ return self._private_config
+
+ @private_config.setter
+ def private_config(self, private_config):
+ """
+ Sets the private-config for this router.
+
+ :param private_config: path to private-config file
+ """
+
+ self._private_config = private_config
+
+ # def rename(self, new_name):
+ # """
+ # Renames this router.
+ #
+ # :param new_name: new name string
+ # """
+ #
+ # if self._startup_config:
+ # # change the hostname in the startup-config
+ # startup_config_path = os.path.join(self.hypervisor.working_dir, "configs", "i{}_startup-config.cfg".format(self.id))
+ # if os.path.isfile(startup_config_path):
+ # try:
+ # with open(startup_config_path, "r+", errors="replace") as f:
+ # old_config = f.read()
+ # new_config = old_config.replace(self.name, new_name)
+ # f.seek(0)
+ # f.write(new_config)
+ # except OSError as e:
+ # raise DynamipsError("Could not amend the configuration {}: {}".format(startup_config_path, e))
+ #
+ # if self._private_config:
+ # # change the hostname in the private-config
+ # private_config_path = os.path.join(self.hypervisor.working_dir, "configs", "i{}_private-config.cfg".format(self.id))
+ # if os.path.isfile(private_config_path):
+ # try:
+ # with open(private_config_path, "r+", errors="replace") as f:
+ # old_config = f.read()
+ # new_config = old_config.replace(self.name, new_name)
+ # f.seek(0)
+ # f.write(new_config)
+ # except OSError as e:
+ # raise DynamipsError("Could not amend the configuration {}: {}".format(private_config_path, e))
+ #
+ # new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
+ # self._hypervisor.send("vm rename {name} {new_name}".format(name=self._name,
+ # new_name=new_name))
+ #
+ # log.info("router {name} [id={id}]: renamed to {new_name}".format(name=self._name,
+ # id=self._id,
+ # new_name=new_name))
+ # self._name = new_name
+
+ # def set_config(self, startup_config, private_config=''):
+ # """
+ # Sets the config files that are pushed to startup-config and
+ # private-config in NVRAM when the instance is started.
+ #
+ # :param startup_config: path to statup-config file
+ # :param private_config: path to private-config file
+ # (keep existing data when if an empty string)
+ # """
+ #
+ # if self._startup_config != startup_config or self._private_config != private_config:
+ #
+ # self._hypervisor.send("vm set_config {name} {startup} {private}".format(name=self._name,
+ # startup='"' + startup_config + '"',
+ # private='"' + private_config + '"'))
+ #
+ # log.info("router {name} [id={id}]: has a startup-config set: {startup}".format(name=self._name,
+ # id=self._id,
+ # startup='"' + startup_config + '"'))
+ #
+ # self._startup_config = startup_config
+ #
+ # if private_config:
+ # log.info("router {name} [id={id}]: has a private-config set: {private}".format(name=self._name,
+ # id=self._id,
+ # private='"' + private_config + '"'))
+ #
+ # self._private_config = private_config
+ #
+ # def extract_config(self):
+ # """
+ # Gets the contents of the config files
+ # startup-config and private-config from NVRAM.
+ #
+ # :returns: tuple (startup-config, private-config) base64 encoded
+ # """
+ #
+ # try:
+ # reply = self._hypervisor.send("vm extract_config {}".format(self._name))[0].rsplit(' ', 2)[-2:]
+ # except IOError:
+ # #for some reason Dynamips gets frozen when it does not find the magic number in the NVRAM file.
+ # return None, None
+ # startup_config = reply[0][1:-1] # get statup-config and remove single quotes
+ # private_config = reply[1][1:-1] # get private-config and remove single quotes
+ # return startup_config, private_config
+ #
+ # def push_config(self, startup_config, private_config='(keep)'):
+ # """
+ # Pushes configuration to the config files startup-config and private-config in NVRAM.
+ # The data is a Base64 encoded string, or '(keep)' to keep existing data.
+ #
+ # :param startup_config: statup-config string base64 encoded
+ # :param private_config: private-config string base64 encoded
+ # (keep existing data when if the value is ('keep'))
+ # """
+ #
+ # self._hypervisor.send("vm push_config {name} {startup} {private}".format(name=self._name,
+ # startup=startup_config,
+ # private=private_config))
+ #
+ # log.info("router {name} [id={id}]: new startup-config pushed".format(name=self._name,
+ # id=self._id))
+ #
+ # if private_config != '(keep)':
+ # log.info("router {name} [id={id}]: new private-config pushed".format(name=self._name,
+ # id=self._id))
+ #
+ # def save_configs(self):
+ # """
+ # Saves the startup-config and private-config to files.
+ # """
+ #
+ # if self.startup_config or self.private_config:
+ # startup_config_base64, private_config_base64 = self.extract_config()
+ # if startup_config_base64:
+ # try:
+ # config = base64.decodebytes(startup_config_base64.encode("utf-8")).decode("utf-8")
+ # config = "!\n" + config.replace("\r", "")
+ # config_path = os.path.join(self.hypervisor.working_dir, self.startup_config)
+ # with open(config_path, "w") as f:
+ # log.info("saving startup-config to {}".format(self.startup_config))
+ # f.write(config)
+ # except OSError as e:
+ # raise DynamipsError("Could not save the startup configuration {}: {}".format(config_path, e))
+ #
+ # if private_config_base64:
+ # try:
+ # config = base64.decodebytes(private_config_base64.encode("utf-8")).decode("utf-8")
+ # config = "!\n" + config.replace("\r", "")
+ # config_path = os.path.join(self.hypervisor.working_dir, self.private_config)
+ # with open(config_path, "w") as f:
+ # log.info("saving private-config to {}".format(self.private_config))
+ # f.write(config)
+ # except OSError as e:
+ # raise DynamipsError("Could not save the private configuration {}: {}".format(config_path, e))
+
+ # def clean_delete(self):
+ # """
+ # Deletes this router & associated files (nvram, disks etc.)
+ # """
+ #
+ # self._hypervisor.send("vm clean_delete {}".format(self._name))
+ # self._hypervisor.devices.remove(self)
+ #
+ # if self._startup_config:
+ # # delete the startup-config
+ # startup_config_path = os.path.join(self.hypervisor.working_dir, "configs", "{}.cfg".format(self.name))
+ # if os.path.isfile(startup_config_path):
+ # os.remove(startup_config_path)
+ #
+ # if self._private_config:
+ # # delete the private-config
+ # private_config_path = os.path.join(self.hypervisor.working_dir, "configs", "{}-private.cfg".format(self.name))
+ # if os.path.isfile(private_config_path):
+ # os.remove(private_config_path)
+ #
+ # log.info("router {name} [id={id}] has been deleted (including associated files)".format(name=self._name, id=self._id))
diff --git a/gns3server/modules/port_manager.py b/gns3server/modules/port_manager.py
index 80e94087..da448cd6 100644
--- a/gns3server/modules/port_manager.py
+++ b/gns3server/modules/port_manager.py
@@ -185,7 +185,7 @@ class PortManager:
"""
if port in self._used_tcp_ports:
- raise HTTPConflict(text="TCP port already {} in use on host".format(port, self._console_host))
+ raise HTTPConflict(text="TCP port {} already in use on host".format(port, self._console_host))
self._used_tcp_ports.add(port)
return port
@@ -221,7 +221,7 @@ class PortManager:
"""
if port in self._used_udp_ports:
- raise HTTPConflict(text="UDP port already {} in use on host".format(port, self._console_host))
+ raise HTTPConflict(text="UDP port {} already in use on host".format(port, self._console_host))
self._used_udp_ports.add(port)
def release_udp_port(self, port):
diff --git a/gns3server/modules/vpcs/vpcs_vm.py b/gns3server/modules/vpcs/vpcs_vm.py
index 036bfedc..9791fde0 100644
--- a/gns3server/modules/vpcs/vpcs_vm.py
+++ b/gns3server/modules/vpcs/vpcs_vm.py
@@ -254,10 +254,10 @@ class VPCSVM(BaseVM):
if self.is_running():
self._terminate_process()
try:
- yield from asyncio.wait_for(self._process.wait(), timeout=10)
+ yield from asyncio.wait_for(self._process.wait(), timeout=3)
except asyncio.TimeoutError:
self._process.kill()
- if self._process.poll() is None:
+ if self._process.returncode is None:
log.warn("VPCS process {} is still running".format(self._process.pid))
self._process = None
diff --git a/gns3server/old_modules/dynamips/__init__.py b/gns3server/old_modules/dynamips/__init__.py
deleted file mode 100644
index 26347094..00000000
--- a/gns3server/old_modules/dynamips/__init__.py
+++ /dev/null
@@ -1,578 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Dynamips server module.
-"""
-
-import sys
-import os
-import base64
-import tempfile
-import shutil
-import glob
-import socket
-from gns3server.modules import IModule
-from gns3server.config import Config
-from gns3server.builtins.interfaces import get_windows_interfaces
-
-from .hypervisor import Hypervisor
-from .hypervisor_manager import HypervisorManager
-from .dynamips_error import DynamipsError
-
-# Nodes
-from .nodes.router import Router
-from .nodes.c1700 import C1700
-from .nodes.c2600 import C2600
-from .nodes.c2691 import C2691
-from .nodes.c3600 import C3600
-from .nodes.c3725 import C3725
-from .nodes.c3745 import C3745
-from .nodes.c7200 import C7200
-from .nodes.bridge import Bridge
-from .nodes.ethernet_switch import EthernetSwitch
-from .nodes.atm_switch import ATMSwitch
-from .nodes.atm_bridge import ATMBridge
-from .nodes.frame_relay_switch import FrameRelaySwitch
-from .nodes.hub import Hub
-
-# Adapters
-from .adapters.c7200_io_2fe import C7200_IO_2FE
-from .adapters.c7200_io_fe import C7200_IO_FE
-from .adapters.c7200_io_ge_e import C7200_IO_GE_E
-from .adapters.nm_16esw import NM_16ESW
-from .adapters.nm_1e import NM_1E
-from .adapters.nm_1fe_tx import NM_1FE_TX
-from .adapters.nm_4e import NM_4E
-from .adapters.nm_4t import NM_4T
-from .adapters.pa_2fe_tx import PA_2FE_TX
-from .adapters.pa_4e import PA_4E
-from .adapters.pa_4t import PA_4T
-from .adapters.pa_8e import PA_8E
-from .adapters.pa_8t import PA_8T
-from .adapters.pa_a1 import PA_A1
-from .adapters.pa_fe_tx import PA_FE_TX
-from .adapters.pa_ge import PA_GE
-from .adapters.pa_pos_oc3 import PA_POS_OC3
-from .adapters.wic_1t import WIC_1T
-from .adapters.wic_2t import WIC_2T
-from .adapters.wic_1enet import WIC_1ENET
-
-# NIOs
-from .nios.nio_udp import NIO_UDP
-from .nios.nio_udp_auto import NIO_UDP_auto
-from .nios.nio_unix import NIO_UNIX
-from .nios.nio_vde import NIO_VDE
-from .nios.nio_tap import NIO_TAP
-from .nios.nio_generic_ethernet import NIO_GenericEthernet
-from .nios.nio_linux_ethernet import NIO_LinuxEthernet
-from .nios.nio_fifo import NIO_FIFO
-from .nios.nio_mcast import NIO_Mcast
-from .nios.nio_null import NIO_Null
-
-from .backends import vm
-from .backends import ethsw
-from .backends import ethhub
-from .backends import frsw
-from .backends import atmsw
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class Dynamips(IModule):
-
- """
- Dynamips module.
-
- :param name: module name
- :param args: arguments for the module
- :param kwargs: named arguments for the module
- """
-
- def __init__(self, name, *args, **kwargs):
-
- # get the Dynamips location
- config = Config.instance()
- dynamips_config = config.get_section_config(name.upper())
- self._dynamips = dynamips_config.get("dynamips_path")
- if not self._dynamips or not os.path.isfile(self._dynamips):
- paths = [os.getcwd()] + os.environ["PATH"].split(os.pathsep)
- # look for Dynamips in the current working directory and $PATH
- for path in paths:
- try:
- if "dynamips" in os.listdir(path) and os.access(os.path.join(path, "dynamips"), os.X_OK):
- self._dynamips = os.path.join(path, "dynamips")
- break
- except OSError:
- continue
-
- if not self._dynamips:
- log.warning("dynamips binary couldn't be found!")
- elif not os.access(self._dynamips, os.X_OK):
- log.warning("dynamips is not executable")
-
- IModule.__init__(self, name, *args, **kwargs)
- self._hypervisor_manager = None
- self._hypervisor_manager_settings = {}
- self._routers = {}
- self._ethernet_switches = {}
- self._frame_relay_switches = {}
- self._atm_switches = {}
- self._ethernet_hubs = {}
- self._projects_dir = kwargs["projects_dir"]
- self._tempdir = kwargs["temp_dir"]
- self._working_dir = self._projects_dir
- self._host = dynamips_config.get("host", kwargs["host"])
- self._console_host = dynamips_config.get("console_host", kwargs["console_host"])
-
- if not sys.platform.startswith("win32"):
- # FIXME: pickle issues Windows
- self._callback = self.add_periodic_callback(self._check_hypervisors, 5000)
- self._callback.start()
-
- def stop(self, signum=None):
- """
- Properly stops the module.
-
- :param signum: signal number (if called by the signal handler)
- """
-
- if not sys.platform.startswith("win32"):
- self._callback.stop()
-
- # automatically save configs for all router instances
- for router_id in self._routers:
- router = self._routers[router_id]
- try:
- router.save_configs()
- except DynamipsError:
- continue
-
- # stop all Dynamips hypervisors
- if self._hypervisor_manager:
- self._hypervisor_manager.stop_all_hypervisors()
-
- self.delete_dynamips_files()
- IModule.stop(self, signum) # this will stop the I/O loop
-
- def _check_hypervisors(self):
- """
- Periodic callback to check if Dynamips hypervisors are running.
-
- Sends a notification to the client if not.
- """
-
- if self._hypervisor_manager:
- for hypervisor in self._hypervisor_manager.hypervisors:
- if hypervisor.started and not hypervisor.is_running():
- notification = {"module": self.name}
- stdout = hypervisor.read_stdout()
- device_names = []
- for device in hypervisor.devices:
- device_names.append(device.name)
- notification["message"] = "Dynamips has stopped running"
- notification["details"] = stdout
- notification["devices"] = device_names
- self.send_notification("{}.dynamips_stopped".format(self.name), notification)
- hypervisor.stop()
-
- def get_device_instance(self, device_id, instance_dict):
- """
- Returns a device instance.
-
- :param device_id: device identifier
- :param instance_dict: dictionary containing the instances
-
- :returns: device instance
- """
-
- if device_id not in instance_dict:
- log.debug("device ID {} doesn't exist".format(device_id), exc_info=1)
- self.send_custom_error("Device ID {} doesn't exist".format(device_id))
- return None
- return instance_dict[device_id]
-
- def delete_dynamips_files(self):
- """
- Deletes useless Dynamips files from the working directory
- """
-
- files = glob.glob(os.path.join(self._working_dir, "dynamips", "*.ghost"))
- files += glob.glob(os.path.join(self._working_dir, "dynamips", "*_lock"))
- files += glob.glob(os.path.join(self._working_dir, "dynamips", "ilt_*"))
- files += glob.glob(os.path.join(self._working_dir, "dynamips", "c[0-9][0-9][0-9][0-9]_*_rommon_vars"))
- files += glob.glob(os.path.join(self._working_dir, "dynamips", "c[0-9][0-9][0-9][0-9]_*_ssa"))
- for file in files:
- try:
- log.debug("deleting file {}".format(file))
- os.remove(file)
- except OSError as e:
- log.warn("could not delete file {}: {}".format(file, e))
- continue
-
- @IModule.route("dynamips.reset")
- def reset(self, request=None):
- """
- Resets the module (JSON-RPC notification).
-
- :param request: JSON request (not used)
- """
-
- # automatically save configs for all router instances
- for router_id in self._routers:
- router = self._routers[router_id]
- try:
- router.save_configs()
- except DynamipsError:
- continue
-
- # stop all Dynamips hypervisors
- if self._hypervisor_manager:
- self._hypervisor_manager.stop_all_hypervisors()
-
- # resets the instance counters
- Router.reset()
- EthernetSwitch.reset()
- Hub.reset()
- FrameRelaySwitch.reset()
- ATMSwitch.reset()
- NIO_UDP.reset()
- NIO_UDP_auto.reset()
- NIO_UNIX.reset()
- NIO_VDE.reset()
- NIO_TAP.reset()
- NIO_GenericEthernet.reset()
- NIO_LinuxEthernet.reset()
- NIO_FIFO.reset()
- NIO_Mcast.reset()
- NIO_Null.reset()
-
- self._routers.clear()
- self._ethernet_switches.clear()
- self._frame_relay_switches.clear()
- self._atm_switches.clear()
-
- self.delete_dynamips_files()
-
- self._hypervisor_manager = None
- self._working_dir = self._projects_dir
- log.info("dynamips module has been reset")
-
- def start_hypervisor_manager(self):
- """
- Starts the hypervisor manager.
- """
-
- # check if Dynamips path exists
- if not os.path.isfile(self._dynamips):
- raise DynamipsError("Dynamips executable {} doesn't exist".format(self._dynamips))
-
- # check if Dynamips is executable
- if not os.access(self._dynamips, os.X_OK):
- raise DynamipsError("Dynamips {} is not executable".format(self._dynamips))
-
- workdir = os.path.join(self._working_dir, "dynamips")
- try:
- os.makedirs(workdir)
- except FileExistsError:
- pass
- except OSError as e:
- raise DynamipsError("Could not create working directory {}".format(e))
-
- # check if the working directory is writable
- if not os.access(workdir, os.W_OK):
- raise DynamipsError("Cannot write to working directory {}".format(workdir))
-
- log.info("starting the hypervisor manager with Dynamips working directory set to '{}'".format(workdir))
- self._hypervisor_manager = HypervisorManager(self._dynamips, workdir, self._host, self._console_host)
-
- for name, value in self._hypervisor_manager_settings.items():
- if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value:
- setattr(self._hypervisor_manager, name, value)
-
- @IModule.route("dynamips.settings")
- def settings(self, request):
- """
- Set or update settings.
-
- Optional request parameters:
- - path (path to the Dynamips executable)
- - working_dir (path to a working directory)
- - project_name
-
- :param request: JSON request
- """
-
- if request is None:
- self.send_param_error()
- return
-
- log.debug("received request {}".format(request))
-
- # TODO: JSON schema validation
- if not self._hypervisor_manager:
-
- if "path" in request:
- self._dynamips = request.pop("path")
-
- if "working_dir" in request:
- self._working_dir = request.pop("working_dir")
- log.info("this server is local")
- else:
- self._working_dir = os.path.join(self._projects_dir, request["project_name"])
- log.info("this server is remote with working directory path to {}".format(self._working_dir))
-
- self._hypervisor_manager_settings = request
-
- else:
- if "project_name" in request:
- # for remote server
- new_working_dir = os.path.join(self._projects_dir, request["project_name"])
-
- if self._projects_dir != self._working_dir != new_working_dir:
-
- # trick to avoid file locks by Dynamips on Windows
- if sys.platform.startswith("win"):
- self._hypervisor_manager.working_dir = tempfile.gettempdir()
-
- if not os.path.isdir(new_working_dir):
- try:
- self.delete_dynamips_files()
- shutil.move(self._working_dir, new_working_dir)
- except OSError as e:
- log.error("could not move working directory from {} to {}: {}".format(self._working_dir,
- new_working_dir,
- e))
- return
-
- elif "working_dir" in request:
- # for local server
- new_working_dir = request.pop("working_dir")
-
- try:
- self._hypervisor_manager.working_dir = new_working_dir
- except DynamipsError as e:
- log.error("could not change working directory: {}".format(e))
- return
-
- self._working_dir = new_working_dir
-
- # apply settings to the hypervisor manager
- for name, value in request.items():
- if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value:
- setattr(self._hypervisor_manager, name, value)
-
- @IModule.route("dynamips.echo")
- def echo(self, request):
- """
- Echo end point for testing purposes.
-
- :param request: JSON request
- """
-
- if request is None:
- self.send_param_error()
- else:
- log.debug("received request {}".format(request))
- self.send_response(request)
-
- def create_nio(self, node, request):
- """
- Creates a new NIO.
-
- :param node: node requesting the NIO
- :param request: the original request with the
- necessary information to create the NIO
-
- :returns: a NIO object
- """
-
- nio = None
- if request["nio"]["type"] == "nio_udp":
- lport = request["nio"]["lport"]
- rhost = request["nio"]["rhost"]
- rport = request["nio"]["rport"]
- try:
- # TODO: handle IPv6
- with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
- sock.connect((rhost, rport))
- except OSError as e:
- raise DynamipsError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
- # check if we have an allocated NIO UDP auto
- nio = node.hypervisor.get_nio_udp_auto(lport)
- if not nio:
- # otherwise create an NIO UDP
- nio = NIO_UDP(node.hypervisor, lport, rhost, rport)
- else:
- nio.connect(rhost, rport)
- elif request["nio"]["type"] == "nio_generic_ethernet":
- ethernet_device = request["nio"]["ethernet_device"]
- if sys.platform.startswith("win"):
- # replace the interface name by the GUID on Windows
- interfaces = get_windows_interfaces()
- npf_interface = None
- for interface in interfaces:
- if interface["name"] == ethernet_device:
- npf_interface = interface["id"]
- if not npf_interface:
- raise DynamipsError("Could not find interface {} on this host".format(ethernet_device))
- else:
- ethernet_device = npf_interface
- nio = NIO_GenericEthernet(node.hypervisor, ethernet_device)
- elif request["nio"]["type"] == "nio_linux_ethernet":
- if sys.platform.startswith("win"):
- raise DynamipsError("This NIO type is not supported on Windows")
- ethernet_device = request["nio"]["ethernet_device"]
- nio = NIO_LinuxEthernet(node.hypervisor, ethernet_device)
- elif request["nio"]["type"] == "nio_tap":
- tap_device = request["nio"]["tap_device"]
- nio = NIO_TAP(node.hypervisor, tap_device)
- elif request["nio"]["type"] == "nio_unix":
- local_file = request["nio"]["local_file"]
- remote_file = request["nio"]["remote_file"]
- nio = NIO_UNIX(node.hypervisor, local_file, remote_file)
- elif request["nio"]["type"] == "nio_vde":
- control_file = request["nio"]["control_file"]
- local_file = request["nio"]["local_file"]
- nio = NIO_VDE(node.hypervisor, control_file, local_file)
- elif request["nio"]["type"] == "nio_null":
- nio = NIO_Null(node.hypervisor)
- return nio
-
- def allocate_udp_port(self, node):
- """
- Allocates a UDP port in order to create an UDP NIO.
-
- :param node: the node that needs to allocate an UDP port
-
- :returns: dictionary with the allocated host/port info
- """
-
- port = node.hypervisor.allocate_udp_port()
- host = node.hypervisor.host
-
- log.info("{} [id={}] has allocated UDP port {} with host {}".format(node.name,
- node.id,
- port,
- host))
- response = {"lport": port}
- return response
-
- def set_ghost_ios(self, router):
- """
- Manages Ghost IOS support.
-
- :param router: Router instance
- """
-
- if not router.mmap:
- raise DynamipsError("mmap support is required to enable ghost IOS support")
-
- ghost_instance = router.formatted_ghost_file()
- all_ghosts = []
-
- # search of an existing ghost instance across all hypervisors
- for hypervisor in self._hypervisor_manager.hypervisors:
- all_ghosts.extend(hypervisor.ghosts)
-
- if ghost_instance not in all_ghosts:
- # create a new ghost IOS instance
- ghost = Router(router.hypervisor, "ghost-" + ghost_instance, router.platform, ghost_flag=True)
- ghost.image = router.image
- # for 7200s, the NPE must be set when using an NPE-G2.
- if router.platform == "c7200":
- ghost.npe = router.npe
- ghost.ghost_status = 1
- ghost.ghost_file = ghost_instance
- ghost.ram = router.ram
- try:
- ghost.start()
- ghost.stop()
- except DynamipsError:
- raise
- finally:
- ghost.clean_delete()
-
- if router.ghost_file != ghost_instance:
- # set the ghost file to the router
- router.ghost_status = 2
- router.ghost_file = ghost_instance
-
- def create_config_from_file(self, local_base_config, router, destination_config_path):
- """
- Creates a config file from a local base config
-
- :param local_base_config: path the a local base config
- :param router: router instance
- :param destination_config_path: path to the destination config file
-
- :returns: relative path to the created config file
- """
-
- log.info("creating config file {} from {}".format(destination_config_path, local_base_config))
- config_path = destination_config_path
- config_dir = os.path.dirname(destination_config_path)
- try:
- os.makedirs(config_dir)
- except FileExistsError:
- pass
- except OSError as e:
- raise DynamipsError("Could not create configs directory: {}".format(e))
-
- try:
- with open(local_base_config, "r", errors="replace") as f:
- config = f.read()
- with open(config_path, "w") as f:
- config = "!\n" + config.replace("\r", "")
- config = config.replace('%h', router.name)
- f.write(config)
- except OSError as e:
- raise DynamipsError("Could not save the configuration from {} to {}: {}".format(local_base_config, config_path, e))
- return "configs" + os.sep + os.path.basename(config_path)
-
- def create_config_from_base64(self, config_base64, router, destination_config_path):
- """
- Creates a config file from a base64 encoded config.
-
- :param config_base64: base64 encoded config
- :param router: router instance
- :param destination_config_path: path to the destination config file
-
- :returns: relative path to the created config file
- """
-
- log.info("creating config file {} from base64".format(destination_config_path))
- config = base64.decodebytes(config_base64.encode("utf-8")).decode("utf-8")
- config = "!\n" + config.replace("\r", "")
- config = config.replace('%h', router.name)
- config_dir = os.path.dirname(destination_config_path)
- try:
- os.makedirs(config_dir)
- except FileExistsError:
- pass
- except OSError as e:
- raise DynamipsError("Could not create configs directory: {}".format(e))
-
- config_path = destination_config_path
- try:
- with open(config_path, "w") as f:
- log.info("saving startup-config to {}".format(config_path))
- f.write(config)
- except OSError as e:
- raise DynamipsError("Could not save the configuration {}: {}".format(config_path, e))
- return "configs" + os.sep + os.path.basename(config_path)
diff --git a/gns3server/old_modules/dynamips/backends/atmsw.py b/gns3server/old_modules/dynamips/backends/atmsw.py
deleted file mode 100644
index 2ce0410b..00000000
--- a/gns3server/old_modules/dynamips/backends/atmsw.py
+++ /dev/null
@@ -1,395 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-import re
-import os
-from gns3server.modules import IModule
-from ..nodes.atm_switch import ATMSwitch
-from ..dynamips_error import DynamipsError
-
-from ..schemas.atmsw import ATMSW_CREATE_SCHEMA
-from ..schemas.atmsw import ATMSW_DELETE_SCHEMA
-from ..schemas.atmsw import ATMSW_UPDATE_SCHEMA
-from ..schemas.atmsw import ATMSW_ALLOCATE_UDP_PORT_SCHEMA
-from ..schemas.atmsw import ATMSW_ADD_NIO_SCHEMA
-from ..schemas.atmsw import ATMSW_DELETE_NIO_SCHEMA
-from ..schemas.atmsw import ATMSW_START_CAPTURE_SCHEMA
-from ..schemas.atmsw import ATMSW_STOP_CAPTURE_SCHEMA
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class ATMSW(object):
-
- @IModule.route("dynamips.atmsw.create")
- def atmsw_create(self, request):
- """
- Creates a new ATM switch.
-
- Mandatory request parameters:
- - name (switch name)
-
- Response parameters:
- - id (switch identifier)
- - name (switch name)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ATMSW_CREATE_SCHEMA):
- return
-
- name = request["name"]
- try:
- if not self._hypervisor_manager:
- self.start_hypervisor_manager()
-
- hypervisor = self._hypervisor_manager.allocate_hypervisor_for_simulated_device()
- atmsw = ATMSwitch(hypervisor, name)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"name": atmsw.name,
- "id": atmsw.id}
-
- self._atm_switches[atmsw.id] = atmsw
- self.send_response(response)
-
- @IModule.route("dynamips.atmsw.delete")
- def atmsw_delete(self, request):
- """
- Deletes a ATM switch.
-
- Mandatory request parameters:
- - id (switch identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ATMSW_DELETE_SCHEMA):
- return
-
- # get the ATM switch instance
- atmsw_id = request["id"]
- atmsw = self.get_device_instance(atmsw_id, self._atm_switches)
- if not atmsw:
- return
-
- try:
- atmsw.delete()
- self._hypervisor_manager.unallocate_hypervisor_for_simulated_device(atmsw)
- del self._atm_switches[atmsw_id]
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
- self.send_response(True)
-
- @IModule.route("dynamips.atmsw.update")
- def atmsw_update(self, request):
- """
- Updates a ATM switch.
-
- Mandatory request parameters:
- - id (switch identifier)
-
- Optional request parameters:
- - name (new switch name)
-
- Response parameters:
- - name if changed
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ATMSW_UPDATE_SCHEMA):
- return
-
- # get the ATM switch instance
- atmsw = self.get_device_instance(request["id"], self._atm_switches)
- if not atmsw:
- return
-
- response = {}
- # rename the switch if requested
- if "name" in request and atmsw.name != request["name"]:
- try:
- atmsw.name = request["name"]
- response["name"] = atmsw.name
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(response)
-
- @IModule.route("dynamips.atmsw.allocate_udp_port")
- def atmsw_allocate_udp_port(self, request):
- """
- Allocates a UDP port in order to create an UDP NIO for an
- ATM switch.
-
- Mandatory request parameters:
- - id (switch identifier)
- - port_id (port identifier)
-
- Response parameters:
- - port_id (port identifier)
- - lport (allocated local port)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ATMSW_ALLOCATE_UDP_PORT_SCHEMA):
- return
-
- # get the ATM switch instance
- atmsw = self.get_device_instance(request["id"], self._atm_switches)
- if not atmsw:
- return
-
- try:
- # allocate a new UDP port
- response = self.allocate_udp_port(atmsw)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response["port_id"] = request["port_id"]
- self.send_response(response)
-
- @IModule.route("dynamips.atmsw.add_nio")
- def atmsw_add_nio(self, request):
- """
- Adds an NIO (Network Input/Output) for an ATM switch.
-
- Mandatory request parameters:
- - id (switch identifier)
- - port (port identifier)
- - port_id (port identifier)
- - mappings (VCs/VPs mapped to the port)
- - nio (one of the following)
- - type "nio_udp"
- - lport (local port)
- - rhost (remote host)
- - rport (remote port)
- - type "nio_generic_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_linux_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_tap"
- - tap_device (TAP device name e.g. tap0)
- - type "nio_unix"
- - local_file (path to UNIX socket file)
- - remote_file (path to UNIX socket file)
- - type "nio_vde"
- - control_file (path to VDE control file)
- - local_file (path to VDE local file)
- - type "nio_null"
-
- Response parameters:
- - port_id (unique port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ATMSW_ADD_NIO_SCHEMA):
- return
-
- # get the ATM switch instance
- atmsw = self.get_device_instance(request["id"], self._atm_switches)
- if not atmsw:
- return
-
- port = request["port"]
- mappings = request["mappings"]
-
- try:
- nio = self.create_nio(atmsw, request)
- if not nio:
- raise DynamipsError("Requested NIO doesn't exist: {}".format(request["nio"]))
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- try:
- atmsw.add_nio(nio, port)
- pvc_entry = re.compile(r"""^([0-9]*):([0-9]*):([0-9]*)$""")
- for source, destination in mappings.items():
- match_source_pvc = pvc_entry.search(source)
- match_destination_pvc = pvc_entry.search(destination)
- if match_source_pvc and match_destination_pvc:
- # add the virtual channels mapped with this port/nio
- source_port, source_vpi, source_vci = map(int, match_source_pvc.group(1, 2, 3))
- destination_port, destination_vpi, destination_vci = map(int, match_destination_pvc.group(1, 2, 3))
- if atmsw.has_port(destination_port):
- if (source_port, source_vpi, source_vci) not in atmsw.mapping and \
- (destination_port, destination_vpi, destination_vci) not in atmsw.mapping:
- atmsw.map_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci)
- atmsw.map_pvc(destination_port, destination_vpi, destination_vci, source_port, source_vpi, source_vci)
- else:
- # add the virtual paths mapped with this port/nio
- source_port, source_vpi = map(int, source.split(':'))
- destination_port, destination_vpi = map(int, destination.split(':'))
- if atmsw.has_port(destination_port):
- if (source_port, source_vpi) not in atmsw.mapping and (destination_port, destination_vpi) not in atmsw.mapping:
- atmsw.map_vp(source_port, source_vpi, destination_port, destination_vpi)
- atmsw.map_vp(destination_port, destination_vpi, source_port, source_vpi)
-
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response({"port_id": request["port_id"]})
-
- @IModule.route("dynamips.atmsw.delete_nio")
- def atmsw_delete_nio(self, request):
- """
- Deletes an NIO (Network Input/Output).
-
- Mandatory request parameters:
- - id (switch identifier)
- - port (port identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ATMSW_DELETE_NIO_SCHEMA):
- return
-
- # get the ATM switch instance
- atmsw = self.get_device_instance(request["id"], self._atm_switches)
- if not atmsw:
- return
-
- port = request["port"]
- try:
- for source, destination in atmsw.mapping.copy().items():
- if len(source) == 3 and len(destination) == 3:
- # remove the virtual channels mapped with this port/nio
- source_port, source_vpi, source_vci = source
- destination_port, destination_vpi, destination_vci = destination
- if port == source_port:
- atmsw.unmap_pvc(source_port, source_vpi, source_vci, destination_port, destination_vpi, destination_vci)
- atmsw.unmap_pvc(destination_port, destination_vpi, destination_vci, source_port, source_vpi, source_vci)
- else:
- # remove the virtual paths mapped with this port/nio
- source_port, source_vpi = source
- destination_port, destination_vpi = destination
- if port == source_port:
- atmsw.unmap_vp(source_port, source_vpi, destination_port, destination_vpi)
- atmsw.unmap_vp(destination_port, destination_vpi, source_port, source_vpi)
-
- nio = atmsw.remove_nio(port)
- nio.delete()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("dynamips.atmsw.start_capture")
- def atmsw_start_capture(self, request):
- """
- Starts a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port (port identifier)
- - port_id (port identifier)
- - capture_file_name
-
- Optional request parameters:
- - data_link_type (PCAP DLT_* value)
-
- Response parameters:
- - port_id (port identifier)
- - capture_file_path (path to the capture file)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ATMSW_START_CAPTURE_SCHEMA):
- return
-
- # get the ATM switch instance
- atmsw = self.get_device_instance(request["id"], self._atm_switches)
- if not atmsw:
- return
-
- port = request["port"]
- capture_file_name = request["capture_file_name"]
- data_link_type = request.get("data_link_type")
-
- try:
- capture_file_path = os.path.join(atmsw.hypervisor.working_dir, "captures", capture_file_name)
- atmsw.start_capture(port, capture_file_path, data_link_type)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"],
- "capture_file_path": capture_file_path}
- self.send_response(response)
-
- @IModule.route("dynamips.atmsw.stop_capture")
- def atmsw_stop_capture(self, request):
- """
- Stops a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port_id (port identifier)
- - port (port number)
-
- Response parameters:
- - port_id (port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ATMSW_STOP_CAPTURE_SCHEMA):
- return
-
- # get the ATM switch instance
- atmsw = self.get_device_instance(request["id"], self._atm_switches)
- if not atmsw:
- return
-
- port = request["port"]
- try:
- atmsw.stop_capture(port)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"]}
- self.send_response(response)
diff --git a/gns3server/old_modules/dynamips/backends/ethhub.py b/gns3server/old_modules/dynamips/backends/ethhub.py
deleted file mode 100644
index 97c9df7f..00000000
--- a/gns3server/old_modules/dynamips/backends/ethhub.py
+++ /dev/null
@@ -1,353 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-import os
-from gns3server.modules import IModule
-from ..nodes.hub import Hub
-from ..dynamips_error import DynamipsError
-
-from ..schemas.ethhub import ETHHUB_CREATE_SCHEMA
-from ..schemas.ethhub import ETHHUB_DELETE_SCHEMA
-from ..schemas.ethhub import ETHHUB_UPDATE_SCHEMA
-from ..schemas.ethhub import ETHHUB_ALLOCATE_UDP_PORT_SCHEMA
-from ..schemas.ethhub import ETHHUB_ADD_NIO_SCHEMA
-from ..schemas.ethhub import ETHHUB_DELETE_NIO_SCHEMA
-from ..schemas.ethhub import ETHHUB_START_CAPTURE_SCHEMA
-from ..schemas.ethhub import ETHHUB_STOP_CAPTURE_SCHEMA
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class ETHHUB(object):
-
- @IModule.route("dynamips.ethhub.create")
- def ethhub_create(self, request):
- """
- Creates a new Ethernet hub.
-
- Mandatory request parameters:
- - name (hub name)
-
- Response parameters:
- - id (hub identifier)
- - name (hub name)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHHUB_CREATE_SCHEMA):
- return
-
- name = request["name"]
- try:
- if not self._hypervisor_manager:
- self.start_hypervisor_manager()
-
- hypervisor = self._hypervisor_manager.allocate_hypervisor_for_simulated_device()
- ethhub = Hub(hypervisor, name)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"name": ethhub.name,
- "id": ethhub.id}
-
- self._ethernet_hubs[ethhub.id] = ethhub
- self.send_response(response)
-
- @IModule.route("dynamips.ethhub.delete")
- def ethhub_delete(self, request):
- """
- Deletes a Ethernet hub.
-
- Mandatory request parameters:
- - id (hub identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHHUB_DELETE_SCHEMA):
- return
-
- # get the Ethernet hub instance
- ethhub_id = request["id"]
- ethhub = self.get_device_instance(ethhub_id, self._ethernet_hubs)
- if not ethhub:
- return
-
- try:
- ethhub.delete()
- self._hypervisor_manager.unallocate_hypervisor_for_simulated_device(ethhub)
- del self._ethernet_hubs[ethhub_id]
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
- self.send_response(request)
-
- @IModule.route("dynamips.ethhub.update")
- def ethhub_update(self, request):
- """
- Updates a Ethernet hub.
-
- Mandatory request parameters:
- - id (hub identifier)
-
- Optional request parameters:
- - name (new hub name)
-
- Response parameters:
- - name if changed
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHHUB_UPDATE_SCHEMA):
- return
-
- # get the Ethernet hub instance
- ethhub = self.get_device_instance(request["id"], self._ethernet_hubs)
- if not ethhub:
- return
-
- response = {}
- # rename the hub if requested
- if "name" in request and ethhub.name != request["name"]:
- try:
- ethhub.name = request["name"]
- response["name"] = ethhub.name
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(request)
-
- @IModule.route("dynamips.ethhub.allocate_udp_port")
- def ethhub_allocate_udp_port(self, request):
- """
- Allocates a UDP port in order to create an UDP NIO for an
- Ethernet hub.
-
- Mandatory request parameters:
- - id (hub identifier)
- - port_id (port identifier)
-
- Response parameters:
- - port_id (port identifier)
- - lport (allocated local port)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHHUB_ALLOCATE_UDP_PORT_SCHEMA):
- return
-
- # get the Ethernet hub instance
- ethhub = self.get_device_instance(request["id"], self._ethernet_hubs)
- if not ethhub:
- return
-
- try:
- # allocate a new UDP port
- response = self.allocate_udp_port(ethhub)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response["port_id"] = request["port_id"]
- self.send_response(response)
-
- @IModule.route("dynamips.ethhub.add_nio")
- def ethhub_add_nio(self, request):
- """
- Adds an NIO (Network Input/Output) for an Ethernet hub.
-
- Mandatory request parameters:
- - id (hub identifier)
- - port (port identifier)
- - port_id (port identifier)
- - nio (one of the following)
- - type "nio_udp"
- - lport (local port)
- - rhost (remote host)
- - rport (remote port)
- - type "nio_generic_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_linux_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_tap"
- - tap_device (TAP device name e.g. tap0)
- - type "nio_unix"
- - local_file (path to UNIX socket file)
- - remote_file (path to UNIX socket file)
- - type "nio_vde"
- - control_file (path to VDE control file)
- - local_file (path to VDE local file)
- - type "nio_null"
-
- Response parameters:
- - port_id (unique port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHHUB_ADD_NIO_SCHEMA):
- return
-
- # get the Ethernet hub instance
- ethhub = self.get_device_instance(request["id"], self._ethernet_hubs)
- if not ethhub:
- return
-
- port = request["port"]
- try:
- nio = self.create_nio(ethhub, request)
- if not nio:
- raise DynamipsError("Requested NIO doesn't exist: {}".format(request["nio"]))
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- try:
- ethhub.add_nio(nio, port)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response({"port_id": request["port_id"]})
-
- @IModule.route("dynamips.ethhub.delete_nio")
- def ethhub_delete_nio(self, request):
- """
- Deletes an NIO (Network Input/Output).
-
- Mandatory request parameters:
- - id (hub identifier)
- - port (port identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHHUB_DELETE_NIO_SCHEMA):
- return
-
- # get the Ethernet hub instance
- ethhub = self.get_device_instance(request["id"], self._ethernet_hubs)
- if not ethhub:
- return
-
- port = request["port"]
- try:
- nio = ethhub.remove_nio(port)
- nio.delete()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("dynamips.ethhub.start_capture")
- def ethhub_start_capture(self, request):
- """
- Starts a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port (port identifier)
- - port_id (port identifier)
- - capture_file_name
-
- Optional request parameters:
- - data_link_type (PCAP DLT_* value)
-
- Response parameters:
- - port_id (port identifier)
- - capture_file_path (path to the capture file)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHHUB_START_CAPTURE_SCHEMA):
- return
-
- # get the Ethernet hub instance
- ethhub = self.get_device_instance(request["id"], self._ethernet_hubs)
- if not ethhub:
- return
-
- port = request["port"]
- capture_file_name = request["capture_file_name"]
- data_link_type = request.get("data_link_type")
-
- try:
- capture_file_path = os.path.join(ethhub.hypervisor.working_dir, "captures", capture_file_name)
- ethhub.start_capture(port, capture_file_path, data_link_type)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"],
- "capture_file_path": capture_file_path}
- self.send_response(response)
-
- @IModule.route("dynamips.ethhub.stop_capture")
- def ethhub_stop_capture(self, request):
- """
- Stops a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port_id (port identifier)
- - port (port number)
-
- Response parameters:
- - port_id (port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHHUB_STOP_CAPTURE_SCHEMA):
- return
-
- # get the Ethernet hub instance
- ethhub = self.get_device_instance(request["id"], self._ethernet_hubs)
- if not ethhub:
- return
-
- port = request["port"]
- try:
- ethhub.stop_capture(port)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"]}
- self.send_response(response)
diff --git a/gns3server/old_modules/dynamips/backends/ethsw.py b/gns3server/old_modules/dynamips/backends/ethsw.py
deleted file mode 100644
index e251e158..00000000
--- a/gns3server/old_modules/dynamips/backends/ethsw.py
+++ /dev/null
@@ -1,382 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-import os
-from gns3server.modules import IModule
-from ..nodes.ethernet_switch import EthernetSwitch
-from ..dynamips_error import DynamipsError
-
-from ..schemas.ethsw import ETHSW_CREATE_SCHEMA
-from ..schemas.ethsw import ETHSW_DELETE_SCHEMA
-from ..schemas.ethsw import ETHSW_UPDATE_SCHEMA
-from ..schemas.ethsw import ETHSW_ALLOCATE_UDP_PORT_SCHEMA
-from ..schemas.ethsw import ETHSW_ADD_NIO_SCHEMA
-from ..schemas.ethsw import ETHSW_DELETE_NIO_SCHEMA
-from ..schemas.ethsw import ETHSW_START_CAPTURE_SCHEMA
-from ..schemas.ethsw import ETHSW_STOP_CAPTURE_SCHEMA
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class ETHSW(object):
-
- @IModule.route("dynamips.ethsw.create")
- def ethsw_create(self, request):
- """
- Creates a new Ethernet switch.
-
- Mandatory request parameters:
- - name (switch name)
-
- Response parameters:
- - id (switch identifier)
- - name (switch name)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHSW_CREATE_SCHEMA):
- return
-
- name = request["name"]
- try:
- if not self._hypervisor_manager:
- self.start_hypervisor_manager()
-
- hypervisor = self._hypervisor_manager.allocate_hypervisor_for_simulated_device()
- ethsw = EthernetSwitch(hypervisor, name)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"name": ethsw.name,
- "id": ethsw.id}
-
- self._ethernet_switches[ethsw.id] = ethsw
- self.send_response(response)
-
- @IModule.route("dynamips.ethsw.delete")
- def ethsw_delete(self, request):
- """
- Deletes a Ethernet switch.
-
- Mandatory request parameters:
- - id (switch identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHSW_DELETE_SCHEMA):
- return
-
- # get the Ethernet switch instance
- ethsw_id = request["id"]
- ethsw = self.get_device_instance(ethsw_id, self._ethernet_switches)
- if not ethsw:
- return
-
- try:
- ethsw.delete()
- self._hypervisor_manager.unallocate_hypervisor_for_simulated_device(ethsw)
- del self._ethernet_switches[ethsw_id]
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
- self.send_response(True)
-
- @IModule.route("dynamips.ethsw.update")
- def ethsw_update(self, request):
- """
- Updates a Ethernet switch.
-
- Mandatory request parameters:
- - id (switch identifier)
-
- Optional request parameters:
- - name (new switch name)
- - ports (ports settings)
-
- Response parameters:
- - name if changed
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHSW_UPDATE_SCHEMA):
- return
-
- # get the Ethernet switch instance
- ethsw = self.get_device_instance(request["id"], self._ethernet_switches)
- if not ethsw:
- return
-
- if "ports" in request:
- ports = request["ports"]
-
- # update the port settings
- for port, info in ports.items():
- vlan = info["vlan"]
- port_type = info["type"]
- try:
- if port_type == "access":
- ethsw.set_access_port(int(port), vlan)
- elif port_type == "dot1q":
- ethsw.set_dot1q_port(int(port), vlan)
- elif port_type == "qinq":
- ethsw.set_qinq_port(int(port), vlan)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {}
- # rename the switch if requested
- if "name" in request and ethsw.name != request["name"]:
- try:
- ethsw.name = request["name"]
- response["name"] = ethsw.name
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(response)
-
- @IModule.route("dynamips.ethsw.allocate_udp_port")
- def ethsw_allocate_udp_port(self, request):
- """
- Allocates a UDP port in order to create an UDP NIO for an
- Ethernet switch.
-
- Mandatory request parameters:
- - id (switch identifier)
- - port_id (port identifier)
-
- Response parameters:
- - port_id (port identifier)
- - lport (allocated local port)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHSW_ALLOCATE_UDP_PORT_SCHEMA):
- return
-
- # get the Ethernet switch instance
- ethsw = self.get_device_instance(request["id"], self._ethernet_switches)
- if not ethsw:
- return
-
- try:
- # allocate a new UDP port
- response = self.allocate_udp_port(ethsw)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response["port_id"] = request["port_id"]
- self.send_response(response)
-
- @IModule.route("dynamips.ethsw.add_nio")
- def ethsw_add_nio(self, request):
- """
- Adds an NIO (Network Input/Output) for an Ethernet switch.
-
- Mandatory request parameters:
- - id (switch identifier)
- - port (port identifier)
- - port_id (port identifier)
- - vlan (vlan identifier)
- - port_type ("access", "dot1q" or "qinq")
- - nio (one of the following)
- - type "nio_udp"
- - lport (local port)
- - rhost (remote host)
- - rport (remote port)
- - type "nio_generic_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_linux_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_tap"
- - tap_device (TAP device name e.g. tap0)
- - type "nio_unix"
- - local_file (path to UNIX socket file)
- - remote_file (path to UNIX socket file)
- - type "nio_vde"
- - control_file (path to VDE control file)
- - local_file (path to VDE local file)
- - type "nio_null"
-
- Response parameters:
- - port_id (unique port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHSW_ADD_NIO_SCHEMA):
- return
-
- # get the Ethernet switch instance
- ethsw = self.get_device_instance(request["id"], self._ethernet_switches)
- if not ethsw:
- return
-
- port = request["port"]
- vlan = request["vlan"]
- port_type = request["port_type"]
- try:
- nio = self.create_nio(ethsw, request)
- if not nio:
- raise DynamipsError("Requested NIO doesn't exist: {}".format(request["nio"]))
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- try:
- ethsw.add_nio(nio, port)
- if port_type == "access":
- ethsw.set_access_port(port, vlan)
- elif port_type == "dot1q":
- ethsw.set_dot1q_port(port, vlan)
- elif port_type == "qinq":
- ethsw.set_qinq_port(port, vlan)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response({"port_id": request["port_id"]})
-
- @IModule.route("dynamips.ethsw.delete_nio")
- def ethsw_delete_nio(self, request):
- """
- Deletes an NIO (Network Input/Output).
-
- Mandatory request parameters:
- - id (switch identifier)
- - port (port identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHSW_DELETE_NIO_SCHEMA):
- return
-
- # get the Ethernet switch instance
- ethsw = self.get_device_instance(request["id"], self._ethernet_switches)
- if not ethsw:
- return
-
- port = request["port"]
- try:
- nio = ethsw.remove_nio(port)
- nio.delete()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("dynamips.ethsw.start_capture")
- def ethsw_start_capture(self, request):
- """
- Starts a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port (port identifier)
- - port_id (port identifier)
- - capture_file_name
-
- Optional request parameters:
- - data_link_type (PCAP DLT_* value)
-
- Response parameters:
- - port_id (port identifier)
- - capture_file_path (path to the capture file)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHSW_START_CAPTURE_SCHEMA):
- return
-
- # get the Ethernet switch instance
- ethsw = self.get_device_instance(request["id"], self._ethernet_switches)
- if not ethsw:
- return
-
- port = request["port"]
- capture_file_name = request["capture_file_name"]
- data_link_type = request.get("data_link_type")
-
- try:
- capture_file_path = os.path.join(ethsw.hypervisor.working_dir, "captures", capture_file_name)
- ethsw.start_capture(port, capture_file_path, data_link_type)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"],
- "capture_file_path": capture_file_path}
- self.send_response(response)
-
- @IModule.route("dynamips.ethsw.stop_capture")
- def ethsw_stop_capture(self, request):
- """
- Stops a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port_id (port identifier)
- - port (port number)
-
- Response parameters:
- - port_id (port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, ETHSW_STOP_CAPTURE_SCHEMA):
- return
-
- # get the Ethernet switch instance
- ethsw = self.get_device_instance(request["id"], self._ethernet_switches)
- if not ethsw:
- return
-
- port = request["port"]
- try:
- ethsw.stop_capture(port)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"]}
- self.send_response(response)
diff --git a/gns3server/old_modules/dynamips/backends/frsw.py b/gns3server/old_modules/dynamips/backends/frsw.py
deleted file mode 100644
index ed63f501..00000000
--- a/gns3server/old_modules/dynamips/backends/frsw.py
+++ /dev/null
@@ -1,374 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-import os
-from gns3server.modules import IModule
-from ..nodes.frame_relay_switch import FrameRelaySwitch
-from ..dynamips_error import DynamipsError
-
-from ..schemas.frsw import FRSW_CREATE_SCHEMA
-from ..schemas.frsw import FRSW_DELETE_SCHEMA
-from ..schemas.frsw import FRSW_UPDATE_SCHEMA
-from ..schemas.frsw import FRSW_ALLOCATE_UDP_PORT_SCHEMA
-from ..schemas.frsw import FRSW_ADD_NIO_SCHEMA
-from ..schemas.frsw import FRSW_DELETE_NIO_SCHEMA
-from ..schemas.frsw import FRSW_START_CAPTURE_SCHEMA
-from ..schemas.frsw import FRSW_STOP_CAPTURE_SCHEMA
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class FRSW(object):
-
- @IModule.route("dynamips.frsw.create")
- def frsw_create(self, request):
- """
- Creates a new Frame-Relay switch.
-
- Mandatory request parameters:
- - name (switch name)
-
- Response parameters:
- - id (switch identifier)
- - name (switch name)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, FRSW_CREATE_SCHEMA):
- return
-
- name = request["name"]
- try:
- if not self._hypervisor_manager:
- self.start_hypervisor_manager()
-
- hypervisor = self._hypervisor_manager.allocate_hypervisor_for_simulated_device()
- frsw = FrameRelaySwitch(hypervisor, name)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"name": frsw.name,
- "id": frsw.id}
-
- self._frame_relay_switches[frsw.id] = frsw
- self.send_response(response)
-
- @IModule.route("dynamips.frsw.delete")
- def frsw_delete(self, request):
- """
- Deletes a Frame Relay switch.
-
- Mandatory request parameters:
- - id (switch identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, FRSW_DELETE_SCHEMA):
- return
-
- # get the Frame relay switch instance
- frsw_id = request["id"]
- frsw = self.get_device_instance(frsw_id, self._frame_relay_switches)
- if not frsw:
- return
-
- try:
- frsw.delete()
- self._hypervisor_manager.unallocate_hypervisor_for_simulated_device(frsw)
- del self._frame_relay_switches[frsw_id]
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("dynamips.frsw.update")
- def frsw_update(self, request):
- """
- Updates a Frame Relay switch.
-
- Mandatory request parameters:
- - id (switch identifier)
-
- Optional request parameters:
- - name (new switch name)
-
- Response parameters:
- - name if updated
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, FRSW_UPDATE_SCHEMA):
- return
-
- # get the Frame relay switch instance
- frsw = self.get_device_instance(request["id"], self._frame_relay_switches)
- if not frsw:
- return
-
- response = {}
- # rename the switch if requested
- if "name" in request and frsw.name != request["name"]:
- try:
- frsw.name = request["name"]
- response["name"] = frsw.name
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(request)
-
- @IModule.route("dynamips.frsw.allocate_udp_port")
- def frsw_allocate_udp_port(self, request):
- """
- Allocates a UDP port in order to create an UDP NIO for an
- Frame Relay switch.
-
- Mandatory request parameters:
- - id (switch identifier)
- - port_id (port identifier)
-
- Response parameters:
- - port_id (port identifier)
- - lport (allocated local port)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, FRSW_ALLOCATE_UDP_PORT_SCHEMA):
- return
-
- # get the Frame relay switch instance
- frsw = self.get_device_instance(request["id"], self._frame_relay_switches)
- if not frsw:
- return
-
- try:
- # allocate a new UDP port
- response = self.allocate_udp_port(frsw)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response["port_id"] = request["port_id"]
- self.send_response(response)
-
- @IModule.route("dynamips.frsw.add_nio")
- def frsw_add_nio(self, request):
- """
- Adds an NIO (Network Input/Output) for an Frame-Relay switch.
-
- Mandatory request parameters:
- - id (switch identifier)
- - port (port identifier)
- - port_id (port identifier)
- - mappings (VCs mapped to the port)
- - nio (one of the following)
- - type "nio_udp"
- - lport (local port)
- - rhost (remote host)
- - rport (remote port)
- - type "nio_generic_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_linux_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_tap"
- - tap_device (TAP device name e.g. tap0)
- - type "nio_unix"
- - local_file (path to UNIX socket file)
- - remote_file (path to UNIX socket file)
- - type "nio_vde"
- - control_file (path to VDE control file)
- - local_file (path to VDE local file)
- - type "nio_null"
-
- Response parameters:
- - port_id (unique port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, FRSW_ADD_NIO_SCHEMA):
- return
-
- # get the Frame relay switch instance
- frsw = self.get_device_instance(request["id"], self._frame_relay_switches)
- if not frsw:
- return
-
- port = request["port"]
- mappings = request["mappings"]
-
- try:
- nio = self.create_nio(frsw, request)
- if not nio:
- raise DynamipsError("Requested NIO doesn't exist: {}".format(request["nio"]))
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- try:
- frsw.add_nio(nio, port)
-
- # add the VCs mapped with this port/nio
- for source, destination in mappings.items():
- source_port, source_dlci = map(int, source.split(':'))
- destination_port, destination_dlci = map(int, destination.split(':'))
- if frsw.has_port(destination_port):
- if (source_port, source_dlci) not in frsw.mapping and (destination_port, destination_dlci) not in frsw.mapping:
- frsw.map_vc(source_port, source_dlci, destination_port, destination_dlci)
- frsw.map_vc(destination_port, destination_dlci, source_port, source_dlci)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response({"port_id": request["port_id"]})
-
- @IModule.route("dynamips.frsw.delete_nio")
- def frsw_delete_nio(self, request):
- """
- Deletes an NIO (Network Input/Output).
-
- Mandatory request parameters:
- - id (switch identifier)
- - port (port identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, FRSW_DELETE_NIO_SCHEMA):
- return
-
- # get the Frame relay switch instance
- frsw = self.get_device_instance(request["id"], self._frame_relay_switches)
- if not frsw:
- return
-
- port = request["port"]
- try:
- # remove the VCs mapped with this port/nio
- for source, destination in frsw.mapping.copy().items():
- source_port, source_dlci = source
- destination_port, destination_dlci = destination
- if port == source_port:
- frsw.unmap_vc(source_port, source_dlci, destination_port, destination_dlci)
- frsw.unmap_vc(destination_port, destination_dlci, source_port, source_dlci)
-
- nio = frsw.remove_nio(port)
- nio.delete()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("dynamips.frsw.start_capture")
- def frsw_start_capture(self, request):
- """
- Starts a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port (port identifier)
- - port_id (port identifier)
- - capture_file_name
-
- Optional request parameters:
- - data_link_type (PCAP DLT_* value)
-
- Response parameters:
- - port_id (port identifier)
- - capture_file_path (path to the capture file)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, FRSW_START_CAPTURE_SCHEMA):
- return
-
- # get the Frame relay switch instance
- frsw = self.get_device_instance(request["id"], self._frame_relay_switches)
- if not frsw:
- return
-
- port = request["port"]
- capture_file_name = request["capture_file_name"]
- data_link_type = request.get("data_link_type")
-
- try:
- capture_file_path = os.path.join(frsw.hypervisor.working_dir, "captures", capture_file_name)
- frsw.start_capture(port, capture_file_path, data_link_type)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"],
- "capture_file_path": capture_file_path}
- self.send_response(response)
-
- @IModule.route("dynamips.frsw.stop_capture")
- def frsw_stop_capture(self, request):
- """
- Stops a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port_id (port identifier)
- - port (port number)
-
- Response parameters:
- - port_id (port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, FRSW_STOP_CAPTURE_SCHEMA):
- return
-
- # get the Frame relay switch instance
- frsw = self.get_device_instance(request["id"], self._frame_relay_switches)
- if not frsw:
- return
-
- port = request["port"]
- try:
- frsw.stop_capture(port)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"]}
- self.send_response(response)
diff --git a/gns3server/old_modules/dynamips/backends/vm.py b/gns3server/old_modules/dynamips/backends/vm.py
deleted file mode 100644
index e40e79d6..00000000
--- a/gns3server/old_modules/dynamips/backends/vm.py
+++ /dev/null
@@ -1,905 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-import os
-import ntpath
-import time
-from gns3server.modules import IModule
-from gns3dms.cloud.rackspace_ctrl import get_provider
-from ..dynamips_error import DynamipsError
-
-from ..nodes.c1700 import C1700
-from ..nodes.c2600 import C2600
-from ..nodes.c2691 import C2691
-from ..nodes.c3600 import C3600
-from ..nodes.c3725 import C3725
-from ..nodes.c3745 import C3745
-from ..nodes.c7200 import C7200
-
-from ..adapters.c7200_io_2fe import C7200_IO_2FE
-from ..adapters.c7200_io_fe import C7200_IO_FE
-from ..adapters.c7200_io_ge_e import C7200_IO_GE_E
-from ..adapters.nm_16esw import NM_16ESW
-from ..adapters.nm_1e import NM_1E
-from ..adapters.nm_1fe_tx import NM_1FE_TX
-from ..adapters.nm_4e import NM_4E
-from ..adapters.nm_4t import NM_4T
-from ..adapters.pa_2fe_tx import PA_2FE_TX
-from ..adapters.pa_4e import PA_4E
-from ..adapters.pa_4t import PA_4T
-from ..adapters.pa_8e import PA_8E
-from ..adapters.pa_8t import PA_8T
-from ..adapters.pa_a1 import PA_A1
-from ..adapters.pa_fe_tx import PA_FE_TX
-from ..adapters.pa_ge import PA_GE
-from ..adapters.pa_pos_oc3 import PA_POS_OC3
-from ..adapters.wic_1enet import WIC_1ENET
-from ..adapters.wic_1t import WIC_1T
-from ..adapters.wic_2t import WIC_2T
-
-from ..schemas.vm import VM_CREATE_SCHEMA
-from ..schemas.vm import VM_DELETE_SCHEMA
-from ..schemas.vm import VM_START_SCHEMA
-from ..schemas.vm import VM_STOP_SCHEMA
-from ..schemas.vm import VM_SUSPEND_SCHEMA
-from ..schemas.vm import VM_RELOAD_SCHEMA
-from ..schemas.vm import VM_UPDATE_SCHEMA
-from ..schemas.vm import VM_START_CAPTURE_SCHEMA
-from ..schemas.vm import VM_STOP_CAPTURE_SCHEMA
-from ..schemas.vm import VM_SAVE_CONFIG_SCHEMA
-from ..schemas.vm import VM_EXPORT_CONFIG_SCHEMA
-from ..schemas.vm import VM_IDLEPCS_SCHEMA
-from ..schemas.vm import VM_AUTO_IDLEPC_SCHEMA
-from ..schemas.vm import VM_ALLOCATE_UDP_PORT_SCHEMA
-from ..schemas.vm import VM_ADD_NIO_SCHEMA
-from ..schemas.vm import VM_DELETE_NIO_SCHEMA
-
-import logging
-log = logging.getLogger(__name__)
-
-
-ADAPTER_MATRIX = {"C7200-IO-2FE": C7200_IO_2FE,
- "C7200-IO-FE": C7200_IO_FE,
- "C7200-IO-GE-E": C7200_IO_GE_E,
- "NM-16ESW": NM_16ESW,
- "NM-1E": NM_1E,
- "NM-1FE-TX": NM_1FE_TX,
- "NM-4E": NM_4E,
- "NM-4T": NM_4T,
- "PA-2FE-TX": PA_2FE_TX,
- "PA-4E": PA_4E,
- "PA-4T+": PA_4T,
- "PA-8E": PA_8E,
- "PA-8T": PA_8T,
- "PA-A1": PA_A1,
- "PA-FE-TX": PA_FE_TX,
- "PA-GE": PA_GE,
- "PA-POS-OC3": PA_POS_OC3}
-
-WIC_MATRIX = {"WIC-1ENET": WIC_1ENET,
- "WIC-1T": WIC_1T,
- "WIC-2T": WIC_2T}
-
-PLATFORMS = {'c1700': C1700,
- 'c2600': C2600,
- 'c2691': C2691,
- 'c3725': C3725,
- 'c3745': C3745,
- 'c3600': C3600,
- 'c7200': C7200}
-
-
-class VM(object):
-
- @IModule.route("dynamips.vm.create")
- def vm_create(self, request):
- """
- Creates a new VM (router).
-
- Mandatory request parameters:
- - name (vm name)
- - platform (platform name e.g. c7200)
- - image (path to IOS image)
- - ram (amount of RAM in MB)
-
- Optional request parameters:
- - console (console port number)
- - aux (auxiliary console port number)
- - mac_addr (MAC address)
- - chassis (router chassis model)
-
- Response parameters:
- - id (vm identifier)
- - name (vm name)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_CREATE_SCHEMA):
- return
-
- name = request["name"]
- platform = request["platform"]
- image = request["image"]
- ram = request["ram"]
- hypervisor = None
- chassis = request.get("chassis")
- router_id = request.get("router_id")
-
- # Locate the image
- updated_image_path = os.path.join(self.images_directory, image)
- if os.path.isfile(updated_image_path):
- image = updated_image_path
- else:
- if not os.path.exists(self.images_directory):
- os.mkdir(self.images_directory)
- cloud_path = request.get("cloud_path", None)
- if cloud_path is not None:
- # Download the image from cloud files
- _, filename = ntpath.split(image)
- src = '{}/{}'.format(cloud_path, filename)
- provider = get_provider(self._cloud_settings)
- log.debug("Downloading file from {} to {}...".format(src, updated_image_path))
- provider.download_file(src, updated_image_path)
- log.debug("Download of {} complete.".format(src))
- image = updated_image_path
-
- try:
- if platform not in PLATFORMS:
- raise DynamipsError("Unknown router platform: {}".format(platform))
-
- if not self._hypervisor_manager:
- self.start_hypervisor_manager()
-
- hypervisor = self._hypervisor_manager.allocate_hypervisor_for_router(image, ram)
-
- if chassis:
- router = PLATFORMS[platform](hypervisor, name, router_id, chassis=chassis)
- elif platform == "c7200" and os.path.basename(image).lower().startswith("c7200p"):
- router = PLATFORMS[platform](hypervisor, name, router_id, npe="npe-g2")
- else:
- router = PLATFORMS[platform](hypervisor, name, router_id)
- router.ram = ram
- router.image = image
- if platform not in ("c1700", "c2600"):
- router.sparsemem = self._hypervisor_manager.sparse_memory_support
- router.mmap = self._hypervisor_manager.mmap_support
- if "console" in request:
- router.console = request["console"]
- if "aux" in request:
- router.aux = request["aux"]
- if "mac_addr" in request:
- router.mac_addr = request["mac_addr"]
-
- # JIT sharing support
- if self._hypervisor_manager.jit_sharing_support:
- jitsharing_groups = hypervisor.jitsharing_groups
- ios_image = os.path.basename(image)
- if ios_image in jitsharing_groups:
- router.jit_sharing_group = jitsharing_groups[ios_image]
- else:
- new_jit_group = -1
- for jit_group in range(0, 127):
- if jit_group not in jitsharing_groups.values():
- new_jit_group = jit_group
- break
- if new_jit_group == -1:
- raise DynamipsError("All JIT groups are allocated!")
- router.jit_sharing_group = new_jit_group
-
- # Ghost IOS support
- if self._hypervisor_manager.ghost_ios_support:
- self.set_ghost_ios(router)
-
- except DynamipsError as e:
- dynamips_stdout = ""
- if hypervisor:
- hypervisor.decrease_memory_load(ram)
- if hypervisor.memory_load == 0 and not hypervisor.devices:
- hypervisor.stop()
- self._hypervisor_manager.hypervisors.remove(hypervisor)
- dynamips_stdout = hypervisor.read_stdout()
- self.send_custom_error(str(e) + dynamips_stdout)
- return
-
- response = {"name": router.name,
- "id": router.id}
- defaults = router.defaults()
- response.update(defaults)
- self._routers[router.id] = router
- self.send_response(response)
-
- @IModule.route("dynamips.vm.delete")
- def vm_delete(self, request):
- """
- Deletes a VM (router).
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_DELETE_SCHEMA):
- return
-
- # get the router instance
- router_id = request["id"]
- router = self.get_device_instance(router_id, self._routers)
- if not router:
- return
-
- try:
- router.clean_delete()
- self._hypervisor_manager.unallocate_hypervisor_for_router(router)
- del self._routers[router_id]
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("dynamips.vm.start")
- def vm_start(self, request):
- """
- Starts a VM (router)
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_START_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- try:
- router.start()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
- self.send_response(True)
-
- @IModule.route("dynamips.vm.stop")
- def vm_stop(self, request):
- """
- Stops a VM (router)
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_STOP_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- try:
- router.stop()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("dynamips.vm.suspend")
- def vm_suspend(self, request):
- """
- Suspends a VM (router)
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_SUSPEND_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- try:
- router.suspend()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("dynamips.vm.reload")
- def vm_reload(self, request):
- """
- Reloads a VM (router)
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_RELOAD_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- try:
- if router.get_status() != "inactive":
- router.stop()
- router.start()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("dynamips.vm.update")
- def vm_update(self, request):
- """
- Updates settings for a VM (router).
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Optional request parameters:
- - any setting to update
- - startup_config_base64 (startup-config base64 encoded)
- - private_config_base64 (private-config base64 encoded)
-
- Response parameters:
- - updated settings
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_UPDATE_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- response = {}
- try:
- default_startup_config_path = os.path.join(router.hypervisor.working_dir, "configs", "i{}_startup-config.cfg".format(router.id))
- default_private_config_path = os.path.join(router.hypervisor.working_dir, "configs", "i{}_private-config.cfg".format(router.id))
-
- # a new startup-config has been pushed
- if "startup_config_base64" in request:
- # update the request with the new local startup-config path
- request["startup_config"] = self.create_config_from_base64(request["startup_config_base64"], router, default_startup_config_path)
-
- # a new private-config has been pushed
- if "private_config_base64" in request:
- # update the request with the new local private-config path
- request["private_config"] = self.create_config_from_base64(request["private_config_base64"], router, default_private_config_path)
-
- if "startup_config" in request:
- startup_config_path = request["startup_config"].replace("\\", '/')
- if os.path.isfile(startup_config_path) and startup_config_path != default_startup_config_path:
- # this is a local file set in the GUI
- startup_config_path = self.create_config_from_file(startup_config_path, router, default_startup_config_path)
- router.set_config(startup_config_path)
- else:
- router.set_config(startup_config_path)
- response["startup_config"] = startup_config_path
- del request["startup_config"]
-
- if "private_config" in request:
- private_config_path = request["private_config"].replace("\\", '/')
- if os.path.isfile(private_config_path) and private_config_path != default_private_config_path:
- # this is a local file set in the GUI
- private_config_path = self.create_config_from_file(private_config_path, router, default_private_config_path)
- router.set_config(router.startup_config, private_config_path)
- else:
- router.set_config(router.startup_config, private_config_path)
- response["private_config"] = private_config_path
- del request["private_config"]
-
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- # update the settings
- for name, value in request.items():
- if hasattr(router, name) and getattr(router, name) != value:
- try:
- setattr(router, name, value)
- response[name] = value
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
- elif name.startswith("slot") and value in ADAPTER_MATRIX:
- slot_id = int(name[-1])
- adapter_name = value
- adapter = ADAPTER_MATRIX[adapter_name]()
- try:
- if router.slots[slot_id] and not isinstance(router.slots[slot_id], type(adapter)):
- router.slot_remove_binding(slot_id)
- router.slot_add_binding(slot_id, adapter)
- response[name] = value
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
- elif name.startswith("slot") and value is None:
- slot_id = int(name[-1])
- if router.slots[slot_id]:
- try:
- router.slot_remove_binding(slot_id)
- response[name] = value
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
- elif name.startswith("wic") and value in WIC_MATRIX:
- wic_slot_id = int(name[-1])
- wic_name = value
- wic = WIC_MATRIX[wic_name]()
- try:
- if router.slots[0].wics[wic_slot_id] and not isinstance(router.slots[0].wics[wic_slot_id], type(wic)):
- router.uninstall_wic(wic_slot_id)
- router.install_wic(wic_slot_id, wic)
- response[name] = value
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
- elif name.startswith("wic") and value is None:
- wic_slot_id = int(name[-1])
- if router.slots[0].wics and router.slots[0].wics[wic_slot_id]:
- try:
- router.uninstall_wic(wic_slot_id)
- response[name] = value
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- # Update the ghost IOS file in case the RAM size has changed
- if self._hypervisor_manager.ghost_ios_support:
- try:
- self.set_ghost_ios(router)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(response)
-
- @IModule.route("dynamips.vm.start_capture")
- def vm_start_capture(self, request):
- """
- Starts a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port_id (port identifier)
- - slot (slot number)
- - port (port number)
- - capture_file_name
-
- Optional request parameters:
- - data_link_type (PCAP DLT_* value)
-
- Response parameters:
- - port_id (port identifier)
- - capture_file_path (path to the capture file)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_START_CAPTURE_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- slot = request["slot"]
- port = request["port"]
- capture_file_name = request["capture_file_name"]
- data_link_type = request.get("data_link_type")
-
- try:
- capture_file_path = os.path.join(router.hypervisor.working_dir, "captures", capture_file_name)
- router.start_capture(slot, port, capture_file_path, data_link_type)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"],
- "capture_file_path": capture_file_path}
- self.send_response(response)
-
- @IModule.route("dynamips.vm.stop_capture")
- def vm_stop_capture(self, request):
- """
- Stops a packet capture.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port_id (port identifier)
- - slot (slot number)
- - port (port number)
-
- Response parameters:
- - port_id (port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_STOP_CAPTURE_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- slot = request["slot"]
- port = request["port"]
- try:
- router.stop_capture(slot, port)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"port_id": request["port_id"]}
- self.send_response(response)
-
- @IModule.route("dynamips.vm.save_config")
- def vm_save_config(self, request):
- """
- Save the configs for a VM (router).
-
- Mandatory request parameters:
- - id (vm identifier)
- """
-
- # validate the request
- if not self.validate_request(request, VM_SAVE_CONFIG_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- try:
- router.save_configs()
- except DynamipsError as e:
- log.warn("could not save config to {}: {}".format(router.startup_config, e))
-
- @IModule.route("dynamips.vm.export_config")
- def vm_export_config(self, request):
- """
- Export the config from a router
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Response parameters:
- - startup_config_base64 (startup-config base64 encoded)
- - private_config_base64 (private-config base64 encoded)
- - False if no configuration can be extracted
- """
-
- # validate the request
- if not self.validate_request(request, VM_EXPORT_CONFIG_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- response = {}
- try:
- startup_config_base64, private_config_base64 = router.extract_config()
- if startup_config_base64:
- response["startup_config_base64"] = startup_config_base64
- if private_config_base64:
- response["private_config_base64"] = private_config_base64
- except DynamipsError:
- self.send_custom_error("unable to extract configs from the NVRAM")
- return
-
- if not response:
- self.send_response(False)
- else:
- self.send_response(response)
-
- @IModule.route("dynamips.vm.idlepcs")
- def vm_idlepcs(self, request):
- """
- Get Idle-PC proposals.
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Optional request parameters:
- - compute (returns previously compute Idle-PC values if False)
-
- Response parameters:
- - id (vm identifier)
- - idlepcs (Idle-PC values in an array)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_IDLEPCS_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- try:
- if "compute" in request and request["compute"] == False:
- idlepcs = router.show_idle_pc_prop()
- else:
- # reset the current Idle-PC value before calculating a new one
- router.idlepc = "0x0"
- idlepcs = router.get_idle_pc_prop()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"id": router.id,
- "idlepcs": idlepcs}
- self.send_response(response)
-
- @IModule.route("dynamips.vm.auto_idlepc")
- def vm_auto_idlepc(self, request):
- """
- Auto Idle-PC calculation.
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Response parameters:
- - id (vm identifier)
- - logs (logs for the calculation)
- - idlepc (Idle-PC value)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_AUTO_IDLEPC_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- try:
- router.idlepc = "0x0" # reset the current Idle-PC value before calculating a new one
- was_auto_started = False
- if router.get_status() != "running":
- router.start()
- was_auto_started = True
- time.sleep(20) # leave time to the router to boot
-
- logs = []
- validated_idlepc = "0x0"
- idlepcs = router.get_idle_pc_prop()
- if not idlepcs:
- logs.append("No Idle-PC values found")
-
- for idlepc in idlepcs:
- router.idlepc = idlepc.split()[0]
- logs.append("Trying Idle-PC value {}".format(router.idlepc))
- start_time = time.time()
- initial_cpu_usage = router.get_cpu_usage()
- logs.append("Initial CPU usage = {}%".format(initial_cpu_usage))
- time.sleep(4) # wait 4 seconds to probe the cpu again
- elapsed_time = time.time() - start_time
- cpu_elapsed_usage = router.get_cpu_usage() - initial_cpu_usage
- cpu_usage = abs(cpu_elapsed_usage * 100.0 / elapsed_time)
- logs.append("CPU usage after {:.2} seconds = {:.2}%".format(elapsed_time, cpu_usage))
- if cpu_usage > 100:
- cpu_usage = 100
- if cpu_usage < 70:
- validated_idlepc = router.idlepc
- logs.append("Idle-PC value {} has been validated".format(validated_idlepc))
- break
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
- finally:
- if was_auto_started:
- router.stop()
-
- response = {"id": router.id,
- "logs": logs,
- "idlepc": validated_idlepc}
-
- self.send_response(response)
-
- @IModule.route("dynamips.vm.allocate_udp_port")
- def vm_allocate_udp_port(self, request):
- """
- Allocates a UDP port in order to create an UDP NIO.
-
- Mandatory request parameters:
- - id (vm identifier)
- - port_id (unique port identifier)
-
- Response parameters:
- - port_id (unique port identifier)
- - lport (allocated local port)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_ALLOCATE_UDP_PORT_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- try:
- # allocate a new UDP port
- response = self.allocate_udp_port(router)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- response["port_id"] = request["port_id"]
- self.send_response(response)
-
- @IModule.route("dynamips.vm.add_nio")
- def vm_add_nio(self, request):
- """
- Adds an NIO (Network Input/Output) for a VM (router).
-
- Mandatory request parameters:
- - id (vm identifier)
- - slot (slot number)
- - port (port number)
- - port_id (unique port identifier)
- - nio (one of the following)
- - type "nio_udp"
- - lport (local port)
- - rhost (remote host)
- - rport (remote port)
- - type "nio_generic_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_linux_ethernet"
- - ethernet_device (Ethernet device name e.g. eth0)
- - type "nio_tap"
- - tap_device (TAP device name e.g. tap0)
- - type "nio_unix"
- - local_file (path to UNIX socket file)
- - remote_file (path to UNIX socket file)
- - type "nio_vde"
- - control_file (path to VDE control file)
- - local_file (path to VDE local file)
- - type "nio_null"
-
- Response parameters:
- - port_id (unique port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_ADD_NIO_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- slot = request["slot"]
- port = request["port"]
- try:
- nio = self.create_nio(router, request)
- if not nio:
- raise DynamipsError("Requested NIO doesn't exist: {}".format(request["nio"]))
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- try:
- router.slot_add_nio_binding(slot, port, nio)
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response({"port_id": request["port_id"]})
-
- @IModule.route("dynamips.vm.delete_nio")
- def vm_delete_nio(self, request):
- """
- Deletes an NIO (Network Input/Output).
-
- Mandatory request parameters:
- - id (vm identifier)
- - slot (slot identifier)
- - port (port identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VM_DELETE_NIO_SCHEMA):
- return
-
- # get the router instance
- router = self.get_device_instance(request["id"], self._routers)
- if not router:
- return
-
- slot = request["slot"]
- port = request["port"]
- try:
- nio = router.slot_remove_nio_binding(slot, port)
- nio.delete()
- except DynamipsError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
diff --git a/gns3server/old_modules/dynamips/hypervisor_manager.py b/gns3server/old_modules/dynamips/hypervisor_manager.py
deleted file mode 100644
index a9be6ed0..00000000
--- a/gns3server/old_modules/dynamips/hypervisor_manager.py
+++ /dev/null
@@ -1,655 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Manages Dynamips hypervisors (load-balancing etc.)
-"""
-
-from gns3server.config import Config
-from .hypervisor import Hypervisor
-from .dynamips_error import DynamipsError
-from ..attic import find_unused_port
-from ..attic import wait_socket_is_ready
-from pkg_resources import parse_version
-
-import os
-import time
-import logging
-
-log = logging.getLogger(__name__)
-
-
-class HypervisorManager(object):
-
- """
- Manages Dynamips hypervisors.
-
- :param path: path to the Dynamips executable
- :param working_dir: path to a working directory
- :param host: host/address for hypervisors to listen to
- :param console_host: IP address to bind for console connections
- """
-
- def __init__(self, path, working_dir, host='127.0.0.1', console_host='0.0.0.0'):
-
- self._hypervisors = []
- self._path = path
- self._working_dir = working_dir
- self._console_host = console_host
- self._host = console_host # FIXME: Dynamips must be patched to bind on a different address than the one used by the hypervisor.
-
- config = Config.instance()
- dynamips_config = config.get_section_config("DYNAMIPS")
- self._hypervisor_start_port_range = dynamips_config.get("hypervisor_start_port_range", 7200)
- self._hypervisor_end_port_range = dynamips_config.get("hypervisor_end_port_range", 7700)
- self._console_start_port_range = dynamips_config.get("console_start_port_range", 2001)
- self._console_end_port_range = dynamips_config.get("console_end_port_range", 2500)
- self._aux_start_port_range = dynamips_config.get("aux_start_port_range", 2501)
- self._aux_end_port_range = dynamips_config.get("aux_end_port_range", 3000)
- self._udp_start_port_range = dynamips_config.get("udp_start_port_range", 10001)
- self._udp_end_port_range = dynamips_config.get("udp_end_port_range", 20000)
- self._ghost_ios_support = dynamips_config.get("ghost_ios_support", True)
- self._mmap_support = dynamips_config.get("mmap_support", True)
- self._jit_sharing_support = dynamips_config.get("jit_sharing_support", False)
- self._sparse_memory_support = dynamips_config.get("sparse_memory_support", True)
- self._allocate_hypervisor_per_device = dynamips_config.get("allocate_hypervisor_per_device", True)
- self._memory_usage_limit_per_hypervisor = dynamips_config.get("memory_usage_limit_per_hypervisor", 1024)
- self._allocate_hypervisor_per_ios_image = dynamips_config.get("allocate_hypervisor_per_ios_image", True)
-
- def __del__(self):
- """
- Shutdowns all started hypervisors
- """
-
- self.stop_all_hypervisors()
-
- @property
- def hypervisors(self):
- """
- Returns all hypervisor instances.
-
- :returns: list of hypervisor instances
- """
-
- return self._hypervisors
-
- @property
- def path(self):
- """
- Returns the Dynamips path.
-
- :returns: path to Dynamips
- """
-
- return self._path
-
- @path.setter
- def path(self, path):
- """
- Set a new Dynamips path.
-
- :param path: path to Dynamips
- """
-
- self._path = path
- log.info("Dynamips path set to {}".format(self._path))
-
- @property
- def working_dir(self):
- """
- Returns the Dynamips working directory path.
-
- :returns: path to Dynamips working directory
- """
-
- return self._working_dir
-
- @working_dir.setter
- def working_dir(self, working_dir):
- """
- Sets a new path to the Dynamips working directory.
-
- :param working_dir: path to Dynamips working directory
- """
-
- self._working_dir = os.path.join(working_dir, "dynamips")
- log.info("working directory set to {}".format(self._working_dir))
-
- # update all existing hypervisors with the new working directory
- for hypervisor in self._hypervisors:
- hypervisor.working_dir = self._working_dir
-
- @property
- def hypervisor_start_port_range(self):
- """
- Returns the hypervisor start port range value
-
- :returns: hypervisor start port range value (integer)
- """
-
- return self._hypervisor_start_port_range
-
- @hypervisor_start_port_range.setter
- def hypervisor_start_port_range(self, hypervisor_start_port_range):
- """
- Sets a new hypervisor start port range value
-
- :param hypervisor_start_port_range: hypervisor start port range value (integer)
- """
-
- if self._hypervisor_start_port_range != hypervisor_start_port_range:
- self._hypervisor_start_port_range = hypervisor_start_port_range
- log.info("hypervisor start port range value set to {}".format(self._hypervisor_start_port_range))
-
- @property
- def hypervisor_end_port_range(self):
- """
- Returns the hypervisor end port range value
-
- :returns: hypervisor end port range value (integer)
- """
-
- return self._hypervisor_end_port_range
-
- @hypervisor_end_port_range.setter
- def hypervisor_end_port_range(self, hypervisor_end_port_range):
- """
- Sets a new hypervisor end port range value
-
- :param hypervisor_end_port_range: hypervisor end port range value (integer)
- """
-
- if self._hypervisor_end_port_range != hypervisor_end_port_range:
- self._hypervisor_end_port_range = hypervisor_end_port_range
- log.info("hypervisor end port range value set to {}".format(self._hypervisor_end_port_range))
-
- @property
- def console_start_port_range(self):
- """
- Returns the console start port range value
-
- :returns: console start port range value (integer)
- """
-
- return self._console_start_port_range
-
- @console_start_port_range.setter
- def console_start_port_range(self, console_start_port_range):
- """
- Sets a new console start port range value
-
- :param console_start_port_range: console start port range value (integer)
- """
-
- if self._console_start_port_range != console_start_port_range:
- self._console_start_port_range = console_start_port_range
- log.info("console start port range value set to {}".format(self._console_start_port_range))
-
- # update all existing hypervisors with the new value
- for hypervisor in self._hypervisors:
- hypervisor.console_start_port_range = console_start_port_range
-
- @property
- def console_end_port_range(self):
- """
- Returns the console end port range value
-
- :returns: console end port range value (integer)
- """
-
- return self._console_end_port_range
-
- @console_end_port_range.setter
- def console_end_port_range(self, console_end_port_range):
- """
- Sets a new console end port range value
-
- :param console_end_port_range: console end port range value (integer)
- """
-
- if self._console_end_port_range != console_end_port_range:
- self._console_end_port_range = console_end_port_range
- log.info("console end port range value set to {}".format(self._console_end_port_range))
-
- # update all existing hypervisors with the new value
- for hypervisor in self._hypervisors:
- hypervisor.console_end_port_range = console_end_port_range
-
- @property
- def aux_start_port_range(self):
- """
- Returns the auxiliary console start port range value
-
- :returns: auxiliary console start port range value (integer)
- """
-
- return self._aux_start_port_range
-
- @aux_start_port_range.setter
- def aux_start_port_range(self, aux_start_port_range):
- """
- Sets a new auxiliary console start port range value
-
- :param aux_start_port_range: auxiliary console start port range value (integer)
- """
-
- if self._aux_start_port_range != aux_start_port_range:
- self._aux_start_port_range = aux_start_port_range
- log.info("auxiliary console start port range value set to {}".format(self._aux_start_port_range))
-
- # update all existing hypervisors with the new value
- for hypervisor in self._hypervisors:
- hypervisor.aux_start_port_range = aux_start_port_range
-
- @property
- def aux_end_port_range(self):
- """
- Returns the auxiliary console end port range value
-
- :returns: auxiliary console end port range value (integer)
- """
-
- return self._aux_end_port_range
-
- @aux_end_port_range.setter
- def aux_end_port_range(self, aux_end_port_range):
- """
- Sets a new auxiliary console end port range value
-
- :param aux_end_port_range: auxiliary console end port range value (integer)
- """
-
- if self._aux_end_port_range != aux_end_port_range:
- self._aux_end_port_range = aux_end_port_range
- log.info("auxiliary console end port range value set to {}".format(self._aux_end_port_range))
-
- # update all existing hypervisors with the new value
- for hypervisor in self._hypervisors:
- hypervisor.aux_end_port_range = aux_end_port_range
-
- @property
- def udp_start_port_range(self):
- """
- Returns the UDP start port range value
-
- :returns: UDP start port range value (integer)
- """
-
- return self._udp_start_port_range
-
- @udp_start_port_range.setter
- def udp_start_port_range(self, udp_start_port_range):
- """
- Sets a new UDP start port range value
-
- :param udp_start_port_range: UDP start port range value (integer)
- """
-
- if self._udp_start_port_range != udp_start_port_range:
- self._udp_start_port_range = udp_start_port_range
- log.info("UDP start port range value set to {}".format(self._udp_start_port_range))
-
- # update all existing hypervisors with the new value
- for hypervisor in self._hypervisors:
- hypervisor.udp_start_port_range = udp_start_port_range
-
- @property
- def udp_end_port_range(self):
- """
- Returns the UDP end port range value
-
- :returns: UDP end port range value (integer)
- """
-
- return self._udp_end_port_range
-
- @udp_end_port_range.setter
- def udp_end_port_range(self, udp_end_port_range):
- """
- Sets a new UDP end port range value
-
- :param udp_end_port_range: UDP end port range value (integer)
- """
-
- if self._udp_end_port_range != udp_end_port_range:
- self._udp_end_port_range = udp_end_port_range
- log.info("UDP end port range value set to {}".format(self._udp_end_port_range))
-
- # update all existing hypervisors with the new value
- for hypervisor in self._hypervisors:
- hypervisor.udp_end_port_range = udp_end_port_range
-
- @property
- def ghost_ios_support(self):
- """
- Returns either ghost IOS is activated or not.
-
- :returns: boolean
- """
-
- return self._ghost_ios_support
-
- @ghost_ios_support.setter
- def ghost_ios_support(self, ghost_ios_support):
- """
- Sets ghost IOS support.
-
- :param ghost_ios_support: boolean
- """
-
- if self._ghost_ios_support != ghost_ios_support:
- self._ghost_ios_support = ghost_ios_support
- if ghost_ios_support:
- log.info("ghost IOS support enabled")
- else:
- log.info("ghost IOS support disabled")
-
- @property
- def mmap_support(self):
- """
- Returns either mmap is activated or not.
-
- :returns: boolean
- """
-
- return self._mmap_support
-
- @mmap_support.setter
- def mmap_support(self, mmap_support):
- """
- Sets mmap support.
-
- :param mmap_support: boolean
- """
-
- if self._mmap_support != mmap_support:
- self._mmap_support = mmap_support
- if mmap_support:
- log.info("mmap support enabled")
- else:
- log.info("mmap support disabled")
-
- @property
- def sparse_memory_support(self):
- """
- Returns either sparse memory is activated or not.
-
- :returns: boolean
- """
-
- return self._sparse_memory_support
-
- @sparse_memory_support.setter
- def sparse_memory_support(self, sparse_memory_support):
- """
- Sets sparse memory support.
-
- :param sparse_memory_support: boolean
- """
-
- if self._sparse_memory_support != sparse_memory_support:
- self._sparse_memory_support = sparse_memory_support
- if sparse_memory_support:
- log.info("sparse memory support enabled")
- else:
- log.info("sparse memory support disabled")
-
- @property
- def jit_sharing_support(self):
- """
- Returns either JIT sharing is activated or not.
-
- :returns: boolean
- """
-
- return self._jit_sharing_support
-
- @jit_sharing_support.setter
- def jit_sharing_support(self, jit_sharing_support):
- """
- Sets JIT sharing support.
-
- :param jit_sharing_support: boolean
- """
-
- if self._jit_sharing_support != jit_sharing_support:
- self._jit_sharing_support = jit_sharing_support
- if jit_sharing_support:
- log.info("JIT sharing support enabled")
- else:
- log.info("JIT sharing support disabled")
-
- @property
- def allocate_hypervisor_per_device(self):
- """
- Returns either an hypervisor is created for each device.
-
- :returns: True or False
- """
-
- return self._allocate_hypervisor_per_device
-
- @allocate_hypervisor_per_device.setter
- def allocate_hypervisor_per_device(self, value):
- """
- Sets if an hypervisor is created for each device.
-
- :param value: True or False
- """
-
- if self._allocate_hypervisor_per_device != value:
- self._allocate_hypervisor_per_device = value
- if value:
- log.info("allocating an hypervisor per device enabled")
- else:
- log.info("allocating an hypervisor per device disabled")
-
- @property
- def memory_usage_limit_per_hypervisor(self):
- """
- Returns the memory usage limit per hypervisor
-
- :returns: limit value (integer)
- """
-
- return self._memory_usage_limit_per_hypervisor
-
- @memory_usage_limit_per_hypervisor.setter
- def memory_usage_limit_per_hypervisor(self, memory_limit):
- """
- Sets the memory usage limit per hypervisor
-
- :param memory_limit: memory limit value (integer)
- """
-
- if self._memory_usage_limit_per_hypervisor != memory_limit:
- self._memory_usage_limit_per_hypervisor = memory_limit
- log.info("memory usage limit per hypervisor set to {}".format(memory_limit))
-
- @property
- def allocate_hypervisor_per_ios_image(self):
- """
- Returns if router are grouped per hypervisor
- based on their IOS image.
-
- :returns: True or False
- """
-
- return self._allocate_hypervisor_per_ios_image
-
- @allocate_hypervisor_per_ios_image.setter
- def allocate_hypervisor_per_ios_image(self, value):
- """
- Sets if routers are grouped per hypervisor
- based on their IOS image.
-
- :param value: True or False
- """
-
- if self._allocate_hypervisor_per_ios_image != value:
- self._allocate_hypervisor_per_ios_image = value
- if value:
- log.info("allocating an hypervisor per IOS image enabled")
- else:
- log.info("allocating an hypervisor per IOS image disabled")
-
- def wait_for_hypervisor(self, host, port):
- """
- Waits for an hypervisor to be started (accepting a socket connection)
-
- :param host: host/address to connect to the hypervisor
- :param port: port to connect to the hypervisor
- """
-
- begin = time.time()
- # wait for the socket for a maximum of 10 seconds.
- connection_success, last_exception = wait_socket_is_ready(host, port, wait=10.0)
-
- if not connection_success:
- # FIXME: throw exception here
- log.critical("Couldn't connect to hypervisor on {}:{} :{}".format(host, port,
- last_exception))
- else:
- log.info("Dynamips server ready after {:.4f} seconds".format(time.time() - begin))
-
- def start_new_hypervisor(self):
- """
- Creates a new Dynamips process and start it.
-
- :returns: the new hypervisor instance
- """
-
- try:
- port = find_unused_port(self._hypervisor_start_port_range, self._hypervisor_end_port_range, self._host)
- except Exception as e:
- raise DynamipsError(e)
-
- hypervisor = Hypervisor(self._path,
- self._working_dir,
- self._host,
- port)
-
- log.info("creating new hypervisor {}:{} with working directory {}".format(hypervisor.host, hypervisor.port, self._working_dir))
- hypervisor.start()
-
- self.wait_for_hypervisor(self._host, port)
- log.info("hypervisor {}:{} has successfully started".format(hypervisor.host, hypervisor.port))
-
- hypervisor.connect()
- if parse_version(hypervisor.version) < parse_version('0.2.11'):
- raise DynamipsError("Dynamips version must be >= 0.2.11, detected version is {}".format(hypervisor.version))
-
- hypervisor.console_start_port_range = self._console_start_port_range
- hypervisor.console_end_port_range = self._console_end_port_range
- hypervisor.aux_start_port_range = self._aux_start_port_range
- hypervisor.aux_end_port_range = self._aux_end_port_range
- hypervisor.udp_start_port_range = self._udp_start_port_range
- hypervisor.udp_end_port_range = self._udp_end_port_range
- self._hypervisors.append(hypervisor)
- return hypervisor
-
- def allocate_hypervisor_for_router(self, router_ios_image, router_ram):
- """
- Allocates a Dynamips hypervisor for a specific router
- (new or existing depending on the RAM amount and IOS image)
-
- :param router_ios_image: IOS image name
- :param router_ram: amount of RAM (integer)
-
- :returns: the allocated hypervisor instance
- """
-
- # allocate an hypervisor for each router by default
- if not self._allocate_hypervisor_per_device:
- for hypervisor in self._hypervisors:
- if self._allocate_hypervisor_per_ios_image:
- if not hypervisor.image_ref:
- hypervisor.image_ref = router_ios_image
- elif hypervisor.image_ref != router_ios_image:
- continue
- if (hypervisor.memory_load + router_ram) <= self._memory_usage_limit_per_hypervisor:
- current_memory_load = hypervisor.memory_load
- hypervisor.increase_memory_load(router_ram)
- log.info("allocating existing hypervisor {}:{}, RAM={}+{}".format(hypervisor.host,
- hypervisor.port,
- current_memory_load,
- router_ram))
- return hypervisor
-
- hypervisor = self.start_new_hypervisor()
- hypervisor.image_ref = router_ios_image
- hypervisor.increase_memory_load(router_ram)
- return hypervisor
-
- def unallocate_hypervisor_for_router(self, router):
- """
- Unallocates a Dynamips hypervisor for a specific router.
-
- :param router: Router instance
- """
-
- hypervisor = router.hypervisor
- hypervisor.decrease_memory_load(router.ram)
-
- if hypervisor.memory_load < 0:
- log.warn("hypervisor {}:{} has a memory load below 0 ({})".format(hypervisor.host,
- hypervisor.port,
- hypervisor.memory_load))
- #hypervisor.memory_load = 0
-
- # memory load at 0MB and no devices managed anymore...
- # let's stop this hypervisor
- if hypervisor.memory_load == 0 and not hypervisor.devices:
- hypervisor.stop()
- self._hypervisors.remove(hypervisor)
-
- def allocate_hypervisor_for_simulated_device(self):
- """
- Allocates a Dynamips hypervisor for a specific Dynamips simulated device.
-
- :returns: the allocated hypervisor instance
- """
-
- # For now always allocate the first hypervisor available,
- # in the future we could randomly allocate.
-
- if self._hypervisors:
- return self._hypervisors[0]
-
- # no hypervisor, let's start one!
- return self.start_new_hypervisor()
-
- def unallocate_hypervisor_for_simulated_device(self, device):
- """
- Unallocates a Dynamips hypervisor for a specific Dynamips simulated device.
-
- :param device: device instance
- """
-
- hypervisor = device.hypervisor
- if not hypervisor.devices:
- hypervisor.stop()
- self._hypervisors.remove(hypervisor)
-
- def stop_all_hypervisors(self):
- """
- Stops all hypervisors.
- """
-
- for hypervisor in self._hypervisors:
- hypervisor.stop()
- self._hypervisors = []
diff --git a/gns3server/old_modules/dynamips/nodes/__init__.py b/gns3server/old_modules/dynamips/nodes/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/gns3server/old_modules/dynamips/nodes/atm_bridge.py b/gns3server/old_modules/dynamips/nodes/atm_bridge.py
deleted file mode 100644
index bfed0b78..00000000
--- a/gns3server/old_modules/dynamips/nodes/atm_bridge.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Interface for Dynamips virtual ATM bridge module ("atm_bridge").
-http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L622
-"""
-
-from ..dynamips_error import DynamipsError
-
-
-class ATMBridge(object):
-
- """
- Dynamips bridge switch.
-
- :param hypervisor: Dynamips hypervisor instance
- :param name: name for this switch
- """
-
- def __init__(self, hypervisor, name):
-
- # FIXME: instance tracking
- self._hypervisor = hypervisor
- self._name = '"' + name + '"' # put name into quotes to protect spaces
- self._hypervisor.send("atm_bridge create {}".format(self._name))
- self._hypervisor.devices.append(self)
- self._nios = {}
- self._mapping = {}
-
- @property
- def name(self):
- """
- Returns the current name of this ATM bridge.
-
- :returns: ATM bridge name
- """
-
- return self._name[1:-1] # remove quotes
-
- @name.setter
- def name(self, new_name):
- """
- Renames this ATM bridge.
-
- :param new_name: New name for this bridge
- """
-
- new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
- self._hypervisor.send("atm_bridge rename {name} {new_name}".format(name=self._name,
- new_name=new_name))
- self._name = new_name
-
- @property
- def hypervisor(self):
- """
- Returns the current hypervisor.
-
- :returns: hypervisor instance
- """
-
- return self._hypervisor
-
- def list(self):
- """
- Returns all ATM bridge instances.
-
- :returns: list of all ATM bridges
- """
-
- return self._hypervisor.send("atm_bridge list")
-
- @property
- def nios(self):
- """
- Returns all the NIOs member of this ATM bridge.
-
- :returns: nio list
- """
-
- return self._nios
-
- @property
- def mapping(self):
- """
- Returns port mapping
-
- :returns: mapping list
- """
-
- return self._mapping
-
- def delete(self):
- """
- Deletes this ATM bridge.
- """
-
- self._hypervisor.send("atm_bridge delete {}".format(self._name))
- self._hypervisor.devices.remove(self)
-
- def add_nio(self, nio, port):
- """
- Adds a NIO as new port on ATM bridge.
-
- :param nio: NIO instance to add
- :param port: port to allocate for the NIO
- """
-
- if port in self._nios:
- raise DynamipsError("Port {} isn't free".format(port))
-
- self._nios[port] = nio
-
- def remove_nio(self, port):
- """
- Removes the specified NIO as member of this ATM switch.
-
- :param port: allocated port
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- del self._nios[port]
-
- def configure(self, eth_port, atm_port, atm_vpi, atm_vci):
- """
- Configures this ATM bridge.
-
- :param eth_port: Ethernet port
- :param atm_port: ATM port
- :param atm_vpi: ATM VPI
- :param atm_vci: ATM VCI
- """
-
- if eth_port not in self._nios:
- raise DynamipsError("Ethernet port {} is not allocated".format(eth_port))
-
- if atm_port not in self._nios:
- raise DynamipsError("ATM port {} is not allocated".format(atm_port))
-
- eth_nio = self._nios[eth_port]
- atm_nio = self._nios[atm_port]
-
- self._hypervisor.send("atm_bridge configure {name} {eth_nio} {atm_nio} {vpi} {vci}".format(name=self._name,
- eth_nio=eth_nio,
- atm_nio=atm_nio,
- vpi=atm_vpi,
- vci=atm_vci))
- self._mapping[eth_port] = (atm_port, atm_vpi, atm_vci)
-
- def unconfigure(self):
- """
- Unconfigures this ATM bridge.
- """
-
- self._hypervisor.send("atm_bridge unconfigure {}".format(self._name))
- del self._mapping
diff --git a/gns3server/old_modules/dynamips/nodes/atm_switch.py b/gns3server/old_modules/dynamips/nodes/atm_switch.py
deleted file mode 100644
index aa0dba3e..00000000
--- a/gns3server/old_modules/dynamips/nodes/atm_switch.py
+++ /dev/null
@@ -1,406 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Interface for Dynamips virtual ATM switch module ("atmsw").
-http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L593
-"""
-
-import os
-from ..dynamips_error import DynamipsError
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class ATMSwitch(object):
-
- """
- Dynamips ATM switch.
-
- :param hypervisor: Dynamips hypervisor instance
- :param name: name for this switch
- """
-
- _instances = []
-
- def __init__(self, hypervisor, name):
-
- # find an instance identifier (0 < id <= 4096)
- self._id = 0
- for identifier in range(1, 4097):
- if identifier not in self._instances:
- self._id = identifier
- self._instances.append(self._id)
- break
-
- if self._id == 0:
- raise DynamipsError("Maximum number of instances reached")
-
- self._hypervisor = hypervisor
- self._name = '"' + name + '"' # put name into quotes to protect spaces
- self._hypervisor.send("atmsw create {}".format(self._name))
-
- log.info("ATM switch {name} [id={id}] has been created".format(name=self._name,
- id=self._id))
-
- self._hypervisor.devices.append(self)
- self._nios = {}
- self._mapping = {}
-
- @classmethod
- def reset(cls):
- """
- Resets the instance count and the allocated instances list.
- """
-
- cls._instances.clear()
-
- @property
- def id(self):
- """
- Returns the unique ID for this ATM switch.
-
- :returns: id (integer)
- """
-
- return self._id
-
- @property
- def name(self):
- """
- Returns the current name of this ATM switch.
-
- :returns: ATM switch name
- """
-
- return self._name[1:-1] # remove quotes
-
- @name.setter
- def name(self, new_name):
- """
- Renames this ATM switch.
-
- :param new_name: New name for this switch
- """
-
- new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
- self._hypervisor.send("atmsw rename {name} {new_name}".format(name=self._name,
- new_name=new_name))
-
- log.info("ATM switch {name} [id={id}]: renamed to {new_name}".format(name=self._name,
- id=self._id,
- new_name=new_name))
-
- self._name = new_name
-
- @property
- def hypervisor(self):
- """
- Returns the current hypervisor.
-
- :returns: hypervisor instance
- """
-
- return self._hypervisor
-
- def list(self):
- """
- Returns all ATM switches instances.
-
- :returns: list of all ATM switches
- """
-
- return self._hypervisor.send("atmsw list")
-
- @property
- def nios(self):
- """
- Returns all the NIOs member of this ATM switch.
-
- :returns: nio list
- """
-
- return self._nios
-
- @property
- def mapping(self):
- """
- Returns port mapping
-
- :returns: mapping list
- """
-
- return self._mapping
-
- def delete(self):
- """
- Deletes this ATM switch.
- """
-
- self._hypervisor.send("atmsw delete {}".format(self._name))
-
- log.info("ATM switch {name} [id={id}] has been deleted".format(name=self._name,
- id=self._id))
- self._hypervisor.devices.remove(self)
- self._instances.remove(self._id)
-
- def has_port(self, port):
- """
- Checks if a port exists on this ATM switch.
-
- :returns: boolean
- """
-
- if port in self._nios:
- return True
- return False
-
- def add_nio(self, nio, port):
- """
- Adds a NIO as new port on ATM switch.
-
- :param nio: NIO instance to add
- :param port: port to allocate for the NIO
- """
-
- if port in self._nios:
- raise DynamipsError("Port {} isn't free".format(port))
-
- log.info("ATM switch {name} [id={id}]: NIO {nio} bound to port {port}".format(name=self._name,
- id=self._id,
- nio=nio,
- port=port))
-
- self._nios[port] = nio
-
- def remove_nio(self, port):
- """
- Removes the specified NIO as member of this ATM switch.
-
- :param port: allocated port
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
- log.info("ATM switch {name} [id={id}]: NIO {nio} removed from port {port}".format(name=self._name,
- id=self._id,
- nio=nio,
- port=port))
-
- del self._nios[port]
- return nio
-
- def map_vp(self, port1, vpi1, port2, vpi2):
- """
- Creates a new Virtual Path connection.
-
- :param port1: input port
- :param vpi1: input vpi
- :param port2: output port
- :param vpi2: output vpi
- """
-
- if port1 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port1))
-
- if port2 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port2))
-
- nio1 = self._nios[port1]
- nio2 = self._nios[port2]
-
- self._hypervisor.send("atmsw create_vpc {name} {input_nio} {input_vpi} {output_nio} {output_vpi}".format(name=self._name,
- input_nio=nio1,
- input_vpi=vpi1,
- output_nio=nio2,
- output_vpi=vpi2))
-
- log.info("ATM switch {name} [id={id}]: VPC from port {port1} VPI {vpi1} to port {port2} VPI {vpi2} created".format(name=self._name,
- id=self._id,
- port1=port1,
- vpi1=vpi1,
- port2=port2,
- vpi2=vpi2))
-
- self._mapping[(port1, vpi1)] = (port2, vpi2)
-
- def unmap_vp(self, port1, vpi1, port2, vpi2):
- """
- Deletes a new Virtual Path connection.
-
- :param port1: input port
- :param vpi1: input vpi
- :param port2: output port
- :param vpi2: output vpi
- """
-
- if port1 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port1))
-
- if port2 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port2))
-
- nio1 = self._nios[port1]
- nio2 = self._nios[port2]
-
- self._hypervisor.send("atmsw delete_vpc {name} {input_nio} {input_vpi} {output_nio} {output_vpi}".format(name=self._name,
- input_nio=nio1,
- input_vpi=vpi1,
- output_nio=nio2,
- output_vpi=vpi2))
-
- log.info("ATM switch {name} [id={id}]: VPC from port {port1} VPI {vpi1} to port {port2} VPI {vpi2} deleted".format(name=self._name,
- id=self._id,
- port1=port1,
- vpi1=vpi1,
- port2=port2,
- vpi2=vpi2))
-
- del self._mapping[(port1, vpi1)]
-
- def map_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
- """
- Creates a new Virtual Channel connection (unidirectional).
-
- :param port1: input port
- :param vpi1: input vpi
- :param vci1: input vci
- :param port2: output port
- :param vpi2: output vpi
- :param vci2: output vci
- """
-
- if port1 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port1))
-
- if port2 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port2))
-
- nio1 = self._nios[port1]
- nio2 = self._nios[port2]
-
- self._hypervisor.send("atmsw create_vcc {name} {input_nio} {input_vpi} {input_vci} {output_nio} {output_vpi} {output_vci}".format(name=self._name,
- input_nio=nio1,
- input_vpi=vpi1,
- input_vci=vci1,
- output_nio=nio2,
- output_vpi=vpi2,
- output_vci=vci2))
-
- log.info("ATM switch {name} [id={id}]: VCC from port {port1} VPI {vpi1} VCI {vci1} to port {port2} VPI {vpi2} VCI {vci2} created".format(name=self._name,
- id=self._id,
- port1=port1,
- vpi1=vpi1,
- vci1=vci1,
- port2=port2,
- vpi2=vpi2,
- vci2=vci2))
-
- self._mapping[(port1, vpi1, vci1)] = (port2, vpi2, vci2)
-
- def unmap_pvc(self, port1, vpi1, vci1, port2, vpi2, vci2):
- """
- Deletes a new Virtual Channel connection (unidirectional).
-
- :param port1: input port
- :param vpi1: input vpi
- :param vci1: input vci
- :param port2: output port
- :param vpi2: output vpi
- :param vci2: output vci
- """
-
- if port1 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port1))
-
- if port2 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port2))
-
- nio1 = self._nios[port1]
- nio2 = self._nios[port2]
-
- self._hypervisor.send("atmsw delete_vcc {name} {input_nio} {input_vpi} {input_vci} {output_nio} {output_vpi} {output_vci}".format(name=self._name,
- input_nio=nio1,
- input_vpi=vpi1,
- input_vci=vci1,
- output_nio=nio2,
- output_vpi=vpi2,
- output_vci=vci2))
-
- log.info("ATM switch {name} [id={id}]: VCC from port {port1} VPI {vpi1} VCI {vci1} to port {port2} VPI {vpi2} VCI {vci2} deleted".format(name=self._name,
- id=self._id,
- port1=port1,
- vpi1=vpi1,
- vci1=vci1,
- port2=port2,
- vpi2=vpi2,
- vci2=vci2))
- del self._mapping[(port1, vpi1, vci1)]
-
- def start_capture(self, port, output_file, data_link_type="DLT_ATM_RFC1483"):
- """
- Starts a packet capture.
-
- :param port: allocated port
- :param output_file: PCAP destination file for the capture
- :param data_link_type: PCAP data link type (DLT_*), default is DLT_ATM_RFC1483
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
-
- data_link_type = data_link_type.lower()
- if data_link_type.startswith("dlt_"):
- data_link_type = data_link_type[4:]
-
- if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
- raise DynamipsError("Port {} has already a filter applied".format(port))
-
- try:
- os.makedirs(os.path.dirname(output_file))
- except FileExistsError:
- pass
- except OSError as e:
- raise DynamipsError("Could not create captures directory {}".format(e))
-
- nio.bind_filter("both", "capture")
- nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
-
- log.info("ATM switch {name} [id={id}]: starting packet capture on {port}".format(name=self._name,
- id=self._id,
- port=port))
-
- def stop_capture(self, port):
- """
- Stops a packet capture.
-
- :param port: allocated port
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
- nio.unbind_filter("both")
- log.info("ATM switch {name} [id={id}]: stopping packet capture on {port}".format(name=self._name,
- id=self._id,
- port=port))
diff --git a/gns3server/old_modules/dynamips/nodes/bridge.py b/gns3server/old_modules/dynamips/nodes/bridge.py
deleted file mode 100644
index fcac17b9..00000000
--- a/gns3server/old_modules/dynamips/nodes/bridge.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Interface for Dynamips NIO bridge module ("nio_bridge").
-http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L538
-"""
-
-
-class Bridge(object):
-
- """
- Dynamips bridge.
-
- :param hypervisor: Dynamips hypervisor instance
- :param name: name for this bridge
- """
-
- def __init__(self, hypervisor, name):
-
- self._hypervisor = hypervisor
- self._name = '"' + name + '"' # put name into quotes to protect spaces
- self._hypervisor.send("nio_bridge create {}".format(self._name))
- self._hypervisor.devices.append(self)
- self._nios = []
-
- @property
- def name(self):
- """
- Returns the current name of this bridge.
-
- :returns: bridge name
- """
-
- return self._name[1:-1] # remove quotes
-
- @name.setter
- def name(self, new_name):
- """
- Renames this bridge.
-
- :param new_name: New name for this bridge
- """
-
- new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
- self._hypervisor.send("nio_bridge rename {name} {new_name}".format(name=self._name,
- new_name=new_name))
-
- self._name = new_name
-
- @property
- def hypervisor(self):
- """
- Returns the current hypervisor.
-
- :returns: hypervisor instance
- """
-
- return self._hypervisor
-
- def list(self):
- """
- Returns all bridge instances.
-
- :returns: list of all bridges
- """
-
- return self._hypervisor.send("nio_bridge list")
-
- @property
- def nios(self):
- """
- Returns all the NIOs member of this bridge.
-
- :returns: nio list
- """
-
- return self._nios
-
- def delete(self):
- """
- Deletes this bridge.
- """
-
- self._hypervisor.send("nio_bridge delete {}".format(self._name))
- self._hypervisor.devices.remove(self)
-
- def add_nio(self, nio):
- """
- Adds a NIO as new port on this bridge.
-
- :param nio: NIO instance to add
- """
-
- self._hypervisor.send("nio_bridge add_nio {name} {nio}".format(name=self._name,
- nio=nio))
- self._nios.append(nio)
-
- def remove_nio(self, nio):
- """
- Removes the specified NIO as member of this bridge.
-
- :param nio: NIO instance to remove
- """
-
- self._hypervisor.send("nio_bridge remove_nio {name} {nio}".format(name=self._name,
- nio=nio))
- self._nios.remove(nio)
diff --git a/gns3server/old_modules/dynamips/nodes/ethernet_switch.py b/gns3server/old_modules/dynamips/nodes/ethernet_switch.py
deleted file mode 100644
index a88346dc..00000000
--- a/gns3server/old_modules/dynamips/nodes/ethernet_switch.py
+++ /dev/null
@@ -1,342 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Interface for Dynamips virtual Ethernet switch module ("ethsw").
-http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L558
-"""
-
-import os
-from ..dynamips_error import DynamipsError
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class EthernetSwitch(object):
-
- """
- Dynamips Ethernet switch.
-
- :param hypervisor: Dynamips hypervisor instance
- :param name: name for this switch
- """
-
- _instances = []
-
- def __init__(self, hypervisor, name):
-
- # find an instance identifier (0 < id <= 4096)
- self._id = 0
- for identifier in range(1, 4097):
- if identifier not in self._instances:
- self._id = identifier
- self._instances.append(self._id)
- break
-
- if self._id == 0:
- raise DynamipsError("Maximum number of instances reached")
-
- self._hypervisor = hypervisor
- self._name = '"' + name + '"' # put name into quotes to protect spaces
- self._hypervisor.send("ethsw create {}".format(self._name))
-
- log.info("Ethernet switch {name} [id={id}] has been created".format(name=self._name,
- id=self._id))
-
- self._hypervisor.devices.append(self)
- self._nios = {}
- self._mapping = {}
-
- @classmethod
- def reset(cls):
- """
- Resets the instance count and the allocated instances list.
- """
-
- cls._instances.clear()
-
- @property
- def id(self):
- """
- Returns the unique ID for this Ethernet switch.
-
- :returns: id (integer)
- """
-
- return self._id
-
- @property
- def name(self):
- """
- Returns the current name of this Ethernet switch.
-
- :returns: Ethernet switch name
- """
-
- return self._name[1:-1] # remove quotes
-
- @name.setter
- def name(self, new_name):
- """
- Renames this Ethernet switch.
-
- :param new_name: New name for this switch
- """
-
- new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
- self._hypervisor.send("ethsw rename {name} {new_name}".format(name=self._name,
- new_name=new_name))
-
- log.info("Ethernet switch {name} [id={id}]: renamed to {new_name}".format(name=self._name,
- id=self._id,
- new_name=new_name))
-
- self._name = new_name
-
- @property
- def hypervisor(self):
- """
- Returns the current hypervisor.
-
- :returns: hypervisor instance
- """
-
- return self._hypervisor
-
- def list(self):
- """
- Returns all Ethernet switches instances.
-
- :returns: list of all Ethernet switches
- """
-
- return self._hypervisor.send("ethsw list")
-
- @property
- def nios(self):
- """
- Returns all the NIOs member of this Ethernet switch.
-
- :returns: nio list
- """
-
- return self._nios
-
- @property
- def mapping(self):
- """
- Returns port mapping
-
- :returns: mapping list
- """
-
- return self._mapping
-
- def delete(self):
- """
- Deletes this Ethernet switch.
- """
-
- self._hypervisor.send("ethsw delete {}".format(self._name))
-
- log.info("Ethernet switch {name} [id={id}] has been deleted".format(name=self._name,
- id=self._id))
- self._hypervisor.devices.remove(self)
- self._instances.remove(self._id)
-
- def add_nio(self, nio, port):
- """
- Adds a NIO as new port on Ethernet switch.
-
- :param nio: NIO instance to add
- :param port: port to allocate for the NIO
- """
-
- if port in self._nios:
- raise DynamipsError("Port {} isn't free".format(port))
-
- self._hypervisor.send("ethsw add_nio {name} {nio}".format(name=self._name,
- nio=nio))
-
- log.info("Ethernet switch {name} [id={id}]: NIO {nio} bound to port {port}".format(name=self._name,
- id=self._id,
- nio=nio,
- port=port))
- self._nios[port] = nio
-
- def remove_nio(self, port):
- """
- Removes the specified NIO as member of this Ethernet switch.
-
- :param port: allocated port
-
- :returns: the NIO that was bound to the port
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
- self._hypervisor.send("ethsw remove_nio {name} {nio}".format(name=self._name,
- nio=nio))
-
- log.info("Ethernet switch {name} [id={id}]: NIO {nio} removed from port {port}".format(name=self._name,
- id=self._id,
- nio=nio,
- port=port))
-
- del self._nios[port]
-
- if port in self._mapping:
- del self._mapping[port]
-
- return nio
-
- def set_access_port(self, port, vlan_id):
- """
- Sets the specified port as an ACCESS port.
-
- :param port: allocated port
- :param vlan_id: VLAN number membership
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
- self._hypervisor.send("ethsw set_access_port {name} {nio} {vlan_id}".format(name=self._name,
- nio=nio,
- vlan_id=vlan_id))
-
- log.info("Ethernet switch {name} [id={id}]: port {port} set as an access port in VLAN {vlan_id}".format(name=self._name,
- id=self._id,
- port=port,
- vlan_id=vlan_id))
- self._mapping[port] = ("access", vlan_id)
-
- def set_dot1q_port(self, port, native_vlan):
- """
- Sets the specified port as a 802.1Q trunk port.
-
- :param port: allocated port
- :param native_vlan: native VLAN for this trunk port
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
- self._hypervisor.send("ethsw set_dot1q_port {name} {nio} {native_vlan}".format(name=self._name,
- nio=nio,
- native_vlan=native_vlan))
-
- log.info("Ethernet switch {name} [id={id}]: port {port} set as a 802.1Q port with native VLAN {vlan_id}".format(name=self._name,
- id=self._id,
- port=port,
- vlan_id=native_vlan))
-
- self._mapping[port] = ("dot1q", native_vlan)
-
- def set_qinq_port(self, port, outer_vlan):
- """
- Sets the specified port as a trunk (QinQ) port.
-
- :param port: allocated port
- :param outer_vlan: outer VLAN (transport VLAN) for this QinQ port
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
- self._hypervisor.send("ethsw set_qinq_port {name} {nio} {outer_vlan}".format(name=self._name,
- nio=nio,
- outer_vlan=outer_vlan))
-
- log.info("Ethernet switch {name} [id={id}]: port {port} set as a QinQ port with outer VLAN {vlan_id}".format(name=self._name,
- id=self._id,
- port=port,
- vlan_id=outer_vlan))
- self._mapping[port] = ("qinq", outer_vlan)
-
- def get_mac_addr_table(self):
- """
- Returns the MAC address table for this Ethernet switch.
-
- :returns: list of entries (Ethernet address, VLAN, NIO)
- """
-
- return self._hypervisor.send("ethsw show_mac_addr_table {}".format(self._name))
-
- def clear_mac_addr_table(self):
- """
- Clears the MAC address table for this Ethernet switch.
- """
-
- self._hypervisor.send("ethsw clear_mac_addr_table {}".format(self._name))
-
- def start_capture(self, port, output_file, data_link_type="DLT_EN10MB"):
- """
- Starts a packet capture.
-
- :param port: allocated port
- :param output_file: PCAP destination file for the capture
- :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
-
- data_link_type = data_link_type.lower()
- if data_link_type.startswith("dlt_"):
- data_link_type = data_link_type[4:]
-
- if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
- raise DynamipsError("Port {} has already a filter applied".format(port))
-
- try:
- os.makedirs(os.path.dirname(output_file))
- except FileExistsError:
- pass
- except OSError as e:
- raise DynamipsError("Could not create captures directory {}".format(e))
-
- nio.bind_filter("both", "capture")
- nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
-
- log.info("Ethernet switch {name} [id={id}]: starting packet capture on {port}".format(name=self._name,
- id=self._id,
- port=port))
-
- def stop_capture(self, port):
- """
- Stops a packet capture.
-
- :param port: allocated port
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
- nio.unbind_filter("both")
- log.info("Ethernet switch {name} [id={id}]: stopping packet capture on {port}".format(name=self._name,
- id=self._id,
- port=port))
diff --git a/gns3server/old_modules/dynamips/nodes/frame_relay_switch.py b/gns3server/old_modules/dynamips/nodes/frame_relay_switch.py
deleted file mode 100644
index 8a309301..00000000
--- a/gns3server/old_modules/dynamips/nodes/frame_relay_switch.py
+++ /dev/null
@@ -1,328 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Interface for Dynamips virtual Frame-Relay switch module.
-http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L642
-"""
-
-import os
-from ..dynamips_error import DynamipsError
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class FrameRelaySwitch(object):
-
- """
- Dynamips Frame Relay switch.
-
- :param hypervisor: Dynamips hypervisor instance
- :param name: name for this switch
- """
-
- _instances = []
-
- def __init__(self, hypervisor, name):
-
- # find an instance identifier (0 < id <= 4096)
- self._id = 0
- for identifier in range(1, 4097):
- if identifier not in self._instances:
- self._id = identifier
- self._instances.append(self._id)
- break
-
- if self._id == 0:
- raise DynamipsError("Maximum number of instances reached")
-
- self._hypervisor = hypervisor
- self._name = '"' + name + '"' # put name into quotes to protect spaces
- self._hypervisor.send("frsw create {}".format(self._name))
-
- log.info("Frame Relay switch {name} [id={id}] has been created".format(name=self._name,
- id=self._id))
-
- self._hypervisor.devices.append(self)
- self._nios = {}
- self._mapping = {}
-
- @classmethod
- def reset(cls):
- """
- Resets the instance count and the allocated instances list.
- """
-
- cls._instances.clear()
-
- @property
- def id(self):
- """
- Returns the unique ID for this Frame Relay switch.
-
- :returns: id (integer)
- """
-
- return self._id
-
- @property
- def name(self):
- """
- Returns the current name of this Frame Relay switch.
-
- :returns: Frame Relay switch name
- """
-
- return self._name[1:-1] # remove quotes
-
- @name.setter
- def name(self, new_name):
- """
- Renames this Frame Relay switch.
-
- :param new_name: New name for this switch
- """
-
- new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
- self._hypervisor.send("frsw rename {name} {new_name}".format(name=self._name,
- new_name=new_name))
-
- log.info("Frame Relay switch {name} [id={id}]: renamed to {new_name}".format(name=self._name,
- id=self._id,
- new_name=new_name))
-
- self._name = new_name
-
- @property
- def hypervisor(self):
- """
- Returns the current hypervisor.
-
- :returns: hypervisor instance
- """
-
- return self._hypervisor
-
- def list(self):
- """
- Returns all Frame Relay switches instances.
-
- :returns: list of all Frame Relay switches
- """
-
- return self._hypervisor.send("frsw list")
-
- @property
- def nios(self):
- """
- Returns all the NIOs member of this Frame Relay switch.
-
- :returns: nio list
- """
-
- return self._nios
-
- @property
- def mapping(self):
- """
- Returns port mapping
-
- :returns: mapping list
- """
-
- return self._mapping
-
- def delete(self):
- """
- Deletes this Frame Relay switch.
- """
-
- self._hypervisor.send("frsw delete {}".format(self._name))
-
- log.info("Frame Relay switch {name} [id={id}] has been deleted".format(name=self._name,
- id=self._id))
- self._hypervisor.devices.remove(self)
- self._instances.remove(self._id)
-
- def has_port(self, port):
- """
- Checks if a port exists on this Frame Relay switch.
-
- :returns: boolean
- """
-
- if port in self._nios:
- return True
- return False
-
- def add_nio(self, nio, port):
- """
- Adds a NIO as new port on Frame Relay switch.
-
- :param nio: NIO instance to add
- :param port: port to allocate for the NIO
- """
-
- if port in self._nios:
- raise DynamipsError("Port {} isn't free".format(port))
-
- log.info("Frame Relay switch {name} [id={id}]: NIO {nio} bound to port {port}".format(name=self._name,
- id=self._id,
- nio=nio,
- port=port))
-
- self._nios[port] = nio
-
- def remove_nio(self, port):
- """
- Removes the specified NIO as member of this Frame Relay switch.
-
- :param port: allocated port
-
- :returns: the NIO that was bound to the allocated port
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
- log.info("Frame Relay switch {name} [id={id}]: NIO {nio} removed from port {port}".format(name=self._name,
- id=self._id,
- nio=nio,
- port=port))
-
- del self._nios[port]
- return nio
-
- def map_vc(self, port1, dlci1, port2, dlci2):
- """
- Creates a new Virtual Circuit connection (unidirectional).
-
- :param port1: input port
- :param dlci1: input DLCI
- :param port2: output port
- :param dlci2: output DLCI
- """
-
- if port1 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port1))
-
- if port2 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port2))
-
- nio1 = self._nios[port1]
- nio2 = self._nios[port2]
-
- self._hypervisor.send("frsw create_vc {name} {input_nio} {input_dlci} {output_nio} {output_dlci}".format(name=self._name,
- input_nio=nio1,
- input_dlci=dlci1,
- output_nio=nio2,
- output_dlci=dlci2))
-
- log.info("Frame Relay switch {name} [id={id}]: VC from port {port1} DLCI {dlci1} to port {port2} DLCI {dlci2} created".format(name=self._name,
- id=self._id,
- port1=port1,
- dlci1=dlci1,
- port2=port2,
- dlci2=dlci2))
-
- self._mapping[(port1, dlci1)] = (port2, dlci2)
-
- def unmap_vc(self, port1, dlci1, port2, dlci2):
- """
- Deletes a Virtual Circuit connection (unidirectional).
-
- :param port1: input port
- :param dlci1: input DLCI
- :param port2: output port
- :param dlci2: output DLCI
- """
-
- if port1 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port1))
-
- if port2 not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port2))
-
- nio1 = self._nios[port1]
- nio2 = self._nios[port2]
-
- self._hypervisor.send("frsw delete_vc {name} {input_nio} {input_dlci} {output_nio} {output_dlci}".format(name=self._name,
- input_nio=nio1,
- input_dlci=dlci1,
- output_nio=nio2,
- output_dlci=dlci2))
-
- log.info("Frame Relay switch {name} [id={id}]: VC from port {port1} DLCI {dlci1} to port {port2} DLCI {dlci2} deleted".format(name=self._name,
- id=self._id,
- port1=port1,
- dlci1=dlci1,
- port2=port2,
- dlci2=dlci2))
- del self._mapping[(port1, dlci1)]
-
- def start_capture(self, port, output_file, data_link_type="DLT_FRELAY"):
- """
- Starts a packet capture.
-
- :param port: allocated port
- :param output_file: PCAP destination file for the capture
- :param data_link_type: PCAP data link type (DLT_*), default is DLT_FRELAY
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
-
- data_link_type = data_link_type.lower()
- if data_link_type.startswith("dlt_"):
- data_link_type = data_link_type[4:]
-
- if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
- raise DynamipsError("Port {} has already a filter applied".format(port))
-
- try:
- os.makedirs(os.path.dirname(output_file))
- except FileExistsError:
- pass
- except OSError as e:
- raise DynamipsError("Could not create captures directory {}".format(e))
-
- nio.bind_filter("both", "capture")
- nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
-
- log.info("Frame relay switch {name} [id={id}]: starting packet capture on {port}".format(name=self._name,
- id=self._id,
- port=port))
-
- def stop_capture(self, port):
- """
- Stops a packet capture.
-
- :param port: allocated port
- """
-
- if port not in self._nios:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._nios[port]
- nio.unbind_filter("both")
- log.info("Frame relay switch {name} [id={id}]: stopping packet capture on {port}".format(name=self._name,
- id=self._id,
- port=port))
diff --git a/gns3server/old_modules/dynamips/nodes/hub.py b/gns3server/old_modules/dynamips/nodes/hub.py
deleted file mode 100644
index 18cedbe1..00000000
--- a/gns3server/old_modules/dynamips/nodes/hub.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Hub object that uses the Bridge interface to create a hub with ports.
-"""
-
-import os
-from .bridge import Bridge
-from ..dynamips_error import DynamipsError
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class Hub(Bridge):
-
- """
- Dynamips hub (based on Bridge)
-
- :param hypervisor: Dynamips hypervisor instance
- :param name: name for this hub
- """
-
- _instances = []
-
- def __init__(self, hypervisor, name):
-
- # find an instance identifier (0 < id <= 4096)
- self._id = 0
- for identifier in range(1, 4097):
- if identifier not in self._instances:
- self._id = identifier
- self._instances.append(self._id)
- break
-
- if self._id == 0:
- raise DynamipsError("Maximum number of instances reached")
-
- self._mapping = {}
- Bridge.__init__(self, hypervisor, name)
-
- log.info("Ethernet hub {name} [id={id}] has been created".format(name=self._name,
- id=self._id))
-
- @classmethod
- def reset(cls):
- """
- Resets the instance count and the allocated instances list.
- """
-
- cls._instances.clear()
-
- @property
- def id(self):
- """
- Returns the unique ID for this Ethernet switch.
-
- :returns: id (integer)
- """
-
- return self._id
-
- @property
- def mapping(self):
- """
- Returns port mapping
-
- :returns: mapping list
- """
-
- return self._mapping
-
- def delete(self):
- """
- Deletes this hub.
- """
-
- Bridge.delete(self)
- log.info("Ethernet hub {name} [id={id}] has been deleted".format(name=self._name,
- id=self._id))
- self._instances.remove(self._id)
-
- def add_nio(self, nio, port):
- """
- Adds a NIO as new port on this hub.
-
- :param nio: NIO instance to add
- :param port: port to allocate for the NIO
- """
-
- if port in self._mapping:
- raise DynamipsError("Port {} isn't free".format(port))
-
- Bridge.add_nio(self, nio)
-
- log.info("Ethernet hub {name} [id={id}]: NIO {nio} bound to port {port}".format(name=self._name,
- id=self._id,
- nio=nio,
- port=port))
- self._mapping[port] = nio
-
- def remove_nio(self, port):
- """
- Removes the specified NIO as member of this hub.
-
- :param port: allocated port
-
- :returns: the NIO that was bound to the allocated port
- """
-
- if port not in self._mapping:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._mapping[port]
- Bridge.remove_nio(self, nio)
-
- log.info("Ethernet switch {name} [id={id}]: NIO {nio} removed from port {port}".format(name=self._name,
- id=self._id,
- nio=nio,
- port=port))
-
- del self._mapping[port]
- return nio
-
- def start_capture(self, port, output_file, data_link_type="DLT_EN10MB"):
- """
- Starts a packet capture.
-
- :param port: allocated port
- :param output_file: PCAP destination file for the capture
- :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
- """
-
- if port not in self._mapping:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._mapping[port]
-
- data_link_type = data_link_type.lower()
- if data_link_type.startswith("dlt_"):
- data_link_type = data_link_type[4:]
-
- if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
- raise DynamipsError("Port {} has already a filter applied".format(port))
-
- try:
- os.makedirs(os.path.dirname(output_file))
- except FileExistsError:
- pass
- except OSError as e:
- raise DynamipsError("Could not create captures directory {}".format(e))
-
- nio.bind_filter("both", "capture")
- nio.setup_filter("both", "{} {}".format(data_link_type, output_file))
-
- log.info("Ethernet hub {name} [id={id}]: starting packet capture on {port}".format(name=self._name,
- id=self._id,
- port=port))
-
- def stop_capture(self, port):
- """
- Stops a packet capture.
-
- :param port: allocated port
- """
-
- if port not in self._mapping:
- raise DynamipsError("Port {} is not allocated".format(port))
-
- nio = self._mapping[port]
- nio.unbind_filter("both")
- log.info("Ethernet hub {name} [id={id}]: stopping packet capture on {port}".format(name=self._name,
- id=self._id,
- port=port))
diff --git a/gns3server/old_modules/dynamips/nodes/router.py b/gns3server/old_modules/dynamips/nodes/router.py
deleted file mode 100644
index 18d8db8d..00000000
--- a/gns3server/old_modules/dynamips/nodes/router.py
+++ /dev/null
@@ -1,1676 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Interface for Dynamips virtual Machine module ("vm")
-http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L77
-"""
-
-from ..dynamips_error import DynamipsError
-from ...attic import find_unused_port
-
-import time
-import sys
-import os
-import base64
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class Router(object):
-
- """
- Dynamips router implementation.
-
- :param hypervisor: Dynamips hypervisor instance
- :param name: name for this router
- :param router_id: router instance ID
- :param platform: c7200, c3745, c3725, c3600, c2691, c2600 or c1700
- :param ghost_flag: used when creating a ghost IOS.
- """
-
- _instances = []
- _allocated_console_ports = []
- _allocated_aux_ports = []
- _status = {0: "inactive",
- 1: "shutting down",
- 2: "running",
- 3: "suspended"}
-
- def __init__(self, hypervisor, name, router_id=None, platform="c7200", ghost_flag=False):
-
- if not ghost_flag:
-
- if not router_id:
- # find an instance identifier if none is provided (0 < id <= 4096)
- self._id = 0
- for identifier in range(1, 4097):
- if identifier not in self._instances:
- self._id = identifier
- self._instances.append(self._id)
- break
-
- if self._id == 0:
- raise DynamipsError("Maximum number of instances reached")
- else:
- if router_id in self._instances:
- raise DynamipsError("Router identifier {} is already used by another router".format(router_id))
- self._id = router_id
- self._instances.append(self._id)
-
- else:
- log.info("creating a new ghost IOS file")
- self._id = 0
- name = "Ghost"
-
- self._hypervisor = hypervisor
- self._name = '"' + name + '"' # put name into quotes to protect spaces
- self._platform = platform
- self._image = ""
- self._startup_config = ""
- self._private_config = ""
- self._ram = 128 # Megabytes
- self._nvram = 128 # Kilobytes
- self._mmap = True
- self._sparsemem = True
- self._clock_divisor = 8
- self._idlepc = ""
- self._idlemax = 500
- self._idlesleep = 30
- self._ghost_file = ""
- self._ghost_status = 0
- if sys.platform.startswith("win"):
- self._exec_area = 16 # 16 MB by default on Windows (Cygwin)
- else:
- self._exec_area = 64 # 64 MB on other systems
- self._jit_sharing_group = None
- self._disk0 = 0 # Megabytes
- self._disk1 = 0 # Megabytes
- self._confreg = "0x2102"
- self._console = None
- self._aux = None
- self._mac_addr = None
- self._system_id = "FTX0945W0MY" # processor board ID in IOS
- self._slots = []
-
- self._hypervisor.send("vm create {name} {id} {platform}".format(name=self._name,
- id=self._id,
- platform=self._platform))
-
- if not ghost_flag:
- log.info("router {platform} {name} [id={id}] has been created".format(name=self._name,
- platform=platform,
- id=self._id))
-
- try:
- # allocate a console port
- self._console = find_unused_port(self._hypervisor.console_start_port_range,
- self._hypervisor.console_end_port_range,
- self._hypervisor.host,
- ignore_ports=self._allocated_console_ports)
-
- self._hypervisor.send("vm set_con_tcp_port {name} {console}".format(name=self._name,
- console=self._console))
- self._allocated_console_ports.append(self._console)
-
- # allocate a auxiliary console port
- self._aux = find_unused_port(self._hypervisor.aux_start_port_range,
- self._hypervisor.aux_end_port_range,
- self._hypervisor.host,
- ignore_ports=self._allocated_aux_ports)
-
- self._hypervisor.send("vm set_aux_tcp_port {name} {aux}".format(name=self._name,
- aux=self._aux))
-
- self._allocated_aux_ports.append(self._aux)
- except Exception as e:
- raise DynamipsError(e)
-
- # get the default base MAC address
- self._mac_addr = self._hypervisor.send("{platform} get_mac_addr {name}".format(platform=self._platform,
- name=self._name))[0]
-
- self._hypervisor.devices.append(self)
-
- @classmethod
- def reset(cls):
- """
- Resets the instance count and the allocated instances list.
- """
-
- cls._instances.clear()
- cls._allocated_console_ports.clear()
- cls._allocated_aux_ports.clear()
-
- def defaults(self):
- """
- Returns all the default base attribute values for routers.
-
- :returns: default values (dictionary)
- """
-
- router_defaults = {"platform": self._platform,
- "image": self._image,
- "startup_config": self._startup_config,
- "private_config": self._private_config,
- "ram": self._ram,
- "nvram": self._nvram,
- "mmap": self._mmap,
- "sparsemem": self._sparsemem,
- "clock_divisor": self._clock_divisor,
- "idlepc": self._idlepc,
- "idlemax": self._idlemax,
- "idlesleep": self._idlesleep,
- "exec_area": self._exec_area,
- "jit_sharing_group": self._jit_sharing_group,
- "disk0": self._disk0,
- "disk1": self._disk1,
- "confreg": self._confreg,
- "console": self._console,
- "aux": self._aux,
- "mac_addr": self._mac_addr,
- "system_id": self._system_id}
-
- slot_id = 0
- for slot in self._slots:
- if slot:
- slot = str(slot)
- router_defaults["slot" + str(slot_id)] = slot
- slot_id += 1
-
- if self._slots[0] and self._slots[0].wics:
- for wic_slot_id in range(0, len(self._slots[0].wics)):
- router_defaults["wic" + str(wic_slot_id)] = None
-
- return router_defaults
-
- @property
- def id(self):
- """
- Returns the unique ID for this router.
-
- :returns: id (integer)
- """
-
- return self._id
-
- @property
- def name(self):
- """
- Returns the name of this router.
-
- :returns: name (string)
- """
-
- return self._name[1:-1] # remove quotes
-
- @name.setter
- def name(self, new_name):
- """
- Renames this router.
-
- :param new_name: new name string
- """
-
- if self._startup_config:
- # change the hostname in the startup-config
- startup_config_path = os.path.join(self.hypervisor.working_dir, "configs", "i{}_startup-config.cfg".format(self.id))
- if os.path.isfile(startup_config_path):
- try:
- with open(startup_config_path, "r+", errors="replace") as f:
- old_config = f.read()
- new_config = old_config.replace(self.name, new_name)
- f.seek(0)
- f.write(new_config)
- except OSError as e:
- raise DynamipsError("Could not amend the configuration {}: {}".format(startup_config_path, e))
-
- if self._private_config:
- # change the hostname in the private-config
- private_config_path = os.path.join(self.hypervisor.working_dir, "configs", "i{}_private-config.cfg".format(self.id))
- if os.path.isfile(private_config_path):
- try:
- with open(private_config_path, "r+", errors="replace") as f:
- old_config = f.read()
- new_config = old_config.replace(self.name, new_name)
- f.seek(0)
- f.write(new_config)
- except OSError as e:
- raise DynamipsError("Could not amend the configuration {}: {}".format(private_config_path, e))
-
- new_name = '"' + new_name + '"' # put the new name into quotes to protect spaces
- self._hypervisor.send("vm rename {name} {new_name}".format(name=self._name,
- new_name=new_name))
-
- log.info("router {name} [id={id}]: renamed to {new_name}".format(name=self._name,
- id=self._id,
- new_name=new_name))
- self._name = new_name
-
- @property
- def platform(self):
- """
- Returns the platform of this router.
-
- :returns: platform name (string):
- c7200, c3745, c3725, c3600, c2691, c2600 or c1700
- """
-
- return self._platform
-
- @property
- def hypervisor(self):
- """
- Returns the current hypervisor.
-
- :returns: hypervisor instance
- """
-
- return self._hypervisor
-
- def list(self):
- """
- Returns all VM instances
-
- :returns: list of all VM instances
- """
-
- return self._hypervisor.send("vm list")
-
- def list_con_ports(self):
- """
- Returns all VM console TCP ports
-
- :returns: list of port numbers
- """
-
- return self._hypervisor.send("vm list_con_ports")
-
- def delete(self):
- """
- Deletes this router.
- """
-
- self._hypervisor.send("vm delete {}".format(self._name))
- self._hypervisor.devices.remove(self)
- log.info("router {name} [id={id}] has been deleted".format(name=self._name, id=self._id))
- if self._id in self._instances:
- self._instances.remove(self._id)
- if self.console:
- self._allocated_console_ports.remove(self.console)
- if self.aux:
- self._allocated_aux_ports.remove(self.aux)
-
- def clean_delete(self):
- """
- Deletes this router & associated files (nvram, disks etc.)
- """
-
- self._hypervisor.send("vm clean_delete {}".format(self._name))
- self._hypervisor.devices.remove(self)
-
- if self._startup_config:
- # delete the startup-config
- startup_config_path = os.path.join(self.hypervisor.working_dir, "configs", "{}.cfg".format(self.name))
- if os.path.isfile(startup_config_path):
- os.remove(startup_config_path)
-
- if self._private_config:
- # delete the private-config
- private_config_path = os.path.join(self.hypervisor.working_dir, "configs", "{}-private.cfg".format(self.name))
- if os.path.isfile(private_config_path):
- os.remove(private_config_path)
-
- log.info("router {name} [id={id}] has been deleted (including associated files)".format(name=self._name, id=self._id))
- if self._id in self._instances:
- self._instances.remove(self._id)
- if self.console:
- self._allocated_console_ports.remove(self.console)
- if self.aux:
- self._allocated_aux_ports.remove(self.aux)
-
- def start(self):
- """
- Starts this router.
- At least the IOS image must be set before starting it.
- """
-
- status = self.get_status()
- if status == "suspended":
- self.resume()
- elif status == "inactive":
-
- if not os.path.isfile(self._image) or not os.path.exists(self._image):
- if os.path.islink(self._image):
- raise DynamipsError("IOS image '{}' linked to '{}' is not accessible".format(self._image, os.path.realpath(self._image)))
- else:
- raise DynamipsError("IOS image '{}' is not accessible".format(self._image))
-
- try:
- with open(self._image, "rb") as f:
- # read the first 7 bytes of the file.
- elf_header_start = f.read(7)
- except OSError as e:
- raise DynamipsError("Cannot read ELF header for IOS image {}: {}".format(self._image, e))
-
- # IOS images must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
- if elf_header_start != b'\x7fELF\x01\x02\x01':
- raise DynamipsError("'{}' is not a valid IOS image".format(self._image))
-
- self._hypervisor.send("vm start {}".format(self._name))
- log.info("router {name} [id={id}] has been started".format(name=self._name, id=self._id))
-
- def stop(self):
- """
- Stops this router.
- The settings are kept.
- """
-
- if self.get_status() != "inactive":
- self._hypervisor.send("vm stop {}".format(self._name))
- log.info("router {name} [id={id}] has been stopped".format(name=self._name, id=self._id))
-
- def suspend(self):
- """
- Suspends this router
- """
-
- if self.get_status() == "running":
- self._hypervisor.send("vm suspend {}".format(self._name))
- log.info("router {name} [id={id}] has been suspended".format(name=self._name, id=self._id))
-
- def resume(self):
- """
- Resumes this suspended router
- """
-
- self._hypervisor.send("vm resume {}".format(self._name))
- log.info("router {name} [id={id}] has been resumed".format(name=self._name, id=self._id))
-
- def get_status(self):
- """
- Returns the status of this router
-
- :returns: inactive, shutting down, running or suspended.
- """
-
- status_id = int(self._hypervisor.send("vm get_status {}".format(self._name))[0])
- return self._status[status_id]
-
- def is_running(self):
- """
- Checks if this router is running.
-
- :returns: True if running, False otherwise
- """
-
- if self.get_status() == "running":
- return True
- return False
-
- @property
- def jit_sharing_group(self):
- """
- Returns the JIT sharing group for this router.
-
- :returns: translation sharing group ID
- """
-
- return self._jit_sharing_group
-
- @jit_sharing_group.setter
- def jit_sharing_group(self, group_id):
- """
- Sets the translation sharing group (unstable).
-
- :param group_id: translation sharing group ID
- """
-
- if not self._image:
- raise DynamipsError("Register an IOS image fist")
-
- try:
- self._hypervisor.send("vm set_tsg {name} {group_id}".format(name=self._name,
- group_id=group_id))
- except DynamipsError:
- raise DynamipsError("JIT sharing is only supported in Dynamips >= 0.2.8-RC3 unstable")
-
- log.info("router {name} [id={id}]: set in JIT sharing group {group_id}".format(name=self._name,
- id=self._id,
- group_id=group_id))
-
- self._jit_sharing_group = group_id
- self._hypervisor.add_jitsharing_group(os.path.basename(self._image), group_id)
-
- def set_debug_level(self, level):
- """
- Sets the debug level for this router (default is 0).
-
- :param level: level number
- """
-
- self._hypervisor.send("vm set_debug_level {name} {level}".format(name=self._name,
- level=level))
-
- @property
- def image(self):
- """
- Returns this IOS image for this router.
-
- :returns: path to IOS image file
- """
-
- return self._image
-
- @image.setter
- def image(self, image):
- """
- Sets the IOS image for this router.
- There is no default.
-
- :param image: path to IOS image file
- """
-
- # encase image in quotes to protect spaces in the path
- self._hypervisor.send("vm set_ios {name} {image}".format(name=self._name,
- image='"' + image + '"'))
-
- log.info("router {name} [id={id}]: has a new IOS image set: {image}".format(name=self._name,
- id=self._id,
- image='"' + image + '"'))
-
- self._image = image
-
- @property
- def startup_config(self):
- """
- Returns the startup-config for this router.
-
- :returns: path to startup-config file
- """
-
- return self._startup_config
-
- @startup_config.setter
- def startup_config(self, startup_config):
- """
- Sets the startup-config for this router.
-
- :param startup_config: path to startup-config file
- """
-
- self._startup_config = startup_config
-
- @property
- def private_config(self):
- """
- Returns the private-config for this router.
-
- :returns: path to private-config file
- """
-
- return self._private_config
-
- @private_config.setter
- def private_config(self, private_config):
- """
- Sets the private-config for this router.
-
- :param private_config: path to private-config file
- """
-
- self._private_config = private_config
-
- def set_config(self, startup_config, private_config=''):
- """
- Sets the config files that are pushed to startup-config and
- private-config in NVRAM when the instance is started.
-
- :param startup_config: path to statup-config file
- :param private_config: path to private-config file
- (keep existing data when if an empty string)
- """
-
- if self._startup_config != startup_config or self._private_config != private_config:
-
- self._hypervisor.send("vm set_config {name} {startup} {private}".format(name=self._name,
- startup='"' + startup_config + '"',
- private='"' + private_config + '"'))
-
- log.info("router {name} [id={id}]: has a startup-config set: {startup}".format(name=self._name,
- id=self._id,
- startup='"' + startup_config + '"'))
-
- self._startup_config = startup_config
-
- if private_config:
- log.info("router {name} [id={id}]: has a private-config set: {private}".format(name=self._name,
- id=self._id,
- private='"' + private_config + '"'))
-
- self._private_config = private_config
-
- def extract_config(self):
- """
- Gets the contents of the config files
- startup-config and private-config from NVRAM.
-
- :returns: tuple (startup-config, private-config) base64 encoded
- """
-
- try:
- reply = self._hypervisor.send("vm extract_config {}".format(self._name))[0].rsplit(' ', 2)[-2:]
- except IOError:
- # for some reason Dynamips gets frozen when it does not find the magic number in the NVRAM file.
- return None, None
- startup_config = reply[0][1:-1] # get statup-config and remove single quotes
- private_config = reply[1][1:-1] # get private-config and remove single quotes
- return startup_config, private_config
-
- def push_config(self, startup_config, private_config='(keep)'):
- """
- Pushes configuration to the config files startup-config and private-config in NVRAM.
- The data is a Base64 encoded string, or '(keep)' to keep existing data.
-
- :param startup_config: statup-config string base64 encoded
- :param private_config: private-config string base64 encoded
- (keep existing data when if the value is ('keep'))
- """
-
- self._hypervisor.send("vm push_config {name} {startup} {private}".format(name=self._name,
- startup=startup_config,
- private=private_config))
-
- log.info("router {name} [id={id}]: new startup-config pushed".format(name=self._name,
- id=self._id))
-
- if private_config != '(keep)':
- log.info("router {name} [id={id}]: new private-config pushed".format(name=self._name,
- id=self._id))
-
- def save_configs(self):
- """
- Saves the startup-config and private-config to files.
- """
-
- if self.startup_config or self.private_config:
- startup_config_base64, private_config_base64 = self.extract_config()
- if startup_config_base64:
- try:
- config = base64.decodebytes(startup_config_base64.encode("utf-8")).decode("utf-8")
- config = "!\n" + config.replace("\r", "")
- config_path = os.path.join(self.hypervisor.working_dir, self.startup_config)
- with open(config_path, "w") as f:
- log.info("saving startup-config to {}".format(self.startup_config))
- f.write(config)
- except OSError as e:
- raise DynamipsError("Could not save the startup configuration {}: {}".format(config_path, e))
-
- if private_config_base64:
- try:
- config = base64.decodebytes(private_config_base64.encode("utf-8")).decode("utf-8")
- config = "!\n" + config.replace("\r", "")
- config_path = os.path.join(self.hypervisor.working_dir, self.private_config)
- with open(config_path, "w") as f:
- log.info("saving private-config to {}".format(self.private_config))
- f.write(config)
- except OSError as e:
- raise DynamipsError("Could not save the private configuration {}: {}".format(config_path, e))
-
- @property
- def ram(self):
- """
- Returns the amount of RAM allocated to this router.
-
- :returns: amount of RAM in Mbytes (integer)
- """
-
- return self._ram
-
- @ram.setter
- def ram(self, ram):
- """
- Sets amount of RAM allocated to this router
-
- :param ram: amount of RAM in Mbytes (integer)
- """
-
- if self._ram == ram:
- return
-
- self._hypervisor.send("vm set_ram {name} {ram}".format(name=self._name,
- ram=ram))
-
- log.info("router {name} [id={id}]: RAM updated from {old_ram}MB to {new_ram}MB".format(name=self._name,
- id=self._id,
- old_ram=self._ram,
- new_ram=ram))
-
- self._hypervisor.decrease_memory_load(self._ram)
- self._ram = ram
- self._hypervisor.increase_memory_load(ram)
-
- @property
- def nvram(self):
- """
- Returns the mount of NVRAM allocated to this router.
-
- :returns: amount of NVRAM in Kbytes (integer)
- """
-
- return self._nvram
-
- @nvram.setter
- def nvram(self, nvram):
- """
- Sets amount of NVRAM allocated to this router
-
- :param nvram: amount of NVRAM in Kbytes (integer)
- """
-
- if self._nvram == nvram:
- return
-
- self._hypervisor.send("vm set_nvram {name} {nvram}".format(name=self._name,
- nvram=nvram))
-
- log.info("router {name} [id={id}]: NVRAM updated from {old_nvram}KB to {new_nvram}KB".format(name=self._name,
- id=self._id,
- old_nvram=self._nvram,
- new_nvram=nvram))
- self._nvram = nvram
-
- @property
- def mmap(self):
- """
- Returns True if a mapped file is used to simulate this router memory.
-
- :returns: boolean either mmap is activated or not
- """
-
- return self._mmap
-
- @mmap.setter
- def mmap(self, mmap):
- """
- Enable/Disable use of a mapped file to simulate router memory.
- By default, a mapped file is used. This is a bit slower, but requires less memory.
-
- :param mmap: activate/deactivate mmap (boolean)
- """
-
- if mmap:
- flag = 1
- else:
- flag = 0
- self._hypervisor.send("vm set_ram_mmap {name} {mmap}".format(name=self._name,
- mmap=flag))
-
- if mmap:
- log.info("router {name} [id={id}]: mmap enabled".format(name=self._name,
- id=self._id))
- else:
- log.info("router {name} [id={id}]: mmap disabled".format(name=self._name,
- id=self._id))
- self._mmap = mmap
-
- @property
- def sparsemem(self):
- """
- Returns True if sparse memory is used on this router.
-
- :returns: boolean either mmap is activated or not
- """
-
- return self._sparsemem
-
- @sparsemem.setter
- def sparsemem(self, sparsemem):
- """
- Enable/disable use of sparse memory
-
- :param sparsemem: activate/deactivate sparsemem (boolean)
- """
-
- if sparsemem:
- flag = 1
- else:
- flag = 0
- self._hypervisor.send("vm set_sparse_mem {name} {sparsemem}".format(name=self._name,
- sparsemem=flag))
-
- if sparsemem:
- log.info("router {name} [id={id}]: sparse memory enabled".format(name=self._name,
- id=self._id))
- else:
- log.info("router {name} [id={id}]: sparse memory disabled".format(name=self._name,
- id=self._id))
- self._sparsemem = sparsemem
-
- @property
- def clock_divisor(self):
- """
- Returns the clock divisor value for this router.
-
- :returns: clock divisor value (integer)
- """
-
- return self._clock_divisor
-
- @clock_divisor.setter
- def clock_divisor(self, clock_divisor):
- """
- Sets the clock divisor value. The higher is the value, the faster is the clock in the
- virtual machine. The default is 4, but it is often required to adjust it.
-
- :param clock_divisor: clock divisor value (integer)
- """
-
- self._hypervisor.send("vm set_clock_divisor {name} {clock}".format(name=self._name,
- clock=clock_divisor))
-
- log.info("router {name} [id={id}]: clock divisor updated from {old_clock} to {new_clock}".format(name=self._name,
- id=self._id,
- old_clock=self._clock_divisor,
- new_clock=clock_divisor))
- self._clock_divisor = clock_divisor
-
- @property
- def idlepc(self):
- """
- Returns the idle Pointer Counter (PC).
-
- :returns: idlepc value (string)
- """
-
- return self._idlepc
-
- @idlepc.setter
- def idlepc(self, idlepc):
- """
- Sets the idle Pointer Counter (PC)
-
- :param idlepc: idlepc value (string)
- """
-
- if not idlepc:
- idlepc = "0x0"
-
- if not self.is_running():
- # router is not running
- self._hypervisor.send("vm set_idle_pc {name} {idlepc}".format(name=self._name,
- idlepc=idlepc))
- else:
- self._hypervisor.send("vm set_idle_pc_online {name} 0 {idlepc}".format(name=self._name,
- idlepc=idlepc))
-
- log.info("router {name} [id={id}]: idle-PC set to {idlepc}".format(name=self._name,
- id=self._id,
- idlepc=idlepc))
-
- self._idlepc = idlepc
-
- def get_idle_pc_prop(self):
- """
- Gets the idle PC proposals.
- Takes 1000 measurements and records up to 10 idle PC proposals.
- There is a 10ms wait between each measurement.
-
- :returns: list of idle PC proposal
- """
-
- if not self.is_running():
- # router is not running
- raise DynamipsError("router {name} is not running".format(name=self._name))
-
- log.info("router {name} [id={id}] has started calculating Idle-PC values".format(name=self._name, id=self._id))
- begin = time.time()
- idlepcs = self._hypervisor.send("vm get_idle_pc_prop {} 0".format(self._name))
- log.info("router {name} [id={id}] has finished calculating Idle-PC values after {time:.4f} seconds".format(name=self._name,
- id=self._id,
- time=time.time() - begin))
- return idlepcs
-
- def show_idle_pc_prop(self):
- """
- Dumps the idle PC proposals (previously generated).
-
- :returns: list of idle PC proposal
- """
-
- if not self.is_running():
- # router is not running
- raise DynamipsError("router {name} is not running".format(name=self._name))
-
- return self._hypervisor.send("vm show_idle_pc_prop {} 0".format(self._name))
-
- @property
- def idlemax(self):
- """
- Returns CPU idle max value.
-
- :returns: idle max (integer)
- """
-
- return self._idlemax
-
- @idlemax.setter
- def idlemax(self, idlemax):
- """
- Sets CPU idle max value
-
- :param idlemax: idle max value (integer)
- """
-
- if self.is_running(): # router is running
- self._hypervisor.send("vm set_idle_max {name} 0 {idlemax}".format(name=self._name,
- idlemax=idlemax))
-
- log.info("router {name} [id={id}]: idlemax updated from {old_idlemax} to {new_idlemax}".format(name=self._name,
- id=self._id,
- old_idlemax=self._idlemax,
- new_idlemax=idlemax))
-
- self._idlemax = idlemax
-
- @property
- def idlesleep(self):
- """
- Returns CPU idle sleep time value.
-
- :returns: idle sleep (integer)
- """
-
- return self._idlesleep
-
- @idlesleep.setter
- def idlesleep(self, idlesleep):
- """
- Sets CPU idle sleep time value.
-
- :param idlesleep: idle sleep value (integer)
- """
-
- if self.is_running(): # router is running
- self._hypervisor.send("vm set_idle_sleep_time {name} 0 {idlesleep}".format(name=self._name,
- idlesleep=idlesleep))
-
- log.info("router {name} [id={id}]: idlesleep updated from {old_idlesleep} to {new_idlesleep}".format(name=self._name,
- id=self._id,
- old_idlesleep=self._idlesleep,
- new_idlesleep=idlesleep))
-
- self._idlesleep = idlesleep
-
- def show_timer_drift(self):
- """
- Shows info about potential timer drift.
-
- :returns: timer drift info.
- """
-
- return self._hypervisor.send("vm show_timer_drift {} 0".format(self._name))
-
- @property
- def ghost_file(self):
- """
- Returns ghost RAM file.
-
- :returns: path to ghost file
- """
-
- return self._ghost_file
-
- @ghost_file.setter
- def ghost_file(self, ghost_file):
- """
- Sets ghost RAM file
-
- :ghost_file: path to ghost file
- """
-
- self._hypervisor.send("vm set_ghost_file {name} {ghost_file}".format(name=self._name,
- ghost_file=ghost_file))
-
- log.info("router {name} [id={id}]: ghost file set to {ghost_file}".format(name=self._name,
- id=self._id,
- ghost_file=ghost_file))
-
- self._ghost_file = ghost_file
-
- # if this is a ghost instance, track this as a hosted ghost instance by this hypervisor
- if self.ghost_status == 1:
- self._hypervisor.add_ghost(ghost_file, self)
-
- def formatted_ghost_file(self):
- """
- Returns a properly formatted ghost file name.
-
- :returns: formatted ghost_file name (string)
- """
-
- # replace specials characters in 'drive:\filename' in Linux and Dynamips in MS Windows or viceversa.
- ghost_file = "{}-{}.ghost".format(os.path.basename(self._image), self._ram)
- ghost_file = ghost_file.replace('\\', '-').replace('/', '-').replace(':', '-')
- return ghost_file
-
- @property
- def ghost_status(self):
- """Returns ghost RAM status
-
- :returns: ghost status (integer)
- """
-
- return self._ghost_status
-
- @ghost_status.setter
- def ghost_status(self, ghost_status):
- """
- Sets ghost RAM status
-
- :param ghost_status: state flag indicating status
- 0 => Do not use IOS ghosting
- 1 => This is a ghost instance
- 2 => Use an existing ghost instance
- """
-
- self._hypervisor.send("vm set_ghost_status {name} {ghost_status}".format(name=self._name,
- ghost_status=ghost_status))
-
- log.info("router {name} [id={id}]: ghost status set to {ghost_status}".format(name=self._name,
- id=self._id,
- ghost_status=ghost_status))
- self._ghost_status = ghost_status
-
- @property
- def exec_area(self):
- """
- Returns the exec area value.
-
- :returns: exec area value (integer)
- """
-
- return self._exec_area
-
- @exec_area.setter
- def exec_area(self, exec_area):
- """
- Sets the exec area value.
- The exec area is a pool of host memory used to store pages
- translated by the JIT (they contain the native code
- corresponding to MIPS code pages).
-
- :param exec_area: exec area value (integer)
- """
-
- self._hypervisor.send("vm set_exec_area {name} {exec_area}".format(name=self._name,
- exec_area=exec_area))
-
- log.info("router {name} [id={id}]: exec area updated from {old_exec}MB to {new_exec}MB".format(name=self._name,
- id=self._id,
- old_exec=self._exec_area,
- new_exec=exec_area))
- self._exec_area = exec_area
-
- @property
- def disk0(self):
- """
- Returns the size (MB) for PCMCIA disk0.
-
- :returns: disk0 size (integer)
- """
-
- return self._disk0
-
- @disk0.setter
- def disk0(self, disk0):
- """
- Sets the size (MB) for PCMCIA disk0.
-
- :param disk0: disk0 size (integer)
- """
-
- self._hypervisor.send("vm set_disk0 {name} {disk0}".format(name=self._name,
- disk0=disk0))
-
- log.info("router {name} [id={id}]: disk0 updated from {old_disk0}MB to {new_disk0}MB".format(name=self._name,
- id=self._id,
- old_disk0=self._disk0,
- new_disk0=disk0))
- self._disk0 = disk0
-
- @property
- def disk1(self):
- """
- Returns the size (MB) for PCMCIA disk1.
-
- :returns: disk1 size (integer)
- """
-
- return self._disk1
-
- @disk1.setter
- def disk1(self, disk1):
- """
- Sets the size (MB) for PCMCIA disk1.
-
- :param disk1: disk1 size (integer)
- """
-
- self._hypervisor.send("vm set_disk1 {name} {disk1}".format(name=self._name,
- disk1=disk1))
-
- log.info("router {name} [id={id}]: disk1 updated from {old_disk1}MB to {new_disk1}MB".format(name=self._name,
- id=self._id,
- old_disk1=self._disk1,
- new_disk1=disk1))
- self._disk1 = disk1
-
- @property
- def confreg(self):
- """
- Returns the configuration register.
- The default is 0x2102.
-
- :returns: configuration register value (string)
- """
-
- return self._confreg
-
- @confreg.setter
- def confreg(self, confreg):
- """
- Sets the configuration register.
-
- :param confreg: configuration register value (string)
- """
-
- self._hypervisor.send("vm set_conf_reg {name} {confreg}".format(name=self._name,
- confreg=confreg))
-
- log.info("router {name} [id={id}]: confreg updated from {old_confreg} to {new_confreg}".format(name=self._name,
- id=self._id,
- old_confreg=self._confreg,
- new_confreg=confreg))
- self._confreg = confreg
-
- @property
- def console(self):
- """
- Returns the TCP console port.
-
- :returns: console port (integer)
- """
-
- return self._console
-
- @console.setter
- def console(self, console):
- """
- Sets the TCP console port.
-
- :param console: console port (integer)
- """
-
- if console == self._console:
- return
-
- if console in self._allocated_console_ports:
- raise DynamipsError("Console port {} is already used by another router".format(console))
-
- self._hypervisor.send("vm set_con_tcp_port {name} {console}".format(name=self._name,
- console=console))
-
- log.info("router {name} [id={id}]: console port updated from {old_console} to {new_console}".format(name=self._name,
- id=self._id,
- old_console=self._console,
- new_console=console))
- self._allocated_console_ports.remove(self._console)
- self._console = console
- self._allocated_console_ports.append(self._console)
-
- @property
- def aux(self):
- """
- Returns the TCP auxiliary port.
-
- :returns: console auxiliary port (integer)
- """
-
- return self._aux
-
- @aux.setter
- def aux(self, aux):
- """
- Sets the TCP auxiliary port.
-
- :param aux: console auxiliary port (integer)
- """
-
- if aux == self._aux:
- return
-
- if aux in self._allocated_aux_ports:
- raise DynamipsError("Auxiliary console port {} is already used by another router".format(aux))
-
- self._hypervisor.send("vm set_aux_tcp_port {name} {aux}".format(name=self._name,
- aux=aux))
-
- log.info("router {name} [id={id}]: aux port updated from {old_aux} to {new_aux}".format(name=self._name,
- id=self._id,
- old_aux=self._aux,
- new_aux=aux))
-
- self._allocated_aux_ports.remove(self._aux)
- self._aux = aux
- self._allocated_aux_ports.append(self._aux)
-
- def get_cpu_info(self, cpu_id=0):
- """
- Shows info about the CPU identified by cpu_id.
- The boot CPU (which is typically the only CPU) has ID 0.
-
- :returns: ? (could not test)
- """
-
- # FIXME: nothing returned by Dynamips.
- return self._hypervisor.send("vm cpu_info {name} {cpu_id}".format(name=self._name,
- cpu_id=cpu_id))
-
- def get_cpu_usage(self, cpu_id=0):
- """
- Shows cpu usage in seconds, "cpu_id" is ignored.
-
- :returns: cpu usage in seconds
- """
-
- return int(self._hypervisor.send("vm cpu_usage {name} {cpu_id}".format(name=self._name,
- cpu_id=cpu_id))[0])
-
- def send_console_msg(self, message):
- """
- Sends a message to the console.
-
- :param message: message to send to the console
- """
-
- self._hypervisor.send("vm send_con_msg {name} {message}".format(name=self._name,
- message=message))
-
- def send_aux_msg(self, message):
- """
- Sends a message to the auxiliary console.
-
- :param message: message to send to the auxiliary console
- """
-
- self._hypervisor.send("vm send_aux_msg {name} {message}".format(name=self._name,
- message=message))
-
- @property
- def mac_addr(self):
- """
- Returns the MAC address.
-
- :returns: the MAC address (hexadecimal format: hh:hh:hh:hh:hh:hh)
- """
-
- return self._mac_addr
-
- @mac_addr.setter
- def mac_addr(self, mac_addr):
- """
- Sets the MAC address.
-
- :param mac_addr: a MAC address (hexadecimal format: hh:hh:hh:hh:hh:hh)
- """
-
- self._hypervisor.send("{platform} set_mac_addr {name} {mac_addr}".format(platform=self._platform,
- name=self._name,
- mac_addr=mac_addr))
-
- log.info("router {name} [id={id}]: MAC address updated from {old_mac} to {new_mac}".format(name=self._name,
- id=self._id,
- old_mac=self._mac_addr,
- new_mac=mac_addr))
- self._mac_addr = mac_addr
-
- @property
- def system_id(self):
- """
- Returns the system ID.
-
- :returns: the system ID (also called board processor ID)
- """
-
- return self._system_id
-
- @system_id.setter
- def system_id(self, system_id):
- """
- Sets the system ID.
-
- :param system_id: a system ID (also called board processor ID)
- """
-
- self._hypervisor.send("{platform} set_system_id {name} {system_id}".format(platform=self._platform,
- name=self._name,
- system_id=system_id))
-
- log.info("router {name} [id={id}]: system ID updated from {old_id} to {new_id}".format(name=self._name,
- id=self._id,
- old_id=self._system_id,
- new_id=system_id))
- self._system_id = system_id
-
- def get_hardware_info(self):
- """
- Get some hardware info about this router.
-
- :returns: ? (could not test)
- """
-
- # FIXME: nothing returned by Dynamips.
- return (self._hypervisor.send("{platform} show_hardware {name}".format(platform=self._platform,
- name=self._name)))
-
- def get_cpu_usage(self):
- """
- Returns the CPU usage.
-
- :return: CPU usage in percent
- """
-
- return int(self._hypervisor.send("vm cpu_usage {name} 0".format(name=self._name))[0])
-
- def get_slot_bindings(self):
- """
- Returns slot bindings.
-
- :returns: slot bindings (adapter names) list
- """
-
- return self._hypervisor.send("vm slot_bindings {}".format(self._name))
-
- def slot_add_binding(self, slot_id, adapter):
- """
- Adds a slot binding (a module into a slot).
-
- :param slot_id: slot ID
- :param adapter: device to add in the corresponding slot
- """
-
- try:
- slot = self._slots[slot_id]
- except IndexError:
- raise DynamipsError("Slot {slot_id} doesn't exist on router {name}".format(name=self._name,
- slot_id=slot_id))
-
- if slot is not None:
- current_adapter = slot
- raise DynamipsError("Slot {slot_id} is already occupied by adapter {adapter} on router {name}".format(name=self._name,
- slot_id=slot_id,
- adapter=current_adapter))
-
- # Only c7200, c3600 and c3745 (NM-4T only) support new adapter while running
- if self.is_running() and not ((self._platform == 'c7200' and not str(adapter).startswith('C7200'))
- and not (self._platform == 'c3600' and self.chassis == '3660')
- and not (self._platform == 'c3745' and adapter == 'NM-4T')):
- raise DynamipsError("Adapter {adapter} cannot be added while router {name} is running".format(adapter=adapter,
- name=self._name))
-
- self._hypervisor.send("vm slot_add_binding {name} {slot_id} 0 {adapter}".format(name=self._name,
- slot_id=slot_id,
- adapter=adapter))
-
- log.info("router {name} [id={id}]: adapter {adapter} inserted into slot {slot_id}".format(name=self._name,
- id=self._id,
- adapter=adapter,
- slot_id=slot_id))
-
- self._slots[slot_id] = adapter
-
- # Generate an OIR event if the router is running
- if self.is_running():
-
- self._hypervisor.send("vm slot_oir_start {name} {slot_id} 0".format(name=self._name,
- slot_id=slot_id))
-
- log.info("router {name} [id={id}]: OIR start event sent to slot {slot_id}".format(name=self._name,
- id=self._id,
- slot_id=slot_id))
-
- def slot_remove_binding(self, slot_id):
- """
- Removes a slot binding (a module from a slot).
-
- :param slot_id: slot ID
- """
-
- try:
- adapter = self._slots[slot_id]
- except IndexError:
- raise DynamipsError("Slot {slot_id} doesn't exist on router {name}".format(name=self._name,
- slot_id=slot_id))
-
- if adapter is None:
- raise DynamipsError("No adapter in slot {slot_id} on router {name}".format(name=self._name,
- slot_id=slot_id))
-
- # Only c7200, c3600 and c3745 (NM-4T only) support to remove adapter while running
- if self.is_running() and not ((self._platform == 'c7200' and not str(adapter).startswith('C7200'))
- and not (self._platform == 'c3600' and self.chassis == '3660')
- and not (self._platform == 'c3745' and adapter == 'NM-4T')):
- raise DynamipsError("Adapter {adapter} cannot be removed while router {name} is running".format(adapter=adapter,
- name=self._name))
-
- # Generate an OIR event if the router is running
- if self.is_running():
-
- self._hypervisor.send("vm slot_oir_stop {name} {slot_id} 0".format(name=self._name,
- slot_id=slot_id))
-
- log.info("router {name} [id={id}]: OIR stop event sent to slot {slot_id}".format(name=self._name,
- id=self._id,
- slot_id=slot_id))
-
- self._hypervisor.send("vm slot_remove_binding {name} {slot_id} 0".format(name=self._name,
- slot_id=slot_id))
-
- log.info("router {name} [id={id}]: adapter {adapter} removed from slot {slot_id}".format(name=self._name,
- id=self._id,
- adapter=adapter,
- slot_id=slot_id))
- self._slots[slot_id] = None
-
- def install_wic(self, wic_slot_id, wic):
- """
- Installs a WIC adapter into this router.
-
- :param wic_slot_id: WIC slot ID
- :param wic: WIC to be installed
- """
-
- # WICs are always installed on adapters in slot 0
- slot_id = 0
-
- # Do not check if slot has an adapter because adapters with WICs interfaces
- # must be inserted by default in the router and cannot be removed.
- adapter = self._slots[slot_id]
-
- if wic_slot_id > len(adapter.wics) - 1:
- raise DynamipsError("WIC slot {wic_slot_id} doesn't exist".format(name=self._name,
- wic_slot_id=wic_slot_id))
-
- if not adapter.wic_slot_available(wic_slot_id):
- raise DynamipsError("WIC slot {wic_slot_id} is already occupied by another WIC".format(name=self._name,
- wic_slot_id=wic_slot_id))
-
- # Dynamips WICs slot IDs start on a multiple of 16
- # WIC1 = 16, WIC2 = 32 and WIC3 = 48
- internal_wic_slot_id = 16 * (wic_slot_id + 1)
- self._hypervisor.send("vm slot_add_binding {name} {slot_id} {wic_slot_id} {wic}".format(name=self._name,
- slot_id=slot_id,
- wic_slot_id=internal_wic_slot_id,
- wic=wic))
-
- log.info("router {name} [id={id}]: {wic} inserted into WIC slot {wic_slot_id}".format(name=self._name,
- id=self._id,
- wic=wic,
- wic_slot_id=wic_slot_id))
-
- adapter.install_wic(wic_slot_id, wic)
-
- def uninstall_wic(self, wic_slot_id):
- """
- Uninstalls a WIC adapter from this router.
-
- :param wic_slot_id: WIC slot ID
- """
-
- # WICs are always installed on adapters in slot 0
- slot_id = 0
-
- # Do not check if slot has an adapter because adapters with WICs interfaces
- # must be inserted by default in the router and cannot be removed.
- adapter = self._slots[slot_id]
-
- if wic_slot_id > len(adapter.wics) - 1:
- raise DynamipsError("WIC slot {wic_slot_id} doesn't exist".format(name=self._name,
- wic_slot_id=wic_slot_id))
-
- if adapter.wic_slot_available(wic_slot_id):
- raise DynamipsError("No WIC is installed in WIC slot {wic_slot_id}".format(name=self._name,
- wic_slot_id=wic_slot_id))
- # Dynamips WICs slot IDs start on a multiple of 16
- # WIC1 = 16, WIC2 = 32 and WIC3 = 48
- internal_wic_slot_id = 16 * (wic_slot_id + 1)
- self._hypervisor.send("vm slot_remove_binding {name} {slot_id} {wic_slot_id}".format(name=self._name,
- slot_id=slot_id,
- wic_slot_id=internal_wic_slot_id))
-
- log.info("router {name} [id={id}]: {wic} removed from WIC slot {wic_slot_id}".format(name=self._name,
- id=self._id,
- wic=adapter.wics[wic_slot_id],
- wic_slot_id=wic_slot_id))
- adapter.uninstall_wic(wic_slot_id)
-
- def get_slot_nio_bindings(self, slot_id):
- """
- Returns slot NIO bindings.
-
- :param slot_id: slot ID
-
- :returns: list of NIO bindings
- """
-
- return (self._hypervisor.send("vm slot_nio_bindings {name} {slot_id}".format(name=self._name,
- slot_id=slot_id)))
-
- def slot_add_nio_binding(self, slot_id, port_id, nio):
- """
- Adds a slot NIO binding.
-
- :param slot_id: slot ID
- :param port_id: port ID
- :param nio: NIO instance to add to the slot/port
- """
-
- try:
- adapter = self._slots[slot_id]
- except IndexError:
- raise DynamipsError("Slot {slot_id} doesn't exist on router {name}".format(name=self._name,
- slot_id=slot_id))
- if not adapter.port_exists(port_id):
- raise DynamipsError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=adapter,
- port_id=port_id))
-
- self._hypervisor.send("vm slot_add_nio_binding {name} {slot_id} {port_id} {nio}".format(name=self._name,
- slot_id=slot_id,
- port_id=port_id,
- nio=nio))
-
- log.info("router {name} [id={id}]: NIO {nio_name} bound to port {slot_id}/{port_id}".format(name=self._name,
- id=self._id,
- nio_name=nio.name,
- slot_id=slot_id,
- port_id=port_id))
-
- self.slot_enable_nio(slot_id, port_id)
- adapter.add_nio(port_id, nio)
-
- def slot_remove_nio_binding(self, slot_id, port_id):
- """
- Removes a slot NIO binding.
-
- :param slot_id: slot ID
- :param port_id: port ID
-
- :returns: removed NIO instance
- """
-
- try:
- adapter = self._slots[slot_id]
- except IndexError:
- raise DynamipsError("Slot {slot_id} doesn't exist on router {name}".format(name=self._name,
- slot_id=slot_id))
- if not adapter.port_exists(port_id):
- raise DynamipsError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=adapter,
- port_id=port_id))
-
- self.slot_disable_nio(slot_id, port_id)
- self._hypervisor.send("vm slot_remove_nio_binding {name} {slot_id} {port_id}".format(name=self._name,
- slot_id=slot_id,
- port_id=port_id))
-
- nio = adapter.get_nio(port_id)
- adapter.remove_nio(port_id)
-
- log.info("router {name} [id={id}]: NIO {nio_name} removed from port {slot_id}/{port_id}".format(name=self._name,
- id=self._id,
- nio_name=nio.name,
- slot_id=slot_id,
- port_id=port_id))
-
- return nio
-
- def slot_enable_nio(self, slot_id, port_id):
- """
- Enables a slot NIO binding.
-
- :param slot_id: slot ID
- :param port_id: port ID
- """
-
- if self.is_running(): # running router
- self._hypervisor.send("vm slot_enable_nio {name} {slot_id} {port_id}".format(name=self._name,
- slot_id=slot_id,
- port_id=port_id))
-
- log.info("router {name} [id={id}]: NIO enabled on port {slot_id}/{port_id}".format(name=self._name,
- id=self._id,
- slot_id=slot_id,
- port_id=port_id))
-
- def slot_disable_nio(self, slot_id, port_id):
- """
- Disables a slot NIO binding.
-
- :param slot_id: slot ID
- :param port_id: port ID
- """
-
- if self.is_running(): # running router
- self._hypervisor.send("vm slot_disable_nio {name} {slot_id} {port_id}".format(name=self._name,
- slot_id=slot_id,
- port_id=port_id))
-
- log.info("router {name} [id={id}]: NIO disabled on port {slot_id}/{port_id}".format(name=self._name,
- id=self._id,
- slot_id=slot_id,
- port_id=port_id))
-
- def start_capture(self, slot_id, port_id, output_file, data_link_type="DLT_EN10MB"):
- """
- Starts a packet capture.
-
- :param slot_id: slot ID
- :param port_id: port ID
- :param output_file: PCAP destination file for the capture
- :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
- """
-
- try:
- adapter = self._slots[slot_id]
- except IndexError:
- raise DynamipsError("Slot {slot_id} doesn't exist on router {name}".format(name=self._name,
- slot_id=slot_id))
- if not adapter.port_exists(port_id):
- raise DynamipsError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=adapter,
- port_id=port_id))
-
- data_link_type = data_link_type.lower()
- if data_link_type.startswith("dlt_"):
- data_link_type = data_link_type[4:]
-
- nio = adapter.get_nio(port_id)
-
- if nio.input_filter[0] is not None and nio.output_filter[0] is not None:
- raise DynamipsError("Port {port_id} has already a filter applied on {adapter}".format(adapter=adapter,
- port_id=port_id))
-
- try:
- os.makedirs(os.path.dirname(output_file))
- except FileExistsError:
- pass
- except OSError as e:
- raise DynamipsError("Could not create captures directory {}".format(e))
-
- nio.bind_filter("both", "capture")
- nio.setup_filter("both", '{} "{}"'.format(data_link_type, output_file))
-
- log.info("router {name} [id={id}]: starting packet capture on port {slot_id}/{port_id}".format(name=self._name,
- id=self._id,
- nio_name=nio.name,
- slot_id=slot_id,
- port_id=port_id))
-
- def stop_capture(self, slot_id, port_id):
- """
- Stops a packet capture.
-
- :param slot_id: slot ID
- :param port_id: port ID
- """
-
- try:
- adapter = self._slots[slot_id]
- except IndexError:
- raise DynamipsError("Slot {slot_id} doesn't exist on router {name}".format(name=self._name,
- slot_id=slot_id))
- if not adapter.port_exists(port_id):
- raise DynamipsError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=adapter,
- port_id=port_id))
-
- nio = adapter.get_nio(port_id)
- nio.unbind_filter("both")
-
- log.info("router {name} [id={id}]: stopping packet capture on port {slot_id}/{port_id}".format(name=self._name,
- id=self._id,
- nio_name=nio.name,
- slot_id=slot_id,
- port_id=port_id))
-
- def _create_slots(self, numslots):
- """
- Creates the appropriate number of slots for this router.
-
- :param numslots: number of slots to create
- """
-
- self._slots = numslots * [None]
-
- @property
- def slots(self):
- """
- Returns the slots for this router.
-
- :return: slot list
- """
-
- return self._slots
diff --git a/gns3server/old_modules/dynamips/schemas/__init__.py b/gns3server/old_modules/dynamips/schemas/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/gns3server/old_modules/dynamips/schemas/atmsw.py b/gns3server/old_modules/dynamips/schemas/atmsw.py
deleted file mode 100644
index 37669478..00000000
--- a/gns3server/old_modules/dynamips/schemas/atmsw.py
+++ /dev/null
@@ -1,322 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-ATMSW_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new ATM switch instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "ATM switch name",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["name"]
-}
-
-ATMSW_DELETE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete an ATM switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "ATM switch instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-ATMSW_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update an ATM switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "ATM switch instance ID",
- "type": "integer"
- },
- "name": {
- "description": "ATM switch name",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-ATMSW_ALLOCATE_UDP_PORT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to allocate an UDP port for an ATM switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "ATM switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the ATM switch instance",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id"]
-}
-
-ATMSW_ADD_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to add a NIO for an ATM switch instance",
- "type": "object",
-
- "definitions": {
- "UDP": {
- "description": "UDP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_udp"]
- },
- "lport": {
- "description": "Local port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "rhost": {
- "description": "Remote host",
- "type": "string",
- "minLength": 1
- },
- "rport": {
- "description": "Remote port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "required": ["type", "lport", "rhost", "rport"],
- "additionalProperties": False
- },
- "Ethernet": {
- "description": "Generic Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_generic_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "LinuxEthernet": {
- "description": "Linux Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_linux_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "TAP": {
- "description": "TAP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_tap"]
- },
- "tap_device": {
- "description": "TAP device name e.g. tap0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "tap_device"],
- "additionalProperties": False
- },
- "UNIX": {
- "description": "UNIX Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_unix"]
- },
- "local_file": {
- "description": "path to the UNIX socket file (local)",
- "type": "string",
- "minLength": 1
- },
- "remote_file": {
- "description": "path to the UNIX socket file (remote)",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "local_file", "remote_file"],
- "additionalProperties": False
- },
- "VDE": {
- "description": "VDE Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_vde"]
- },
- "control_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- "local_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "control_file", "local_file"],
- "additionalProperties": False
- },
- "NULL": {
- "description": "NULL Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_null"]
- },
- },
- "required": ["type"],
- "additionalProperties": False
- },
- },
-
- "properties": {
- "id": {
- "description": "ATM switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the ATM switch instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- "mappings": {
- "type": "object",
- },
- "nio": {
- "type": "object",
- "description": "Network Input/Output",
- "oneOf": [
- {"$ref": "#/definitions/UDP"},
- {"$ref": "#/definitions/Ethernet"},
- {"$ref": "#/definitions/LinuxEthernet"},
- {"$ref": "#/definitions/TAP"},
- {"$ref": "#/definitions/UNIX"},
- {"$ref": "#/definitions/VDE"},
- {"$ref": "#/definitions/NULL"},
- ]
- },
- },
- "additionalProperties": False,
- "required": ["id", "port", "port_id", "mappings", "nio"],
-}
-
-ATMSW_DELETE_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete a NIO for an ATM switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "ATM switch instance ID",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port"]
-}
-
-ATMSW_START_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to start a packet capture on an ATM switch instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "ATM switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the ATM switch instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- "capture_file_name": {
- "description": "Capture file name",
- "type": "string",
- "minLength": 1,
- },
- "data_link_type": {
- "description": "PCAP data link type",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port", "capture_file_name"]
-}
-
-ATMSW_STOP_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to stop a packet capture on an ATM switch instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "ATM switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the ATM switch instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port"]
-}
diff --git a/gns3server/old_modules/dynamips/schemas/ethhub.py b/gns3server/old_modules/dynamips/schemas/ethhub.py
deleted file mode 100644
index 1002a696..00000000
--- a/gns3server/old_modules/dynamips/schemas/ethhub.py
+++ /dev/null
@@ -1,319 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-ETHHUB_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new Ethernet hub instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "Ethernet hub name",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["name"]
-}
-
-ETHHUB_DELETE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete an Ethernet hub instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet hub instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-ETHHUB_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update an Ethernet hub instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet hub instance ID",
- "type": "integer"
- },
- "name": {
- "description": "Ethernet hub name",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-ETHHUB_ALLOCATE_UDP_PORT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to allocate an UDP port for an Ethernet hub instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet hub instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Ethernet hub instance",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id"]
-}
-
-ETHHUB_ADD_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to add a NIO for an Ethernet hub instance",
- "type": "object",
-
- "definitions": {
- "UDP": {
- "description": "UDP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_udp"]
- },
- "lport": {
- "description": "Local port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "rhost": {
- "description": "Remote host",
- "type": "string",
- "minLength": 1
- },
- "rport": {
- "description": "Remote port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "required": ["type", "lport", "rhost", "rport"],
- "additionalProperties": False
- },
- "Ethernet": {
- "description": "Generic Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_generic_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "LinuxEthernet": {
- "description": "Linux Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_linux_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "TAP": {
- "description": "TAP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_tap"]
- },
- "tap_device": {
- "description": "TAP device name e.g. tap0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "tap_device"],
- "additionalProperties": False
- },
- "UNIX": {
- "description": "UNIX Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_unix"]
- },
- "local_file": {
- "description": "path to the UNIX socket file (local)",
- "type": "string",
- "minLength": 1
- },
- "remote_file": {
- "description": "path to the UNIX socket file (remote)",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "local_file", "remote_file"],
- "additionalProperties": False
- },
- "VDE": {
- "description": "VDE Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_vde"]
- },
- "control_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- "local_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "control_file", "local_file"],
- "additionalProperties": False
- },
- "NULL": {
- "description": "NULL Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_null"]
- },
- },
- "required": ["type"],
- "additionalProperties": False
- },
- },
-
- "properties": {
- "id": {
- "description": "Ethernet hub instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Ethernet hub instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- "nio": {
- "type": "object",
- "description": "Network Input/Output",
- "oneOf": [
- {"$ref": "#/definitions/UDP"},
- {"$ref": "#/definitions/Ethernet"},
- {"$ref": "#/definitions/LinuxEthernet"},
- {"$ref": "#/definitions/TAP"},
- {"$ref": "#/definitions/UNIX"},
- {"$ref": "#/definitions/VDE"},
- {"$ref": "#/definitions/NULL"},
- ]
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port", "nio"]
-}
-
-ETHHUB_DELETE_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete a NIO for an Ethernet hub instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet hub instance ID",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port"]
-}
-
-ETHHUB_START_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to start a packet capture on an Ethernet hub instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet hub instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Ethernet hub instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- "capture_file_name": {
- "description": "Capture file name",
- "type": "string",
- "minLength": 1,
- },
- "data_link_type": {
- "description": "PCAP data link type",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port", "capture_file_name"]
-}
-
-ETHHUB_STOP_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to stop a packet capture on an Ethernet hub instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet hub instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Ethernet hub instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port"]
-}
diff --git a/gns3server/old_modules/dynamips/schemas/ethsw.py b/gns3server/old_modules/dynamips/schemas/ethsw.py
deleted file mode 100644
index 33559f28..00000000
--- a/gns3server/old_modules/dynamips/schemas/ethsw.py
+++ /dev/null
@@ -1,348 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-ETHSW_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new Ethernet switch instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "Ethernet switch name",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["name"]
-}
-
-ETHSW_DELETE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete an Ethernet switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet switch instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-# TODO: ports {'1': {'vlan': 1, 'type': 'qinq'}
-ETHSW_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update an Ethernet switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet switch instance ID",
- "type": "integer"
- },
- "name": {
- "description": "Ethernet switch name",
- "type": "string",
- "minLength": 1,
- },
- # "ports": {
- # "type": "object",
- # "properties": {
- # "type": {
- # "description": "Port type",
- # "enum": ["access", "dot1q", "qinq"],
- # },
- # "vlan": {
- # "description": "VLAN number",
- # "type": "integer",
- # "minimum": 1
- # },
- # },
- # },
- },
- #"additionalProperties": False,
- "required": ["id"]
-}
-
-ETHSW_ALLOCATE_UDP_PORT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to allocate an UDP port for an Ethernet switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Ethernet switch instance",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id"]
-}
-
-ETHSW_ADD_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to add a NIO for an Ethernet switch instance",
- "type": "object",
-
- "definitions": {
- "UDP": {
- "description": "UDP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_udp"]
- },
- "lport": {
- "description": "Local port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "rhost": {
- "description": "Remote host",
- "type": "string",
- "minLength": 1
- },
- "rport": {
- "description": "Remote port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "required": ["type", "lport", "rhost", "rport"],
- "additionalProperties": False
- },
- "Ethernet": {
- "description": "Generic Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_generic_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "LinuxEthernet": {
- "description": "Linux Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_linux_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "TAP": {
- "description": "TAP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_tap"]
- },
- "tap_device": {
- "description": "TAP device name e.g. tap0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "tap_device"],
- "additionalProperties": False
- },
- "UNIX": {
- "description": "UNIX Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_unix"]
- },
- "local_file": {
- "description": "path to the UNIX socket file (local)",
- "type": "string",
- "minLength": 1
- },
- "remote_file": {
- "description": "path to the UNIX socket file (remote)",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "local_file", "remote_file"],
- "additionalProperties": False
- },
- "VDE": {
- "description": "VDE Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_vde"]
- },
- "control_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- "local_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "control_file", "local_file"],
- "additionalProperties": False
- },
- "NULL": {
- "description": "NULL Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_null"]
- },
- },
- "required": ["type"],
- "additionalProperties": False
- },
- },
-
- "properties": {
- "id": {
- "description": "Ethernet switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Ethernet switch instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- "port_type": {
- "description": "Port type",
- "enum": ["access", "dot1q", "qinq"],
- },
- "vlan": {
- "description": "VLAN number",
- "type": "integer",
- "minimum": 1
- },
- "nio": {
- "type": "object",
- "description": "Network Input/Output",
- "oneOf": [
- {"$ref": "#/definitions/UDP"},
- {"$ref": "#/definitions/Ethernet"},
- {"$ref": "#/definitions/LinuxEthernet"},
- {"$ref": "#/definitions/TAP"},
- {"$ref": "#/definitions/UNIX"},
- {"$ref": "#/definitions/VDE"},
- {"$ref": "#/definitions/NULL"},
- ]
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port", "port_type", "vlan", "nio"],
-
- "dependencies": {
- "port_type": ["vlan"],
- "vlan": ["port_type"]
- }
-}
-
-ETHSW_DELETE_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete a NIO for an Ethernet switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet switch instance ID",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port"]
-}
-
-ETHSW_START_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to start a packet capture on an Ethernet switch instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Ethernet switch instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- "capture_file_name": {
- "description": "Capture file name",
- "type": "string",
- "minLength": 1,
- },
- "data_link_type": {
- "description": "PCAP data link type",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port", "capture_file_name"]
-}
-
-ETHSW_STOP_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to stop a packet capture on an Ethernet switch instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "Ethernet switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Ethernet switch instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port"]
-}
diff --git a/gns3server/old_modules/dynamips/schemas/frsw.py b/gns3server/old_modules/dynamips/schemas/frsw.py
deleted file mode 100644
index 835e47a7..00000000
--- a/gns3server/old_modules/dynamips/schemas/frsw.py
+++ /dev/null
@@ -1,322 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-FRSW_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new Frame relay switch instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "Frame relay switch name",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["name"]
-}
-
-FRSW_DELETE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete a Frame relay switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Frame relay switch instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-FRSW_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update a Frame relay switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Frame relay switch instance ID",
- "type": "integer"
- },
- "name": {
- "description": "Frame relay switch name",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-FRSW_ALLOCATE_UDP_PORT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to allocate an UDP port for a Frame relay switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Frame relay switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Frame relay switch instance",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id"]
-}
-
-FRSW_ADD_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to add a NIO for a Frame relay switch instance",
- "type": "object",
-
- "definitions": {
- "UDP": {
- "description": "UDP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_udp"]
- },
- "lport": {
- "description": "Local port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "rhost": {
- "description": "Remote host",
- "type": "string",
- "minLength": 1
- },
- "rport": {
- "description": "Remote port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "required": ["type", "lport", "rhost", "rport"],
- "additionalProperties": False
- },
- "Ethernet": {
- "description": "Generic Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_generic_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "LinuxEthernet": {
- "description": "Linux Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_linux_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "TAP": {
- "description": "TAP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_tap"]
- },
- "tap_device": {
- "description": "TAP device name e.g. tap0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "tap_device"],
- "additionalProperties": False
- },
- "UNIX": {
- "description": "UNIX Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_unix"]
- },
- "local_file": {
- "description": "path to the UNIX socket file (local)",
- "type": "string",
- "minLength": 1
- },
- "remote_file": {
- "description": "path to the UNIX socket file (remote)",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "local_file", "remote_file"],
- "additionalProperties": False
- },
- "VDE": {
- "description": "VDE Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_vde"]
- },
- "control_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- "local_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "control_file", "local_file"],
- "additionalProperties": False
- },
- "NULL": {
- "description": "NULL Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_null"]
- },
- },
- "required": ["type"],
- "additionalProperties": False
- },
- },
-
- "properties": {
- "id": {
- "description": "Frame relay switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Frame relay switch instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- "mappings": {
- "type": "object",
- },
- "nio": {
- "type": "object",
- "description": "Network Input/Output",
- "oneOf": [
- {"$ref": "#/definitions/UDP"},
- {"$ref": "#/definitions/Ethernet"},
- {"$ref": "#/definitions/LinuxEthernet"},
- {"$ref": "#/definitions/TAP"},
- {"$ref": "#/definitions/UNIX"},
- {"$ref": "#/definitions/VDE"},
- {"$ref": "#/definitions/NULL"},
- ]
- },
- },
- "additionalProperties": False,
- "required": ["id", "port", "port_id", "mappings", "nio"],
-}
-
-FRSW_DELETE_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete a NIO for a Frame relay switch instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "Frame relay switch instance ID",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port"]
-}
-
-FRSW_START_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to start a packet capture on a Frame relay switch instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "Frame relay switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Frame relay instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- "capture_file_name": {
- "description": "Capture file name",
- "type": "string",
- "minLength": 1,
- },
- "data_link_type": {
- "description": "PCAP data link type",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port", "capture_file_name"]
-}
-
-FRSW_STOP_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to stop a packet capture on a Frame relay switch instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "Frame relay switch instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the Frame relay instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port"]
-}
diff --git a/gns3server/old_modules/dynamips/schemas/vm.py b/gns3server/old_modules/dynamips/schemas/vm.py
deleted file mode 100644
index adb380e4..00000000
--- a/gns3server/old_modules/dynamips/schemas/vm.py
+++ /dev/null
@@ -1,719 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 GNS3 Technologies Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-VM_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new VM instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "Router name",
- "type": "string",
- "minLength": 1,
- },
- "router_id": {
- "description": "VM/router instance ID",
- "type": "integer"
- },
- "platform": {
- "description": "router platform",
- "type": "string",
- "minLength": 1,
- "pattern": "^c[0-9]{4}$"
- },
- "chassis": {
- "description": "router chassis model",
- "type": "string",
- "minLength": 1,
- "pattern": "^[0-9]{4}(XM)?$"
- },
- "image": {
- "description": "path to the IOS image file",
- "type": "string",
- "minLength": 1
- },
- "ram": {
- "description": "amount of RAM in MB",
- "type": "integer"
- },
- "console": {
- "description": "console TCP port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "aux": {
- "description": "auxiliary console TCP port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "mac_addr": {
- "description": "base MAC address",
- "type": "string",
- "minLength": 1,
- "pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$"
- },
- "cloud_path": {
- "description": "Path to the image in the cloud object store",
- "type": "string",
- }
- },
- "additionalProperties": False,
- "required": ["name", "platform", "image", "ram"]
-}
-
-VM_DELETE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete a VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VM_START_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to start a VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VM_STOP_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to stop a VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VM_SUSPEND_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to suspend a VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VM_RELOAD_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to reload a VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-# TODO: improve platform specific properties (dependencies?)
-VM_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update a VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- "name": {
- "description": "Router name",
- "type": "string",
- "minLength": 1,
- },
- "platform": {
- "description": "platform",
- "type": "string",
- "minLength": 1,
- "pattern": "^c[0-9]{4}$"
- },
- "image": {
- "description": "path to the IOS image",
- "type": "string",
- "minLength": 1,
- },
- "startup_config": {
- "description": "path to the IOS startup configuration file",
- "type": "string",
- "minLength": 1,
- },
- "private_config": {
- "description": "path to the IOS private configuration file",
- "type": "string",
- "minLength": 1,
- },
- "ram": {
- "description": "amount of RAM in MB",
- "type": "integer"
- },
- "nvram": {
- "description": "amount of NVRAM in KB",
- "type": "integer"
- },
- "mmap": {
- "description": "MMAP feature",
- "type": "boolean"
- },
- "sparsemem": {
- "description": "sparse memory feature",
- "type": "boolean"
- },
- "clock_divisor": {
- "description": "clock divisor",
- "type": "integer"
- },
- "idlepc": {
- "description": "Idle-PC value",
- "type": "string",
- "pattern": "^(0x[0-9a-fA-F]+)?$"
- },
- "idlemax": {
- "description": "idlemax value",
- "type": "integer",
- },
- "idlesleep": {
- "description": "idlesleep value",
- "type": "integer",
- },
- "exec_area": {
- "description": "exec area value",
- "type": "integer",
- },
- "jit_sharing_group": {
- "description": "JIT sharing group",
- "type": "integer",
- },
- "disk0": {
- "description": "disk0 size in MB",
- "type": "integer"
- },
- "disk1": {
- "description": "disk1 size in MB",
- "type": "integer"
- },
- "confreg": {
- "description": "configuration register",
- "type": "string",
- "minLength": 1,
- "pattern": "^0x[0-9a-fA-F]{4}$"
- },
- "console": {
- "description": "console TCP port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "aux": {
- "description": "auxiliary console TCP port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "mac_addr": {
- "description": "base MAC address",
- "type": "string",
- "minLength": 1,
- "pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$"
- },
- "system_id": {
- "description": "system ID",
- "type": "string",
- "minLength": 1,
- },
- "slot0": {
- "description": "Network module slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot1": {
- "description": "Network module slot 1",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot2": {
- "description": "Network module slot 2",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot3": {
- "description": "Network module slot 3",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot4": {
- "description": "Network module slot 4",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot5": {
- "description": "Network module slot 5",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "slot6": {
- "description": "Network module slot 6",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic0": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic1": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "wic2": {
- "description": "Network module WIC slot 0",
- "oneOf": [
- {"type": "string"},
- {"type": "null"}
- ]
- },
- "startup_config_base64": {
- "description": "startup configuration base64 encoded",
- "type": "string"
- },
- "private_config_base64": {
- "description": "private configuration base64 encoded",
- "type": "string"
- },
- # C7200 properties
- "npe": {
- "description": "NPE model",
- "enum": ["npe-100",
- "npe-150",
- "npe-175",
- "npe-200",
- "npe-225",
- "npe-300",
- "npe-400",
- "npe-g2"]
- },
- "midplane": {
- "description": "Midplane model",
- "enum": ["std", "vxr"]
- },
- "sensors": {
- "description": "Temperature sensors",
- "type": "array"
- },
- "power_supplies": {
- "description": "Power supplies status",
- "type": "array"
- },
- # I/O memory property for all platforms but C7200
- "iomem": {
- "description": "I/O memory percentage",
- "type": "integer",
- "minimum": 0,
- "maximum": 100
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VM_START_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to start a packet capture on a VM instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the VM instance",
- "type": "integer"
- },
- "slot": {
- "description": "Slot number",
- "type": "integer",
- "minimum": 0,
- "maximum": 6
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 0,
- "maximum": 49 # maximum is 16 for regular port numbers, WICs port numbers start at 16, 32 or 48
- },
- "capture_file_name": {
- "description": "Capture file name",
- "type": "string",
- "minLength": 1,
- },
- "data_link_type": {
- "description": "PCAP data link type",
- "type": "string",
- "minLength": 1,
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "slot", "port", "capture_file_name"]
-}
-
-VM_STOP_CAPTURE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to stop a packet capture on a VM instance port",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the VM instance",
- "type": "integer"
- },
- "slot": {
- "description": "Slot number",
- "type": "integer",
- "minimum": 0,
- "maximum": 6
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 0,
- "maximum": 49 # maximum is 16 for regular port numbers, WICs port numbers start at 16, 32 or 48
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "slot", "port"]
-}
-
-VM_SAVE_CONFIG_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to save the configs for VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VM_EXPORT_CONFIG_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to export the configs for VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VM_IDLEPCS_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to calculate or show Idle-PCs for VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- "compute": {
- "description": "indicates to compute new Idle-PC values",
- "type": "boolean"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VM_AUTO_IDLEPC_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request an auto Idle-PC calculation for this VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VM_ALLOCATE_UDP_PORT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to allocate an UDP port for a VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the VM instance",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id"]
-}
-
-VM_ADD_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to add a NIO for a VM instance",
- "type": "object",
-
- "definitions": {
- "UDP": {
- "description": "UDP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_udp"]
- },
- "lport": {
- "description": "Local port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "rhost": {
- "description": "Remote host",
- "type": "string",
- "minLength": 1
- },
- "rport": {
- "description": "Remote port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "required": ["type", "lport", "rhost", "rport"],
- "additionalProperties": False
- },
- "Ethernet": {
- "description": "Generic Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_generic_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "LinuxEthernet": {
- "description": "Linux Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_linux_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "TAP": {
- "description": "TAP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_tap"]
- },
- "tap_device": {
- "description": "TAP device name e.g. tap0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "tap_device"],
- "additionalProperties": False
- },
- "UNIX": {
- "description": "UNIX Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_unix"]
- },
- "local_file": {
- "description": "path to the UNIX socket file (local)",
- "type": "string",
- "minLength": 1
- },
- "remote_file": {
- "description": "path to the UNIX socket file (remote)",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "local_file", "remote_file"],
- "additionalProperties": False
- },
- "VDE": {
- "description": "VDE Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_vde"]
- },
- "control_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- "local_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "control_file", "local_file"],
- "additionalProperties": False
- },
- "NULL": {
- "description": "NULL Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_null"]
- },
- },
- "required": ["type"],
- "additionalProperties": False
- },
- },
-
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the VM instance",
- "type": "integer"
- },
- "slot": {
- "description": "Slot number",
- "type": "integer",
- "minimum": 0,
- "maximum": 6
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 0,
- "maximum": 49 # maximum is 16 for regular port numbers, WICs port numbers start at 16, 32 or 48
- },
- "nio": {
- "type": "object",
- "description": "Network Input/Output",
- "oneOf": [
- {"$ref": "#/definitions/UDP"},
- {"$ref": "#/definitions/Ethernet"},
- {"$ref": "#/definitions/LinuxEthernet"},
- {"$ref": "#/definitions/TAP"},
- {"$ref": "#/definitions/UNIX"},
- {"$ref": "#/definitions/VDE"},
- {"$ref": "#/definitions/NULL"},
- ]
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "slot", "port", "nio"]
-}
-
-VM_DELETE_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete a NIO for a VM instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VM instance ID",
- "type": "integer"
- },
- "slot": {
- "description": "Slot number",
- "type": "integer",
- "minimum": 0,
- "maximum": 6
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 0,
- "maximum": 49 # maximum is 16 for regular port numbers, WICs port numbers start at 16, 32 or 48
- },
- },
- "additionalProperties": False,
- "required": ["id", "slot", "port"]
-}
diff --git a/gns3server/schemas/dynamips.py b/gns3server/schemas/dynamips.py
new file mode 100644
index 00000000..a707d0cc
--- /dev/null
+++ b/gns3server/schemas/dynamips.py
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2014 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+ROUTER_CREATE_SCHEMA = {
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "description": "Request validation to create a new Dynamips router instance",
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Router name",
+ "type": "string",
+ "minLength": 1,
+ },
+ "router_id": {
+ "description": "VM/router instance ID",
+ "type": "integer"
+ },
+ "platform": {
+ "description": "router platform",
+ "type": "string",
+ "minLength": 1,
+ "pattern": "^c[0-9]{4}$"
+ },
+ "chassis": {
+ "description": "router chassis model",
+ "type": "string",
+ "minLength": 1,
+ "pattern": "^[0-9]{4}(XM)?$"
+ },
+ "image": {
+ "description": "path to the IOS image file",
+ "type": "string",
+ "minLength": 1
+ },
+ "ram": {
+ "description": "amount of RAM in MB",
+ "type": "integer"
+ },
+ "console": {
+ "description": "console TCP port",
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 65535
+ },
+ "aux": {
+ "description": "auxiliary console TCP port",
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 65535
+ },
+ "mac_addr": {
+ "description": "base MAC address",
+ "type": "string",
+ "minLength": 1,
+ "pattern": "^([0-9a-fA-F]{4}\\.){2}[0-9a-fA-F]{4}$"
+ },
+ "cloud_path": {
+ "description": "Path to the image in the cloud object store",
+ "type": "string",
+ }
+ },
+ "additionalProperties": False,
+ "required": ["name", "platform", "image", "ram"]
+}
+
+ROUTER_OBJECT_SCHEMA = {
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "description": "Dynamips router instance",
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "Dynamips router instance name",
+ "type": "string",
+ "minLength": 1,
+ },
+ "vm_id": {
+ "description": "Dynamips router instance UUID",
+ "type": "string",
+ "minLength": 36,
+ "maxLength": 36,
+ "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
+ },
+ "project_id": {
+ "description": "Project UUID",
+ "type": "string",
+ "minLength": 36,
+ "maxLength": 36,
+ "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
+ },
+ },
+ "additionalProperties": False,
+ "required": ["name", "vm_id", "project_id"]
+}